【持续更新】Gradle 相关问题解决 & 疑难杂症记录

Gradle 相关问题解决记录 & 疑难杂症记录

双清解决一大部分问题

  • 遇到奇怪的问题先clean 删除build文件夹等清除缓存操作!!
  • .gradle .idea build等目录文件
  • 实在不行试试删除C盘User目录下的.gradle文件夹

小知识&&参考

查看 module依赖树

gradlew :modulename:dependencies

查看gradle task时间和性能分析
  • 使用gradle profile输出性能报告

示例:gradlew AssembleDebug --profile,会在build/reports/profile生出相应的时间统计数据

  • 在task插入时间戳
import java.time.*

gradle.taskGraph.beforeTask { Task task ->
    task.ext.setProperty("startTime", Instant.now())
}

gradle.taskGraph.afterTask { Task task, TaskState state ->
    println task.name + " took " + Duration.between(task.ext.startTime, Instant.now()).toMillis() + " millis"
}
build.gradle 配置manifest占位符值

在BuildConfig文件 生成对应的变量:buildConfigField “boolean”, “LOG_DEBUG”, “true”
在manifest文件的占位符 manifestPlaceholders = [UMENG_CHANNEL_VALUE: “xxx”]
获取AndroidManifest文件的值

 /**
   * 不同的类型要区别获取,以下是String类型的
   * @param context 上下午
   * @param metaName meta-data定义的名字
   * @param defaultValue 默认值
   * @return
   */
  public static String getAppMetaDataString(Context context, String metaName, String defaultValue) {
    try {
      //application标签下用getApplicationinfo,如果是activity下的用getActivityInfo
      //Sting类型的用getString,Boolean类型的getBoolean,其他具体看api
      String value = context.getPackageManager()
            .getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA)
          .metaData.getString(metaName, defaultValue);
      return value;
    } catch (PackageManager.NameNotFoundException e) {
      e.printStackTrace();
      return defaultValue;
    }
  }
排除不需要的变体
variantFilter { variant ->
    def names = variant.flavors*.name
    def types = variant.buildType.name
    if (names.contains("abi") && types == "debug") {
        // Gradle ignores any variants that satisfy the conditions above.
        setIgnore(true)
    }
}
迁移至AndroidX

最近把测试项目迁移到了androidX 发现现在迁移已经很方便了,特别是不用手动去解决第三方依赖库
修改gradle.properties文件

  • Refactor - migrate to android x
android.useAndroidX=true    // 使用Android X
android.enableJetifier=true  // 将第三方依赖库也一起迁移到AndroidX!!!
  • 然后将一些迁移错误的例如 ConstraintLayout 全局搜索替换一下 根据提示解决冲突就可以了(包名之类的)

附带网上搜的剔除support库依赖方法

   implementation('第三方库的依赖') { exclude group: 'com.android.support' }

推荐参考:AndroidX终极迁移指南

将依赖包打进去生成的aar

embed "xxxxxx"

依赖冲突与排除等API

● 依赖某个库但排除某些间接依赖 exclude

implementation('some.library:version') {
    exclude module: 'unwanted-module'
}

● 全局指定某个依赖的版本

configurations.all {
    resolutionStrategy {
        force 'some.library:specific-version'
    }
}

● 全局排除某个依赖

allprojects {
    configurations {
        all {
            exclude group: 'com.unwanted.group', module: 'unwanted-module'
            exclude group: 'com.unwanted.group'
        }
    }
}
插件发布
  • 参考
  • 发布插件而不是本地源码运行可以避免一些奇怪的bug
plugins {
    id 'java'
    id 'groovy'
    id 'kotlin'
    id 'maven-publish'
}

dependencies {
    //gradle sdk
    implementation gradleApi()
    //groovy sdk
    implementation localGroovy()
    implementation 'com.android.tools.build:gradle:7.4.2'
    implementation 'com.android.tools.build:gradle-api:7.4.2'
    implementation 'org.ow2.asm:asm:9.1'
    implementation 'org.ow2.asm:asm-util:9.1'
    implementation 'org.ow2.asm:asm-commons:9.1'
}

