Android12自动适配exported深入解析避坑

更新时间:2023-05-12 23:37:17 阅读: 评论:0

Android12⾃动适配exported深⼊解析避坑
众所周知,从 Android 12 开始,使⽤了 TargetSDK 31 之后,四⼤组件如果使⽤了 intent-filter, 但是没显性质配置 exported App 将会⽆法安装,甚⾄编译不通过。
⽐如启动的 Activity 就需要设置 exported 为 true ,⾄于其他组件是否设置为 true 则看它是否需要被其它应⽤调⽤。
然⽽这个事情的状态是这样的:
如果出现问题的 AndroidManifest ⽂件是你本地的,那⼿动修改即可;
但如果出现问题的是第三⽅远程依赖,并且对⽅并没有提供源码和更新,你就⽆法直接修改;
如果第三⽅依赖太多,查找哪些出了问题⼗分费时费⼒。
脚本
所以在之前的 ⼀⽂中提供了⼀套脚本,专门⽤于适配 Android 12 下缺少 android:exported ⽆法编译或者安装的问题,但是在这期间收到了不少问题反馈:
ls.build:gradle:4.0.0 以及其下版本
⼀下脚本经过测试最⾼可到⽀持的版本: gradle:4.0.0 & gradle-6.1.1-all.zip
ls.build:gradle:4.0.0 以上版本
以下脚本经过测试⽀持的版本: gradle:4.1.0 & gradle-6.5.1-all.zip android.applicationVariants.all { variant ->    variant.outputs.all { output ->        output.processResources.doFirst { pm ->            String manifestPath = output.processResources.manifestFile            def manifestFile = new File(manifestPath)            def xml = new XmlParr(fal, true).par(manifestFile)            def exportedTag = "android:exported"            ///指定 space            def androidSpace = l.Namespace('/apk/res/android', 'android')            def nodes = xml.application[0].'*'.findAll {                //挑选要修改的节点,没有指定的 exported 的才需要增加                (it.name() == 'activity' || it.name() == 'receiver' || it.name() == 'rvice') && it.ported) == null            }            ///添加 exported ,默认 fal            nodes.each {                def isMain = fal                it.each {                    if (it.name() == "intent-filter") {                        it.each {                            if (it.name() == "action") {                                if (it.attributes().get(androidSpace.name) == "android.intent.action.MAIN") {                                    isMa
in = true                                    println("......................")                                }                            }                        }                    }                }                it.attributes().put(exportedTag, "${isMain}")            }            PrintWriter pw = new PrintWriter(manifestFile)            pw.l.XmlUtil.rialize(xml))            pw.clo()        }    }}
4
5
6
7
8
9
10
11
12
13
14数学大全
15
16
17
18
19
20
21
22
23
24
25
26
27自然垄断行业
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
android.applicationVariants.all { variant ->    variant.outputs.each { output ->        def processManifest
= ProcessManifestProvider().get()        processManifest.doLast { task ->            def outputDir = task.multiApkManifestOutputDirectory            File outputDirectory            if (outputDir instanceof File) {                outputDirectory = outputDir            } el {                outputDirectory = ().asFile            }            File manifestOutFile = file("$l")            println("----------- ${manifestOutFile} ----------- ")            if (ists() && manifestOutFile.canRead() && manifestOutFile.canWrite()) {                def manifestFile = manifestOutFile                ///这⾥第⼆个参数是 fal ,所以 namespace 是展开的,所以下⾯不能⽤ androidSpace ,⽽是⽤ nameTag                def xml = new XmlParr(fal, fal).par(manifestFile)                def exportedTag = "android:exported"                def nameTag = "android:name"                ///指定 space                //def androidSpace = l.Namespace('/apk/res/android', 'android')                def nodes = xml.application[0].'*'.findAll {                    //挑选要修改的节点,没有指定的 exported 的才需要增加                    //如果 exportedTag 拿不到可以尝试 it.ported)                    (it.name() == 'activity' || it.name() == 'receiver' || it.name() == 'rvice') && it.attribute(exportedTag) == null                }                ///添加 exported ,默认 fal                nodes.each {                    def isMain = fal                    it.each {                        if (it.name() == "intent-filter") {                            it.each {                                if (it.name() == "action") {                                    //如果 nameTag 拿不到
可以尝试 it.attribute(androidSpace.name)                                    if (it.attributes().get(nameTag) == "android.intent.action.MAIN") {                                        isMain = true                                        println("......................")                                    }                                }                            }                        }                    }                    it.attributes().put(exportedTag, "${isMain}")                }                PrintWriter pw = new PrintWriter(manifestFile)                pw.l.XmlUtil.rialize(xml))                pw.clo()            }        }    }}
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
这段脚本你可以直接放到 adle  下执⾏,也可以单独放到⼀个 gradle ⽂件之后 apply  引⼊,它的作⽤就是:在打包过程中检索所有没有设置 exported  的组件,给他们动态配置上 exported ,这⾥有个特殊需要注意的是,因为启动 Activity  默认就是需要被 Launcher 打开的,所以 "android.intent.action.MAIN" 需要 exported  设置为 true  。(PS:更正规应该是⽤
LAUNCHER 类别,这⾥故意⽤ MAIN)⽽后综合问题,具体反馈的问题有 :
label 直接写死中⽂,不是引⽤ @string  导致的在 3.x 的版本可以正常运⾏,但不能打包 ;
XmlParr  类找不到,这个⾸先确定 AGP 版本和 Gradle 版本是否匹配,具体可见 ,另外可以通过 groovy.util.XmlParr 或者l.XmlParr 全路径指定使⽤ ,如果是 gradle ⽂件⾥显⽰红⾊并不会影响运⾏;运⾏报错提⽰ android:exported needs,这个就是今天需要输⼊聊的;
基于上述脚本测试和反馈,⽬前的结论是:
从 gradle:4.2.0 & gradle-6.7.1-all.zip 开始,TargetSDK 31 下脚本会有异常,因为在 processDebugMainManifest (带有Main) 的阶段,会直接扫描依赖库的 l 然后抛出直接报错,从⽽进不去 processDebugManifest 任务阶段就编译停⽌,所以实际上脚本并没有成功运⾏。
所以此时拿不到 mergerd_manifest  下的⽂件,因为 mergerd_manifest  下 l  也还没创建成功,没办法进⼊ task ,也就是该脚本⽬前只能针对 gradle:4.1.0 以及其下版本安装 apk 到 Android12 的机器上, 有 intent-filter  但没有 exoprted 的适配问题,基于这个问题,不知道各位是否有什么好的建议?
新脚本
⽽⽬前基于这个问题,这⾥提供了如下脚本,在 gradle:4.2.0 & gradle-6.7.1-all.zip  以及 7.0 的版本上,该脚本的作⽤是在运⾏时⾃动帮你打印出现问题的 aar 包依赖路径和组建名称:
Error: android:exported needs to be explicitly specified for <xxxx>. Apps targeting Android 12 and higher are required to specify an explicit value for `androi 1
如下图所⽰,因为⽬前官⽅如红⾊信息内容其实指向并不正确,容易误导问题⽅向,所以通过上述脚本打印,可以快速查找到问题所在的点,然后通过 tool:replace 临时解决。android.applicationVariants.all { variant ->    variant.outputs.each { output ->        //println("=============== ${BuildType().UpperCa()} ===============")        //println("=============== ${FlavorName()} ===============")        def vn        if (FlavorName() != null && FlavorName() != "") {            vn = variant.name;        } el {            if (BuildType().name == "relea") {                vn = "Relea"            } el {                vn = "Debug"            }        }        def taskName = "process${vn}MainManifest";        try {            println("=============== taskName ${taskName} ===============")            Tasks().getByName(taskName)        } catch (Exception e) {            return        }        ///你的⾃定义名字        Tasks().getByName(taskName).doFirst {            //def method = it.getClass().getMethods()            it.getManifests().getFiles().each {                if (it.exists() && it.canR
ead()) {                    def manifestFile = it                    def exportedTag = "android:exported"                    def nameTag = "android:name"                    ///这⾥第⼆个参数是 fal ,所以 namespace 是展开的,所以下⾯不能⽤ androidSpace ,⽽是⽤ nameTag                    def xml = new XmlParr(fal, fal).par(manifestFile)                    if (xml.application != null && xml.application.size() > 0) {                        def nodes = xml.application[0].'*'.findAll {                            //挑选要修改的节点,没有指定的 exported 的才需要增加                            //如果 exportedTag 拿不到可以尝试 it.ported)                            (it.name() == 'activity' || it.name() == 'receiver' || it.name() == 'rvice') && it.attribute(exportedTag) == null                        }                        if (nodes.application != null && nodes.application.size() > 0) {                            nodes.each {                                def t = it                                it.each {                                    if (it.name() == "intent-filter") {                                        println("$manifestFile \n .....................${t.attributes().get(nameTag)}......................")                                    }                                }                            }                        }                    }                }            }        }    }}
1
2
3
4
5
6
7
胆虚
8
9
10
11
12
史学四大家
13
14
黑芝15
16
17
18
两斤有多重
19
20
21
22
23
24
25
26
27内侍省
28
29
qq直播间
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

本文发布于:2023-05-12 23:37:17,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/890115.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:问题   脚本   没有   需要   是否   节点   依赖   反馈
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图