manifest( 二 )

除此以外,还存在一个默认占位符${applicationId},与android DSL中applicationId配置值绑定 。在构建过程中,会将所有占位符替换为对应值 。
1.4 合并决策日志
最终AndroidManifest.xml的每一个节点、属性,来源于哪个清单文件,通过何种策略生成,这些信息都记录在合并决策日志中,对问题的分析和排查,提供重要辅助信息 。文件位于app工程build/outputs/logs/manifest-merger[-productFlavor]-<buildType>-report.txt,示例内容如下:
activity#com.example.myapplication.MainActivityADDED from /Users/flyeek/workspace/code-lab/android/MyApplication/app/src/main/AndroidManifest.xml:18:9-24:20android:nameADDED from /Users/flyeek/workspace/code-lab/android/MyApplication/app/src/main/AndroidManifest.xml:18:19-47intent-filter#action:name:android.intent.action.MAIN+category:name:android.intent.category.LAUNCHERADDED from /Users/flyeek/workspace/code-lab/android/MyApplication/app/src/main/AndroidManifest.xml:19:13-23:29action#android.intent.action.MAINADDED from /Users/flyeek/workspace/code-lab/android/MyApplication/app/src/main/AndroidManifest.xml:20:17-69android:nameADDED from /Users/flyeek/workspace/code-lab/android/MyApplication/app/src/main/AndroidManifest.xml:20:25-66category#android.intent.category.LAUNCHERADDED from /Users/flyeek/workspace/code-lab/android/MyApplication/app/src/main/AndroidManifest.xml:22:17-77android:nameADDED from /Users/flyeek/workspace/code-lab/android/MyApplication/app/src/main/AndroidManifest.xml:22:27-74...uses-permission#android.permission.READ_EXTERNAL_STORAGEIMPLIED from /Users/flyeek/workspace/code-lab/android/MyApplication/app/src/main/AndroidManifest.xml:2:1-28:12 reason: com.example.libraryaar1 requested WRITE_EXTERNAL_STORAGEMERGED from [com.youku.arch:Hound:2.8.15] /Users/flyeek/.gradle/caches/transforms-2/files-2.1/d42ba59a47f7160082879236533c4582/AndroidManifest.xml:11:5-80MERGED from [com.youku.arch:Hound:2.8.15] /Users/flyeek/.gradle/caches/transforms-2/files-2.1/d42ba59a47f7160082879236533c4582/AndroidManifest.xml:11:5-80uses-permission#android.permission.WRITE_CALL_LOGIMPLIED from /Users/flyeek/workspace/code-lab/android/MyApplication/app/src/main/AndroidManifest.xml:2:1-28:12 reason: com.example.libraryaar1 has targetSdkVersion < 16 and requested WRITE_CONTACTS看完本文的基础知识,这里面的内容,应该都能看懂,不再赘述 。
1.5 几个有意思的配置
至此,我们已经对manifest文件有了一个“框架性”的整体认知 。最后,来看几个比较有意思的配置 。
1package vs applicationId
这两个概念比较容易混淆,从最终apk文件的视角来看,唯一标识apk的,就是AndroidManifest.xml中manifest节点的package属性值,也就是经常说的“appId”、“app包名” 。直接上图:

manifest

文章插图
package vs applicationId
app工程中的package值,仅影响构建过程 。而android DSL中的applicationId值,最后会替换AndroidManifest.xml中的package属性值,成为最终apk唯一标识 。
2隐式系统权限
在某些条件下,清单文件的合并过程,会额外自动添加系统权限声明,如果不加以处理,同时app隐私协议未加以声明,会引发合规风险 。自动添加权限声明的情况如下表(直接摘自官方文档):
manifest

文章插图
合并过程添加的权限声明列表
例如,app的targetSdkVersion是28,以外部依赖形式,引入一个模块,其中包含的AndroidManifest.xml(低优先级清单)中targetSdkVersion是14,并且声明了READ_CONTACTS权限,那么最终apk清单文件,将包含READ_CALL_LOG权限声明 。
3组件导出控制
组件导出,是指android:exported属性为true(显式/隐式),组件可被其它app调用 。如果在清单中显式设置了android:exported值,那以此为准;如果未设置,则隐式规则为:如果设置了intent-filter,则exported值为true,否则为false 。很多app都会使用组件(尤其是activity)的app内路由机制,因此会设置一些intent-filter,这会导致组件被非预期导出,带来安全风险 。这一点需要特别关注,后面也会再讲到 。
值得注意的是,当targetSdkVersion设置为31(Android12)及以上时,如果组件设置了intent-filter,那么必须同时显式设置android:exported值 。如果未显式设置exported值,对于高版本Android Studio,IDE的build会失败,对于低版本Android Studio,build可以成功,但是安装到Android12及以上设备时会失败 。
治理实践前面对manifest基础知识,以及工程应用,进行了相关讲解,相信大家已经形成初步的整体认知 。随着工程模块/代码增加,清单文件可控性逐步降低:无论是关键配置值意外变化,还是非预期权限引入,甚至是无用/冗余/风险节点及属性积累 。优酷在与manifest“腐化”斗争中,从上层实际需求(例如隐私合规、安全漏洞、线上问题)出发,通过相关工具建立有效的检测能力,并基于此形成日常研发卡口机制 。在确保问题零新增前提下,逐步消化已有存量问题 。

秒懂生活扩展阅读