publishing {
    repositories { RepositoryHandler handler ->
        handler.maven { MavenArtifactRepository mavenArtifactRepository -> //正式仓库
            url '..\\localmaven'
            allowInsecureProtocol = true
            if (url.toString().startsWith("http")) {
                credentials {
                    username = ''
                    password = ''
                }
            }
        }
    }

    publications { PublicationContainer publication ->
        maven(MavenPublication) {
            version '0.0.1'
            artifactId 'TestPlugin'
            groupId 'com.hjl.plugin'
            from components.java
        }
    }
}

Gradle、Kotlin 等版本参考对应关系表
Gradle插件版本与gradle版本
AGP插件版本所需的最低 Gradle 版本
8.18.0
8.08.0
7.47.5
7.37.4
7.27.3.3
7.17.2
7.07.0
4.2.0+6.7.1
4.1.x6.5
4.0.x6.1.1
3.6.x5.6.4
3.5.x5.4.1
3.4.x5.1.1
3.3.x4.10.x
3.2.x4.6.x
3.1.x4.4.x
3.0.x4.1.x
Gradle 版本与kotlin插件版本
KGP versionGradle min and max versionsAGP min and max versions
1.9.06.8.3 – 7.6.04.2.2 – 7.4.0
1.8.206.8.3 – 7.6.04.1.3 – 7.4.0
1.8.06.8.3 – 7.3.34.1.3 – 7.2.1
1.7.206.7.1 – 7.1.13.6.4 – 7.0.4
1.7.06.7.1 – 7.0.23.4.3 – 7.0.2
1.6.206.1.1 - 7.0.23.4.3 - 7.0.2
Gradle versionEmbedded Kotlin versionKotlin Language version
5.01.3.101.3
5.11.3.111.3
5.21.3.201.3
5.31.3.211.3
5.51.3.311.3
5.61.3.411.3
6.01.3.501.3
6.11.3.611.3
6.31.3.701.3
6.41.3.711.3
6.51.3.721.3
6.81.4.201.3
7.01.4.311.4
7.21.5.211.4
7.31.5.311.4
7.51.6.211.4
7.61.7.101.4
8.01.8.101.8
8.21.8.201.8
8.31.9.01.8
引入kotlin的几个依赖
  • kotlin标准库 "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${Android.kotlinVersion}"
  • kotlin协程 "org.jetbrains.kotlinx:kotlinx-coroutines-android:${Android.kotlinVersion}"
  • androidx拓展库 "androidx.core:core-ktx:1.6.0"
AndroidStudio版本与kotlin插件版本
Android Studio 版本Kotlin 插件版本Kotlin 版本
3.0.x1.2.x1.2.x
3.1.x1.2.x - 1.2.611.2.x
3.2.x1.3.x - 1.3.501.3.x
3.3.x1.3.x - 1.3.501.3.x
3.4.x1.3.x - 1.3.501.3.x
3.5.x1.3.x - 1.3.501.3.x
3.6.x1.3.x - 1.3.721.3.x
4.0.x1.4.x - 1.4.311.4.x
4.1.x1.4.x - 1.4.311.4.x
4.2.x1.5.x - 1.5.211.5.x
4.3.x1.5.x - 1.5.211.5.x
2020.1.x1.4.x - 1.4.311.4.x
2020.2.x1.4.x - 1.4.311.4.x
2020.3.x1.4.x - 1.4.311.4.x
4.4.x1.6.x1.6.x

疑难杂症

解决在Java7的项目引用了Java8的第三方库:
  1. 将工程和模块的JavaVersion设置为 Java7语言
  2. defalutConfig 里配置 jackOptions{ enable = true}
  3. 升级至Java8,可能遇到乱七八糟的问题可以通过一起升级gradle版本解决
第三方依赖冲突
  • exclude 语法,剔除冲突文件
  • 通过删除jar包里面相关的类(直接解压缩删除相关类)
多种风味,设置默认打包渠道,否则可能会导致打不进去包
        // gradle 插件3.0后无效
        defaultPublishConfig "guestDebug"
        publishNonDefault true
接入三方aar,或者遇到 java.lang.NoClassDefFoundError 问题

问题背景:接入的方法数超过65536,开启multidex分包;
解决:
- 网上查询了资料发现5.0以下的系统,分包可能会导致通过library的类分到不同的包找不到,需要配置一下哪些类在主dex;或者配置dexOptions的一个选项:

    dexOptions{
         preDexLibraries = true
    }
  • 然后还是不解决,并且我的机子是5.0以上的系统,应该不存在这个问题,检查各类资源文件后发现so库的架构和之前的不一样了,配置相关选项解决(坑了我差不多一个星期)
    ndk {  
         abiFilters  'armeabi' 
    //      abiFilters  'armeabi-v7a' 
    }
