从gradle4.x升级gradle7.x

172 阅读3分钟

由于公司的老项目还在用gradle4.0.2,要适配安卓12。故打开Tools->AGP Upgrade Assistant,把4.0.3选择为7.0.1.这里显示没有对应的jdk 11,选择自带的jdk11包就可以。

建议直接更新到7,更新4.x,6.x总有一些奇奇怪怪的bug。坑特多

gradle4.0.2升级到7.0.1

image.png 选择后进行Run Seleted Steps。 接下来是 第一次Build,报错 The minCompileSdk (31) specified in a dependency's AAR metadata (META-INF/com/android/build/gradle/aar-metadata.properties) is greater than this module's compileSdkVersion (android-30). Dependency: androidx.lifecycle:lifecycle-runtime-ktx:2.5.1. 提示要把compileSdk更新到31.我们在app下的build.gradle

android{
    compileSdk 31
    ...
}

直接build成功,可以安装,目前是gradle-7.0.2-bin.zip

classpath 'com.android.tools.build:gradle:7.0.1'

当然,咱们升级gradle一般是为了升级targetSdk, 这时候咱们把targetSdk设置为31。

Build

xml合并时候报错

Error: android:exported needs to be explicitly specified for <activity>. Apps targeting Android 12 and higher are required to specify an explicit value forandroid:exported when the corresponding component has an intent filter defined. See https://developer.android.com/guide/topics/manifest/activity-element#exported for details.

这是因为从 Android 12 开始,使用了 TargetSDK 31 之后,四大组件如果使用了 intent-filter,但是没显性质配置 exported App 将会无法安装,甚至编译不通过。
请确保你的项目下的组件显式指定exported属性,当然,引用了第三方aar的依赖,不一定都指定了这个属性。 这时候需要写一个通用的构建脚本。 以下资料来自Android 12 自动适配 exported 深入解析避坑_android export_沙滩捡贝壳的小孩的博客-CSDN博客

/**
 * 修改 Android 12 因为 exported 的构建问题
 */
 
android.applicationVariants.all { variant ->
    variant.outputs.each { output ->
        def processManifest = output.getProcessManifestProvider().get()
        processManifest.doLast { task ->
            def outputDir = task.multiApkManifestOutputDirectory
            File outputDirectory
            if (outputDir instanceof File) {
                outputDirectory = outputDir
            } else {
                outputDirectory = outputDir.get().asFile
            }
            File manifestOutFile = file("$outputDirectory/AndroidManifest.xml")
            println("----------- ${manifestOutFile} ----------- ")
 
            if (manifestOutFile.exists() && manifestOutFile.canRead() && manifestOutFile.canWrite()) {
                def manifestFile = manifestOutFile
                ///这里第二个参数是 false ,所以 namespace 是展开的,所以下面不能用 androidSpace,而是用 nameTag
                def xml = new XmlParser(false, false).parse(manifestFile)
                def exportedTag = "android:exported"
                def nameTag = "android:name"
                ///指定 space
                //def androidSpace = new groovy.xml.Namespace('http://schemas.android.com/apk/res/android', 'android')
 
                def nodes = xml.application[0].'*'.findAll {
                    //挑选要修改的节点,没有指定的 exported 的才需要增加
                    //如果 exportedTag 拿不到可以尝试 it.attribute(androidSpace.exported)
                    (it.name() == 'activity' || it.name() == 'receiver' || it.name() == 'service') && it.attribute(exportedTag) == null
 
                }
                ///添加 exported,默认 false
                nodes.each {
                    def isMain = false
                    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("......................MAIN FOUND......................")
                                    }
                                }
                            }
                        }
                    }
                    it.attributes().put(exportedTag, "${isMain}")
                }
 
                PrintWriter pw = new PrintWriter(manifestFile)
                pw.write(groovy.xml.XmlUtil.serialize(xml))
                pw.close()
 
            }
 
        }
    }
}

这里我添加到app下的build.gradle的最底部(顶层)依然报错,懒得了解gradle。直接引用他的gradle插件 添加jitpack.io的maven url后 在根build.gradle引用

dependencies {
      classpath 'com.github.xiachufang:manifest-exported-plugin:1.1.1'
}

app的build.gradle引用插件

apply plugin: 'com.xiachufang.manifest.exported'
或
plugins {
 id 'com.xiachufang.manifest.exported'
}

build finished,构建成功。

一鼓作气,gradle升级到7.4.2

Duplicate class androidx.lifecycle.ViewModelLazy found in modules jetified-lifecycle-viewmodel-ktx-2.3.1-runtime (androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1) and lifecycle-viewmodel-2.4.0-runtime (androidx.lifecycle:lifecycle-viewmodel:2.4.0) Duplicate class androidx.lifecycle.ViewModelProviderKt found in modules jetified-lifecycle-viewmodel-ktx-2.3.1-runtime (androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1) and lifecycle-viewmodel-2.4.0-runtime (androidx.lifecycle:lifecycle-viewmodel:2.4.0) Duplicate class androidx.lifecycle.ViewTreeViewModelKt found in modules jetified-lifecycle-viewmodel-ktx-2.3.1-runtime (androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1) and lifecycle-viewmodel-2.4.0-runtime (androidx.lifecycle:lifecycle-viewmodel:2.4.0) 解决方案升级viewModel-ktx 2.4.0及以上

implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'

好的,又build成功了。

gradle升级到8.0.1

报错信息

`Namespace not specified. Please specify a namespace in the module's build.gradle file like so:

android { namespace 'com.example.namespace' }

If the package attribute is specified in the source AndroidManifest.xml, it can be migrated automatically to the namespace value in the build.gradle file using the AGP Upgrade Assistant; please refer to developer.android.com/studio/buil… for more information. `

给每个model加上不重名的namespace后,报错

Incorrect package="com.tencent.qcloud.tuikit.tuicontact" found in source AndroidManifest.xml: D:\XX\TUIKit\TUIContact\tuicontact\src\main\AndroidManifest.xml. Setting the namespace via the package attribute in the source AndroidManifest.xml is no longer supported. 可能是要叫我删除这xml,修改幅度实在太大,暂时就到这里吧。