一次集成与升级AndroidX的记录
Posted 疯狂小芋头
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一次集成与升级AndroidX的记录相关的知识,希望对你有一定的参考价值。
文章目录
- 1. 未升级 AndroidX 之前
- 2. 升级到 AndroidX
- 2.1. 升级转换到 AndroidX
- 2.2. support 升级到 AndroidX
- 2.3. 控件升级到 AndroidX
- 2.4. Program type already present
- 2.5. Static interface methods are only supported starting with Android N
- 2.6. Error:Unable to resolve dependency for ':@debug/compileClasspath'
- 2.7. ACCS_CHANNEL_INIT_FAIL 10212 静默连接进程(默认为channel进程)未初始化
- 2.8. 其它
- 3. 小结
最近将某个项目升级到了 androidX,中间出现了很多问题,特别记录一下。
由于整个过程很复杂,需要简单说明一下。大概的过程如下:
1. 未升级 AndroidX 之前
- 首先是原来没有打算升级 AndroidX 的,只是想集成阿里的推送;但是发现一直无法下载到库,gradle 一直报错。
1.1. Connection refused
连接被拒绝,试了非常多次,不科学上网/部分科学上网/全局科学上网,都是一样的(此时 gradle 版本为 3.0.2)。
Connection refused
偶然间将 gradle 版本升级到最新版本 3.3.2,不再出现该连接拒绝的错误;我不禁陷入了深深地沉思……
实际上之前已经尝试独立集成过一次阿里推送并且正常的(在一个DEMO中只做了阿里推送的集成),所以再回去把项目翻出来查看,那个项目是真的也用了3.3.2
版本的 gradle,暂时我将它定义为确实需要新版本的 gradle 才能正确连接到阿里的仓库,至少我感觉在旧版本上成功率可能会低很多。
- 升级后同步仓库后发现配置文件无法合并
1.2. Could not execute build using Gradle distribution
这是 gradle 同步时出现的错误信息,如果抛出的异常原因不清楚,直接往下看Caused by:...
,即原始异常信息,查找下去可以看到出错的原因。
Error:Internal error:
org.gradle.tooling.BuildException: Could not execute build using Gradle distribution 'https://services.gradle.org/distributions/gradle-4.10.1-all.zip'.
at org.gradle.tooling.internal.consumer.ExceptionTransformer.transform(ExceptionTransformer.java:51)
...
Caused by: org.gradle.internal.exceptions.LocationAwareException: Execution failed for task ':base:processDebugAndroidTestManifest'.
at org.gradle.initialization.DefaultExceptionAnalyser.transform(DefaultExceptionAnalyser.java:74)
...
Caused by: org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':base:processDebugAndroidTestManifest'.
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:110)
... 67 more
Caused by: java.lang.RuntimeException: Manifest merger failed with multiple errors, see logs
... 112 more
排查操作:
在最后我们可以看到是由于Manifest merger failed with multiple errors
合并 AndroidMainfest.xml 文件出错导致的,所以问题肯定就在这里了。详细的错误信息查看 logs ,即在下面面板中 gradle build 的控制输出面板gradle console
。如果是新版本的 AS(3.3.2)则在 build 时出现错误会在右边有很明显的错误信息,不需要手动去点开控制台查看错误信息。
1.3. > Task :base:processDebugAndroidTestManifest FAILED
是这合并 AndroidMainfest.xml 时报错,具体的出错信息需要看下面
> Task :base:processDebugAndroidTestManifest FAILED
[com.pgyersdk:sdk:3.0.0] /Users/xxx/.gradle/caches/transforms-1/files-1.1/sdk-3.0.0.aar/af4ea8a5066b778464e4804d6cf07040/AndroidManifest.xml:9:5-79 Warning:
Element uses-permission#android.permission.ACCESS_NETWORK_STATE at [com.pgyersdk:sdk:3.0.0] AndroidManifest.xml:9:5-79 duplicated with element declared at [com.pgyersdk:sdk:3.0.0] AndroidManifest.xml:8:5-79
[com.aliyun.ams:alicloud-android-push:3.1.4] /Users/xxx/.gradle/caches/transforms-1/files-1.1/alicloud-android-push-3.1.4.aar/66b91b217d8fbce6cb4c4474bbb7d805/AndroidManifest.xml:26:5-81 Warning:
Element uses-permission#android.permission.WRITE_EXTERNAL_STORAGE at [com.aliyun.ams:alicloud-android-push:3.1.4] AndroidManifest.xml:26:5-81 duplicated with element declared at [com.aliyun.ams:alicloud-android-push:3.1.4] AndroidManifest.xml:16:5-81
排查操作:
从错误信息中可以明确知道,就是因为 AndroidMainfest.xml 里的权限重复了导致了错误Element uses-permission#xxx at 某个库的 AndroidManifest.xml:9:5-79 duplicated with element declared at 某个库的 AndroidManifest.xml:8:5-79
,并且错误位置的行号都明确给出来了,所以按着行号去查,将重复的权限注释掉就行了。大部分时候可能是你自己应用里的 AndroidMainfest.xml 的权限已经在依赖库里申请了,所以就重复了。
重量级的坑爹问题出现了!!仔细看上面的重复错误
Element uses-permission# xxx at [com.pgyersdk:sdk:3.0.0] xxx duplicated with element declared at [com.pgyersdk:sdk:3.0.0]
是的,你没有看错,[com.pgyersdk:sdk:3.0.0]
依赖库自己的 AndroidMainfest.xml 里的权限重复了!!!,这个问题是个大坑,因为一开始没有细看以为自己的 AndroidMainfest.xml 的权限与库重复了,即使注释掉了自己项目里的权限依然一直报错!根据错误信息,我们知道了这个库的位置:/Users/xxx/.gradle/caches/transforms-1/files-1.1/sdk-3.0.0.aar/af4ea8a5066b778464e4804d6cf07040/AndroidManifest.xml
打开该位置的配置文件,确实文件中是出现重复的权限!
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!--这里的权限是真的重复了-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
删除掉重复的权限,再重新 build 错误不再出现。PS:细心的小伙伴会发现,上面编译里报错的,还有阿里的包【疲惫的微笑.jpg】。
注意:这件事提醒我们,新的 gradle 版本对检查更加严格;并且在自己也需要提供给别人库或者 module 时,没必要的权限不要申请,重复的权限删除掉,不然可能你永远不知道下一个坑的人是谁。
另外,在解决这个问题的时候查到一些移除库中权限的方法,虽然这里并没有使用到,但是作者很用心测试并说明了情况,这个备注一下。
一次Android权限删除经历
1.4. Attribute application@appComponentFactory
这个错误很奇怪,也很不清晰。首先根据错误信息,在相应的路径下的 xml 文件存在问题/Users/xxx/android/sdk_demo/base/build/intermediates/tmp/manifest/androidTest/debug/manifestMerger5738855137681502227.xml
,但是实际上去对应的路径下查找时,是真的查找到不到这个文件!!!
/Users/xxx/android/sdk_demo/base/build/intermediates/tmp/manifest/androidTest/debug/manifestMerger5738855137681502227.xml:22:18-91 Error:
Attribute application@appComponentFactory value=(android.support.v4.app.CoreComponentFactory) from [com.android.support:support-compat:28.0.0] AndroidManifest.xml:22:18-91
is also present at [androidx.core:core:1.0.0] AndroidManifest.xml:22:18-86 value=(androidx.core.app.CoreComponentFactory).
Suggestion: add 'tools:replace="android:appComponentFactory"' to <application> element at manifestMerger5738855137681502227.xml:7:5-9:19 to override.
后面 gradle 也给出了建议的解决方案:Suggestion: add 'tools:replace="android:appComponentFactory"' to <application> element at manifestMerger5738855137681502227.xml:7:5-9:19 to override.
使用该方案在自己的项目里添加了该参数后,无效。根据网上的小伙伴提示,实际上除了添加这个tools:replace="android:appComponentFactory"
,还需要再添加一个任意值的属性android:appComponentFactory="任意值"
,我理解是后面添加的“任意值”是为了覆盖所有冲突地方的数据。
详细请参考解决 导入三方时出现: appComponentFactory 错误
虽然添加了这个操作,但是在当时依然是无法正常编译(但是不是还是这个问题我不太记得了),并且后面在将项目升级到 AndroidX 之后,实际上去掉这部分操作也是可以正常编译并运行的,怀疑可能是不需要的。
2. 升级到 AndroidX
- 由于 gradle 版本升级到3.3.2,项目中使用的 butterknife 要求需要升级到 10.1.0(支持 AndroidX),开始了痛苦的升级过程
2.1. 升级转换到 AndroidX
升级 AS 到最新版本3.3.2,此版本提供了Refactor->Migrate to AndroidX
功能,可以快速转换到 AndroidX,但是并不是全部,如部分 support 包是无法转换的
2.2. support 升级到 AndroidX
如果原项目使用了 support 包的 annotation,如@Nullable
或@NonNull
,请毫不犹豫在依赖库中添加上以下依赖
api 'androidx.annotation:annotation:1.0.2'
并全局文件搜索将原引用全部替换为新的引用(这种替换方式是最快的,会有误操作的部分,但是影响不大)。
原引用 | 新引用 |
---|---|
android.support.annotation. | androidx.annotation. |
2.3. 控件升级到 AndroidX
- TabLayout
如果原项目使用了 design 包如TabLayout
,请毫不犹豫在依赖库中添加上以下依赖,design 包中原本有的TabLayout
其实是属于 support 的包名下,但是在 AndroidX 中不会默认包含到androidx.core.xxx
的包下
api 'com.android.support:design:28.0.0'
原引用 | 新引用 |
---|---|
android.support.design.widget.TabLayout | com.google.android.material.tabs.TabLayout |
- Constraintlayout
如果原项目使用了Constraintlayout
,请毫不犹豫在依赖库中添加上以下依赖
api 'androidx.constraintlayout:constraintlayout:1.1.3'
原引用 | 新引用 |
---|---|
android.support.constraint.ConstraintLayout | androidx.constraintlayout.widget.ConstraintLayout |
- RecyclerView、SwipeRefreshLayout、Guideline、NestedScrollView
这些控件都需要更新
原引用 | 新引用 |
---|---|
android.support.v7.widget.RecyclerView | androidx.recyclerview.widget.RecyclerView |
android.support.v4.widget.SwipeRefreshLayout | androidx.swiperefreshlayout.widget.SwipeRefreshLayout |
android.support.constraint.Guideline | androidx.constraintlayout.widget.Guideline |
android.support.v4.widget.NestedScrollView | androidx.core.widget.NestedScrollView |
注意:所有的控件在更新引用时,需要把 xml 文件中的控件也一起更新
2.4. Program type already present
引用库文件重复
AGPBI: "kind":"error","text":"Program type already present: android.support.v4.graphics.drawable.IconCompatParcelizer","sources":[],"tool":"D8"
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:transformDexArchiveWithExternalLibsDexMergerForGatewayDebug'.
> com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives:
Program type already present: android.support.v4.graphics.drawable.IconCompatParcelizer
Learn how to resolve the issue at https://developer.android.com/studio/build/dependencies#duplicate_classes.
根据错误信息,可以知道是android.support.v4.graphics.drawable.IconCompatParcelizer
这个类重复了,但是我们并不一定知道是在什么库导致的重复,所以可以全局搜索。这里使用全局搜索文件是可能查找不到的,需要使用双 shift,即 AS 自带的searchEverywhere
一般情况下是因为 AndroidX 默认提供了原有的大部分 support 包,这里很可能是重复引入了原有的com.android.support
包导致的,建议取消掉所有的com.android.support
的依赖
2.5. Static interface methods are only supported starting with Android N
引用库中使用了静态接口方法,该功能只在 java8 中支持,所以需要指定编译的 java 版本为 java8
AGPBI: "kind":"error","text":"Static interface methods are only supported starting with Android N (--min-api 24): void butterknife.Unbinder.lambda$static$0()","sources":[],"tool":"D8"
在主项目(一定要在主项目,一般是 app module)中添加上以下的编译选项:
android
...
compileOptions
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
...
这个是由于 butterknife 10.0.1 版本中使用了静态接口的原因引起的,如果你在其它子 module 中使用了 butterknife,注意上面的编译选项也是需要在主 module 中添加,在子 module 中添加是无效的,这个在实际中已经测试过了(即不能只在引用 butterknife 的 module 中添加,需要在主 module 中添加该配置)
相关参考内容As升级到3.3出现的报错
2.6. Error:Unable to resolve dependency for ‘:@debug/compileClasspath’
在升级后由于阿里的仓库很容易查找不到或者同步失败,切换过 gradle 的 offwork 离线同步操作。后面非常频繁出现以下问题:
Error:Unable to resolve dependency for ':@debug/compileClasspath'
//或者类似
Could not resolve com.aliyun.ams:alicloud-android-utils:latest.integration. Show Details
各种尝试不科学上网或科学上网都无法解决问题,或者是很偶然能同步成功一两次。该情况下需要确认gradle.properties
文件中是否设置了代理,如果设置了代理很有可能就是它引引的,在注释了该文件中的代理后,同步不再频繁出现失败的情况
参考文章:
Android Studio 3.1.4,gradle 4.4解决Error:Unable to resolve dependency for ':@debug/compileClasspath’问题
关于升级到Android studion 3.1.3 gradle 4.4 遇到的坑
2.7. ACCS_CHANNEL_INIT_FAIL 10212 静默连接进程(默认为channel进程)未初始化
使用阿里推送初始化时,可能会报出以下错误。在官方文档中查询到的解决方案并不完全适用。出现这个问题时需要注意:初始化时必须在Application的onCreate()中初始化。
2.8. 其它
- 在升级中有出现过类似
error: resource android:attr/fontVariationSettings resource android:attr/ttcIndex not found
的错误,根据网上信息是 support 包的版本不正确,可以通过以下方式处理资源属性未查找到,但是实际上如果是已经升级到 AndroidX,把所有 support 包依赖去掉,只使用 AndroidX 中统一的包即可,不会有这种问题
3. 小结
总的来说升级 AndroidX 的过程并不是很愉快,可能各种问题都有吧,gradle 又时不时老是要同步,不管改的东西是不是依赖还只是改一个版本号。
另外阿里的仓库是真的很折腾人,包括文档也是很难找,基本是对阿里没有太多的好感了。
最后,感谢所有在网上发布自己经验的人,希望这个文章也能帮到别人。
部分参考文章 :
以上是关于一次集成与升级AndroidX的记录的主要内容,如果未能解决你的问题,请参考以下文章
错误记录Android Studio 集成 ARoute 编译报错 ( 兼容 support 库和 androidx 库 | add ‘tools:replace=“android:appCo )