Unable To Merge Dex
  • 检查是否第三方aar包与已引入的依赖库冲突,查看日志一般可以看到冲突的类: Multiple dex files define:Lcom.xxx.xxx.xxx

删除相关依赖包或者其他方式解决

  • 如果没有提示冲突类,检查依赖aar、jar等是否重复,比如升级SDK忘记删掉老的aar包会报这个错误
  • 使用exclude 排除
Failed to execute aapt

报错:

  • com.android.ide.common.process.ProcessException Failed to execute aapt…
  • …with arguments {package -f --no-crunch -I
  • …finished with non-zero exit value 1-3

解决:

  • 先检查所需要的资源、库有没有打入,一般是少了某项资源比如supportv4包没有打入
  • 检查buildtools 和compileSdkVersion 版本是否对应得上
module层级依赖,遇到风味(productFlavors )缺失的问题

场景: module A 依赖了 moduleB ,B中有许多中风味例如 :flavor1、flavor2,但是A没有,此时会报错
解决方法:

  • 给A或者B加上相应的风味,让他们能够匹配到
  • 在A的风味中加上 matchingFallbacks
        flavorDimensions "default" 
        productFlavors {    
        "moduleAFlavor" {       
             dimension "default" // 每个风味必须制定一个demension维度
             ...  
             matchingFallbacks = ['flavor1','flavor2'] 
        }

在BuildType 也可以用相同的方法解决BuildType缺失的问题

library中有某个demension维度,但是app中没有
// In the app's build.gradle file.
android {
    defaultConfig{
        // 下面这句话告诉gradle,当遇到一个module中有个app中没有的'minApi'维度时,
        // 它应该按照下面这个顺序去匹配这个维度的flavors
        missingDimensionStrategy 'minApi', 'minApi18', 'minApi23'
        // 若其他module中还有更多app中没有的维度,你必须为所有的维度定义回退策略
        missingDimensionStrategy 'abi', 'x86', 'arm64'
    }
    flavorDimensions 'tier'
    productFlavors {
        free {
            dimension 'tier'
            // 你可以在一个特定的flavor中覆盖defaultConfig的配置
            missingDimensionStrategy 'minApi', 'minApi23', 'minApi18'
        }
        paid { }
    }
}
集成第三方SDK android.arch.core.util.Funtion缺少

集成小米单机游戏SDK 发现出现这个问题,文档要求集成V4的27.1.1的库,项目使用了26.1.0,出现这个问题 升级库即可,一般是使用的support版本不匹配

Android Studio 3.6以上版本关闭gradle离线版本

加完库依赖发现报错,原来是开启了离线模式,找了下设置居然没找到关掉离线模式的开关,搜了下发现移动到右侧gradle这边了
在这里插入图片描述

Path ‘xxxx’ is not a readable directory.

clean后仍然无法解决,搜了下 stackoverflow 删除 .gradle文件夹 后正常编译

No resource found that matches the given name: attr ‘colorPrimaryDark’.

发现这个是这个SDK引用到了 AppCompat库的东西,而文档未告知,所以Theme.AppCompat.Light.DarkActionBar相关主题就报错了,引入com.android.support:appcompat-v7:27.1.1 后解决(具体版本号根据项目而定)

强制刷新gradle依赖&& 发布到Maven
  • Windows:
    gradlew build --refresh-dependencies
    gradle build --refresh-dependencies
  • Mac:
    ./gradlew build --refresh-dependencies
AndroidManifest 读取纯数字meta值错误

最近接入小米SDK的时候appkey 和 appid 都是纯数字,最后发现取值的时候被解析成int类型导致取不到值,其实应该是一个string类型的key;解决方法:

在需要被当成string类型的纯数字参数加一个斜杆: / ;
比如数值 1234567890,需要写成 /1234567890

java.lang.AbstractMethodError: org.jetbrains.plugins.gradle.tooling.util.ModuleComponentIdentifierIm

Android Studio 版本太低 尝试用高版本打开

打包打不进so库

这个问题比较奇葩,查看日志发现压缩so库资源的task被跳过了,在so库路径设置正确的情况下:

    1. 设置NDK环境
    1. 检查自己的gradle脚本 是否跳过了此任务(例如含debug字段)
Application需要继承不同的SDK基类
Android X 转移开启的Jetifier导致编译缓慢

推荐参考解决:再见,Jetifier

新版本AS gradle JDK需要依赖Java11

在这里插入图片描述
在这里插入图片描述

新版AS debug gradle插件

直接这样执行,原先监听端口方式无效
在这里插入图片描述

Android studio Installed Build Tools revision 31.0.0 is corrupted. Remove and install again
  • 出现原因:高版本AS下载的SDK在低版本的AS上面使用(新版不兼容)
  • 解决方案:将 SDK路径\build-tools\31.0.0(SDK版本),目录下的d8.batd8.jar改为/复制 一个为dx.batdx.jar (\lib 目录下)
  • 参考
JDK版本错误JAXBException或unrecognized Attribute name MODULE
  • 背景:一般出现其中一个,只要切换JDK版本即可,但是在改老项目的时候发现改了一个错误就报另一个错误
  • 原因:查找后发现是打开了DataBinding影响的,查找资料后发现是因为DataBinding 需要的build tools版本为4.0以上,升级版本即可解决
dex 分包,方法数超过65536
  • 需要开启dex分包,参考
java kotlin混编模块居然找不到java类引用?
  • 发现模块引用正常,打包出来的aar居然没有kotlin的类,检查后发现没有带上kotlin插件,带上就好了
plugins {
    id 'com.android.library'
    id 'org.jetbrains.kotlin.android'
}
升级gradle版本及build tools导致could not find the AndroidManifest.xml file, using generation folder

老项目找不到AndroidManifest文件导致编译不过,添加以下配置即可

defaultConfig {
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [
                        "androidManifestFile": "$projectDir/src/main/AndroidManifest.xml".toString()
                ]
            }
        }
    }
