Android 自定义Gradle插件(八):检查Manifest中的权限

语言: CN / TW / HK

最近公司上到Google Play的App收到了通知,需要对QUERY_ALL_PACKAGES权限进行处理,如果确实需要使用该权限,需要提交声明表单,无需使用则要在Manifest中移除该权限。

1652505389(1).png

第一时间检查了App主项目中的清单文件,没有发现该权限,所以这个权限是来自三方SDK,接入的三方SDK比较多,一个个去看有点麻烦。想到了可以使用自定义Gradle插件来解决,下面介绍一下如何实现。

1. 向插件传入需检查的权限

自定义extensions用于从主项目向插件传入需要检测的权限,代码如下:

``` //Extension类 class PermissionExtension { ArrayList checkPermissions }

class MiniGamePermissionPlugin implements Plugin {

@Override
void apply(Project project) {
    //注册Extension类
    def permissionExtension = project.extensions.create("CheckPermissionExtension", PermissionExtension)

    project.afterEvaluate {
        //获取传入的需检查的权限
        permissionExtension.checkPermissions
    }
}

} ```

2. 自定义检查Manifest权限的Task

自定义的Task代码如下:

``` class CheckPermissionEntity {

def permissionName = ""

def hasPermission = false

}

class CheckPermissionTask extends DefaultTask {

private static def manifestCollection
private static def checkPermissions = new ArrayList<CheckPermissionEntity>()
private static def android = new Namespace("http://schemas.android.com/apk/res/android", "android")

@TaskAction
void doTaskAction() {
    manifestCollection.each {
        handlerVariantManifestFile(it)
    }
}

static void setData(FileCollection collection, ArrayList<String> checkPermissions) {
    manifestCollection = collection
    this.checkPermissions.clear()
    checkPermissions.each {
        def entity = new CheckPermissionEntity()
        entity.permissionName = it
        entity.hasPermission = false
        this.checkPermissions.add(entity)
    }
}

static void handlerVariantManifestFile(File manifestFile) {
    if (!manifestFile.exists()) {
        LogUtils.println("manifestFile do not exists")
        return
    }

    //每个Manifest读取前先把是否有权限置为false
    checkPermissions.each {
        it.hasPermission = false
    }

    try {
        XmlParser xmlParser = new XmlParser()
        def node = xmlParser.parse(manifestFile)
        //获取user-permission标签
        NodeList nodeList = node.get("uses-permission")
        if (!nodeList.isEmpty()) {
            checkPermissions.each {
                nodeList.find { permissionNode ->
                    def permissionName = permissionNode.attributes()[android.get("name")]
                    if (permissionName == it.permissionName) {
                        it.hasPermission = true
                    }
                    return it.hasPermission
                }
            }
        }
        def hasOnePermissionAtLeast = false
        def result = node.attributes()["package"] + " contains permission "
        checkPermissions.each {
            if (it.hasPermission) {
                if (!hasOnePermissionAtLeast) {
                    hasOnePermissionAtLeast = true
                }
                result = result + it.permissionName + (checkPermissions.indexOf(it) == checkPermissions.size() - 1 ? "." : ",")
            }
        }
        //至少包含一个权限,则输出日志
        if (hasOnePermissionAtLeast) {
            LogUtils.println(result)
        }
    } catch (ParserConfigurationException e) {
        e.printStackTrace()
    } catch (SAXException e) {
        e.printStackTrace()
    } catch (IOException e) {
        e.printStackTrace()
    }
}

} ```

3. 添加自定义Task

代码如下:

``` class MiniGamePermissionPlugin implements Plugin {

static def variantNames = new ArrayList()

@Override
void apply(Project project) {
    def permissionExtension = project.extensions.create("CheckPermissionExtension", PermissionExtension)
    def appExtension = project.extensions.findByType(AppExtension.class)

    project.afterEvaluate {
        appExtension.getApplicationVariants().findAll {
            if (!variantNames.contains(it.name)) {
                variantNames.add(it.name)
            }
        }

        variantNames.each {
            //创建Task,并设置分组
            CheckPermissionTask checkPermissionTask = project.getTasks().create(String.format("MiniGameCheck%sPermissionTask", it.capitalize()), CheckPermissionTask)
            checkPermissionTask.group = "MiniGameCheckPermission"
            setCheckPermissionTaskData(project, checkPermissionTask, it.capitalize(), permissionExtension.checkPermissions)
        }
    }
}

private static void setCheckPermissionTaskData(Project project, CheckPermissionTask checkPermissionTask, String name, ArrayList<String> checkPermissions) {
    try {
        //找到处理Manifest的Task
        ProcessApplicationManifest processManifestTask = project.getTasks().getByName(String.format("process%sMainManifest", name))
        //设置Manifest文件和需要检查的权限集合
        checkPermissionTask.setData(processManifestTask.getManifests(), checkPermissions)
    } catch (Exception e) {
        e.printStackTrace()
    }
}

} ```

接入插件

在项⽬下的build.gradle中添加如下代码:

``` buildscript {

repositories {
    maven {
        allowInsecureProtocol(true)
        url 'http://101.43.13.248:8081/repository/sdk-aggregation/' 
    }


dependencies {
    classpath("com.minigame.minicloud:checkpermission-g65-debug:1.0.1.14-SNAPSHOT")
}

} ``` 在app module下的build.gradle中添加如下代码:

``` plugins { id("minigame-permission-plugin") }

//要检测的权限 CheckPermissionExtension { checkPermissions = [ "android.permission.ACCESS_NETWORK_STATE", "android.permission.ACCESS_WIFI_STATE", "com.google.android.gms.permission.AD_ID" ] } ```

接入插件构建后,可以在Gradle中看到自定义的Task。

1652509603.png

执行Task之后,可以在AndroidStudio底部的Build或者Run中看到日志。

1652510900(1).png