无法使用清单占位符来移除权限

12

我正在尝试使用清单占位符来删除AndroidManifest.xml中的uses-permission节点,以便在发布版本中不需要,但一直没有成功。

build.gradle

buildTypes {
    release {
        manifestPlaceholders.excludeDebugPermissions = "remove"
    }
    debug {
        manifestPlaceholders.excludeDebugPermissions = "merge"
    }
}

AndroidManifest.xml

<uses-permission
    android:name="android.permission.SYSTEM_ALERT_WINDOW"
    tools:node="${excludeDebugPermissions}" />

出现这样的错误:

错误:执行任务“:app:processDebugManifest”失败。 com.android.manifmerger.NodeOperationType.${EXCLUDE_DEBUG_PERMISSIONS}中没有枚举常量

但在其他任何地方使用占位符都可以正常工作(合并的清单文件正确,没有错误),例如:

<uses-permission
    android:name="${excludeDebugPermissions}"
    tools:node="remove" />

所以我认为tools:node属性不支持清单占位符,因此我可能会通过替换掉节点标记(merge/ remove)的方式来实现权限名称的替换,但如果可能的话,我宁愿避免这样做。

有什么建议吗?


你是否想为调试版和发布版设置不同的权限?你可以在src/debug中放置另一个Android清单文件。缺点是你需要维护两个清单文件。 - RobVoisey
1
@RobVoisey 实际上我正在尝试摆脱React Native继承的SYSTEM_ALERT_WINDOW权限。 - Andrzej Zabost
你能解决这个问题吗? - Danny Harding
3个回答

3

我发现解决这个问题最简单和最干净的方法是创建一个仅限发布的AndroidManifest文件(app/src/release/AndroidManifest.xml),其中包含以下内容,以删除SYSTEM_ALERT_WINDOW权限:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" tools:node="remove"/>
</manifest>

0
针对您关于React Native的评论,我找到了这个链接:https://github.com/facebook/react-native/issues/5886 解决方案是在您的构建类型中添加以下内容,与您当前的略有不同:
buildTypes {
    debug {
        manifestPlaceholders = [excludeSystemAlertWindowPermission: "false"]
    }
    release {
        manifestPlaceholders = [excludeSystemAlertWindowPermission: "true"]
    }
}

所以这将被包含在您的清单中:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" tools:remove="${excludeSystemAlertWindowPermission}"/>

3
我已经看到了那个问题。提出的解决方案行不通(在此确认链接), 而且我不明白为什么会行不通,因为文档明确表明 tools:remove 将“删除指定属性”,并且它接受属性名称,而不是布尔值。 - Andrzej Zabost

0
作为 Android 版本方法的替代方案,这是我为我的应用程序清单允许不同权限设置的解决方案。
例如,如果我在我的 build.gradle 中设置了自定义 USE_PERMISSION_BUILD_SERIAL 标志,则可以选择启用/禁用 Manifest.permission.READ_PHONE_STATE 权限,如下所示:
ext {
    //to enable READ_PHONE_STATE permission to access Build.SERIAL used 
    //for our bug reporting feature. 
    //Since there is a privacy concern with Build.SERIAL, we can decide 
    //to allow/disallow it right here!
    //If it is disabled, the Phone permission will not appear at all.
    //If it is enabled, the user will decide instead to allow the Phone 
    //access during its permission request as usual
    USE_PERMISSION_BUILD_SERIAL = true
    
    // whatever the rest...
}

android {

    defaultConfig {
    
        buildConfigField("boolean", "USE_PERMISSION_BUILD_SERIAL", "${USE_PERMISSION_BUILD_SERIAL}")
    }

    sourceSets {
    
        main {
            if (USE_PERMISSION_BUILD_SERIAL) {
                manifest.srcFile 'src/main/AndroidManifestBuild.xml'
            }
            else {
                manifest.srcFile 'src/main/AndroidManifest.xml'
            }
        }
    }           
}

接下来,我准备了两个不同的清单文件,AndroidManifestBuild.xmlAndroidManifest.xml,并将它们存储在我的项目的 src/main 文件夹下。
与普通的 AndroidManifest.xml 不同的是,在 AndroidManifestBuild.xml 文件中,我将请求 Manifest.permission.READ_PHONE_STATE 权限,如下所示:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.app">

    <!-- required for accessing android.os.Build.getSerial() in Android 9.0+ -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    
</manifest>

不用担心清单文件的名称,因为 Gradle 将会构建出最终正确命名的 Android 应用程序清单文件。
利用 Gradle 的 buildConfigField() 功能,我可以使用 BuildConfig.USE_PERMISSION_BUILD_SERIAL 存储 USE_PERMISSION_BUILD_SERIAL 标志的状态以准备必要的权限请求(可选)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接