最近公司上到Google Play的App收到了通知,需要对QUERY_ALL_PACKAGES权限进行处理,如果确实需要使用该权限,需要提交声明表单,无需使用则要在Manifest中移除该权限。
第一时间检查了App主项目中的清单文件,没有发现该权限,所以这个权限是来自三方SDK,接入的三方SDK比较多,一个个去看有点麻烦。想到了可以使用自定义Gradle插件来解决,下面介绍一下如何实现。
1. 向插件传入需检查的权限
自定义extensions用于从主项目向插件传入需要检测的权限,代码如下:
//Extension类
class PermissionExtension {
ArrayList<String> checkPermissions
}
class MiniGamePermissionPlugin implements Plugin<Project> {
@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<Project> {
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。
执行Task之后,可以在AndroidStudio底部的Build或者Run中看到日志。