开启混淆:java.io.IOException: Please correct the above warnings first.
What went wrong:
Execution failed for task ':android_sdk:proguardJar'.
> java.io.IOException: Please correct the above warnings first.
  • 报出的警告太多
  1. 根据提示解决警告
  2. 忽略或者直接不混淆一些错误比较多的非关键类
# proguard-rules.pro 文件

#不警告编译过程中的警告:Please correct the above warnings first
#-dontwarn com.mobile.emm.**
升级三方库crash java.lang.NoSuchMethodError: No static method metafactory

三方库使用了lambda表达式,但是当前sdk的编译版本依然是JDK7 ,需要将当前SDK module以及app module改为JDK8

android {

   ...
       compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
       }
   ...
}
新版AS 编译老工程错误 java.lang.IllegalAccessError: class org.jetbrains.kotlin.kapt3.base.KaptContext cannot access class

jdk版本不对,切换为老的JDK11解决。

新版AS 编译老工程提示签名错误 java.security.NoSuchAlgorithmException: Algorithm HmacPBESHA256 not available

一样也是JDK版本不对,如果切换回老的版本后还是不行,查看是不是用了默认的debug的签名秘钥,如果是的话把他删除或者删除整个.android文件夹。这个问题多半是先安装了新的再安装了老板的android studio

maven-publish 上传nexus失败 sha-256/sha-512 校验失败
Cannot upload checksum for module-maven-metadata.xml because the remote repository doesn't support SHA-512. This will not fail the build

# gradle.properties
# 加入此项配置
systemProp.org.gradle.internal.publish.checksums.insecure=true
DataBinding is null

● 表现

编译没问题,运行时直接报错,提示databinding 为空;
查看databinding生成的 DataBinderMapperImpl#collectDependencies 发现各个模块虽然有生成对应的类,但是没有被添加到这个方法里面

  • 解决方法

由于存在多种可能,可以按以下依次排查

  1. 模块以及依赖的模块均开启了databinding dataBinding { enable = true}
  2. 使用了kotlin、检查模块是否应用了kapt
  3. 可能存在同个模块生成的相同类名的 DataBinderMapperImpl被覆盖了,使用不同包名或者不同的 namesapace,参考 这篇文章
  4. 如果存在gradle插件,检查应用的 android build tools依赖,将 com.android.tools.build:gradle:7.4.2 替换为 com.android.tools.build:gradle-api:7.4.2 可以解决
AGP 8.0 升级问题
模块化工程无法引用到子模块的资源路径,编译报错
android.nonTransitiveRClass=false
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值