Android Gradle plugin升级 3.0.1 和升级 3.1.1遇到的坑

升级过程

  1. 将project下的build.gradle中的gradle plugin版本升级到3.0.1

    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.1' //原先为2.3.3
    }

    修改后通过Sync project可以得知gradle-wrapper版本低于gradle plugin 3.0.1所要求的最低版本,根据提示将gradle 版本升级到4.1。

        distributionUrl=https://services.gradle.org/distributions/gradle-4.1-all.zip  //原先为 3.3
  2. 更改仓库,如下:

    buildscript {
        repositories {
            ...
            // You need to add the following repository to download the new plugin.
            google()
        }
    
        dependencies {
            classpath 'com.android.tools.build:gradle:3.0.1'
        }
    }
  3. 再次Sync project会出现以下错误,

    Error:All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com/r/tools/flavorDimensions-missing-error-message.html

    意思是需要我们在app/build.gradle加上默认的flavor dimension:

    flavorDimensions "default" // 即以下说的风味维度

    gradle plugin 3.0以上包含一项新的依赖项机制,这种机制可以在消费库时自动匹配变体。 也就是说,应用的 debug 变体将自动消费库的 debug 变体,等等。 这种机制也适用于使用风味的情况 - 应用的 redDebug 变体将消费库的 redDebug 变体。 要使这种机制发挥作用,插件现在要求属于给定风味维度的所有风味 - 即使您仅准备使用一个维度,也是如此。

    这个属性主要用于不同渠道打包时的配置问题,至于它的使用具体请参考配置构建变体

  4. 更改依赖项配置

    新配置 已弃用配置 行为
    implementation compile 依赖项在编译时对模块可用,并且仅在运行时对模块的消费者可用。对于大型多项目构建,使用 implementation 而不是 api/compile 可以显著缩短构建时间,因为它可以减少构建系统需要重新编译的项目量。大多数应用和测试模块都应使用此配置。
    api compile 依赖项在编译时对模块可用,并且在编译时和运行时还对模块的消费者可用。此配置的行为类似于 compile(现在已弃用),一般情况下,您应当仅在库模块中使用它。应用模块应使用 implementation,除非您想要将其 API 公开给单独的测试模块。
    compileOnly provided 依赖项仅在编译时对模块可用,并且在编译或运行时对其消费者不可用。此配置的行为类似于 provided(现在已弃用)。
    runtimeOnly apk 依赖项仅在运行时对模块及其消费者可用。此配置的行为类似于 apk(现在已弃用)。

    注:compile、provided 和 apk 目前仍然可用。 不过,它们将在下一个主要版本中消失。

    同时还需要修改注解处理器依赖项配置,即将 apt 改为 annotationProcessor ,因为以后的gradle plugin将不再兼容android-apt 插件,修改如下:

    dependencies {
        ...
        annotationProcessor 'com.google.dagger:dagger-compiler:' //原本为apt 'com.***'
    }
  5. 接下来再rebuild或者直接run时,如果项目中有用到注解依赖的话,会出现找不到注解的情况,例如用到Dagger会出现

    Error:(31, 34) 错误: 找不到符号
    符号:   类 DaggerAppComponent
    位置: 程序包 com.***.***.

    该问题可以通过设置 module 的 build.gradle 处理,如下

    android {
        ...
        defaultConfig {
            ...
            javaCompileOptions {
                annotationProcessorOptions {
                    includeCompileClasspath true
                }
            }
        }
    }

    不过官方并不建议这么使用,甚至在将来将会移除该选项,但是好像也没找到有其他解决方法。

  6. 修改完再sync依然会有问题,如下:

    Error:(268, 5) error: style attribute '@android:attr/windowEnterAnimation' not found.
    Error:(268, 5) error: style attribute '@android:attr/windowExitAnimation' not found.
    ...
    Error:failed linking references.
    Error:java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: com.android.tools.aapt2.Aapt2Exception: AAPT2 error: check logs for details
    Error:java.util.concurrent.ExecutionException: com.android.tools.aapt2.Aapt2Exception: AAPT2 error: check logs for details
    Error:com.android.tools.aapt2.Aapt2Exception: AAPT2 error: check logs for details

    从这里来看好像是AAPT2的问题,所以从网上可以找到大量对该问题的解决方法都是在 project 的 gradle.properties中添加这样一行代码 android.enableAapt2=false, 添加完之后也确实是可以解决了。
    但是,加上这个之后,在以后升级 3.1.1 时将无法使用instant run,会一直报错:Error: java.util.NoSuchElementException,所以这里真正的解决方法是找到你的style文件,将里面所有的以 @android 开头的都去掉 “@” 这个符号,例如:

    // 原先的
    <style name="PushInBottom">
    <item name="@android:windowEnterAnimation">@anim/push_bottom_in
    "@android:windowExitAnimation">@anim/push_bottom_out
    style>
    // 变更后的
    <style name="PushInBottom">
    <item name="android:windowEnterAnimation">@anim/push_bottom_in
    "android:windowExitAnimation">@anim/push_bottom_out
    style>
  7. API变更
    Variant API 变更,主要是 variant 的outputFile在使用上产生了变化,例如原本是 output.outputFileoutput.outputFile.name, 变更后应该使用 output.outputFileName,但涉及访问 outputFile 对象的更复杂任务将不再奏效。
    manifestOutputFile变更,processManifest.manifestOutputFile() 函数不再可用,如果尝试调用该函数,将遇到以下错误:

    A problem occurred configuring project ':myapp'.
    Could not get unknown property 'manifestOutputFile' for task ':myapp:processDebugManifest'
    of type com.android.build.gradle.tasks.ProcessManifest.

    取而代之的是通过调用 processManifest.manifestOutputDirectory()来返回包含所有已生成 manifest 目录的路径, 然后,通过该路径找到某个 manifest 。下面的示例可以在 manifest 中动态更改版本代码:

    android.applicationVariants.all { variant ->
        variant.outputs.all { output ->
            output.processManifest.doLast {
                // Stores the path to the maifest.
                String manifestPath = "$manifestOutputDirectory/AndroidManifest.xml"
                // Stores the contents of the manifest.
                def manifestContent = file(manifestPath).getText()
                // Changes the version code in the stored text.
                manifestContent = manifestContent.replace('android:versionCode="1"',
                        String.format('android:versionCode="%s"', generatedCode))
                // Overwrites the manifest with the new text.
                file(manifestPath).write(manifestContent)
            }
        }
    }

参考文献

迁移到 Android Plugin for Gradle 3.0.0

你可能感兴趣的:(android)