天天看点

Android探索之旅(第三十三篇)手把手教你跨过学习Android Studio 3.0的坑

过完了快乐的国庆,也该安安心心的投入工作中了。再次趁工作项目不是太赶急,因此闲的蛋疼索性更新AndroidStudio3.0 Update的一下,再次碰到了一些坑,并作以记录

本文大部分出来简书 ThinkNuo &简书 JonathanHsia

1. gradle 和 buildToolsVersion 版本

Android Studio 3.0 要求 gradle 版本为 4.1 ,对应的 buildToolsVersion 为 26.0.2 ,然后记得在项目最外层的 build.gradle 添加 google() ,如果不添加将会导致某些官方依赖下载不了。

buildscript {
    repositories {
        ...
        google()
    }
}
           

2. module 依赖方式变更

原先依赖 module 使用的是 compile ,现在需要替换为 api 或 implementation。

api : module 编译时可用,module 的使用者编译和运行时可用,这个和过时的 compile 一样的。

implementation : module 编译时可用,module 的使用者运行时可用,对于大量使用 library 的项目,可以显著提高编译时间,因为它可以减少构建系统重新编译一些 module 。

那么什么时候用 api ,什么时候用 implementation 呢?由于公司项目采用的是组件化开发,有个 common module 需要被各个组件依赖,一开始采用的是 implementation ,结果发现会导致别的组件无法引用 common 中的库( common -> A module ,A module 无法引用 common 依赖的库 )。

试验过后得出结论,当这个 module 会被多次引用应该使用 api,不会被别的 module 引用使用 implementation 。

发一下我现在使用的方式

dependencies {
    api fileTree(include: ['*.jar'], dir: 'libs')
    api 'com.squareup.okhttp3:okhttp:3.4.2'
    ...
    debugApi 'com.squareup.leakcanary:leakcanary-android:1.5.1'
    releaseApi 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
}
           

3. apt 插件更换

apt 插件已被废弃,需更换为 annotationProcessor 。

//apply plugin: 'android-apt'

dependencies {
    ...
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'
}
           

4.第三方库不兼容问题

· retrolambda

Android Studio 3.0 已经支持 Java 8 了,不需要第三方库来支持,因此需要去掉 retrolambda 库。

项目最外层的 build.gradle

buildscript {
    ...
    dependencies {
        ...
        //classpath 'me.tatarka:gradle-retrolambda:3.2.5'
    }
}
           

module 中的 build.gradle

//apply plugin: 'me.tatarka.retrolambda'

android {
    ...
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    ...
    //retrolambdaConfig 'net.orfjackal.retrolambda:retrolambda:2.3.0'
}
           

· butterknife

butterknife 最新版本为 8.8.0,与 Android Studio 3.0 不兼容,会提示

官方 issue 已经有人提过这个问题,貌似是 gradle 的问题。解决办法:版本降级到 8.5.1 即可解决。

· 项目中同一个第三库有多个版本导致编译失败

不知道是不是 Android Studio 3.0 编译现在比以前严格了,以前有的库没有统一过版本,现在直接编译不过了。解决办法:统一第三方库的版本。

在 Terminal 中输入 gradle app:dependencies (gradle环境配置可以百度)

...
+--- com.meituan.android.walle:library:
|    +--- com.android.support:support-annotations: -> 
|    \--- com.meituan.android.walle:payload_reader:
...
           

如果出现了 com.android.support:support-annotations:24.1.1 -> 25.2.0 代表该库中有自己依赖的库被升级了,需要去除这个依赖。

dependencies {
    ...
    api('com.meituan.android.walle:library:1.1.5') {
        exclude(group: 'com.android.support', module: 'support-annotations')
    }
}
           

group 是 : 前面的包名,: 后面的是 module 名字。

如果依赖的是 jar 包,写法为 exclude(module: ‘libs/xxx.jar’)。

exclude(group: ‘com.android.support’) 是忽略所有 com.android.support 的module。

4.一直卡在Refreshing项目

第一条中的问题解决后,我出现了

Android探索之旅(第三十三篇)手把手教你跨过学习Android Studio 3.0的坑

这种提示,在正常的流程中,如果不出现第一个问题,会首先出现这个提示,意思是升级现在项目的编译插件,相信之前升级过AS版本的同学在第一次运行新版本的时候见过这个提示,直接点击update按钮就行了.如果不想接着踩坑那么点击Dont’t reminmd me againg for this project按钮就可以了,它代表你还是用之前版本的插件来运行当前项目,也就不会出现后面一大串的问题;

这里直接点击update按钮;

点击之后如果你网络不畅通的话就会一直的

Android探索之旅(第三十三篇)手把手教你跨过学习Android Studio 3.0的坑

之所以会这样,是因为

点击该按钮后实际上做了两件事情

  • 在主项目的build.gradle文件中的dependencies节点中更改了
``` gradle
 //原先的插件版本
 classpath 'com.android.tools.build:gradle:2.3.3'
 //更改后的插件版本
 classpath 'com.android.tools.build:gradle:3.0.0'
           
  • 在项目目录中的gradle > gradle-wrapper.properties文件中的distributionUrl字段更改了
``` 
 //原先的插件版本
 distributionUrl=https\://services.gradle.org/distributions/gradle--all.zip
 //更改后的插件版本
 distributionUrl=https\://services.gradle.org/distributions/gradle--all.zip
           

读者需要理会其中的用意就可以了

这两个文件修改后AS就会去下载https://services.gradle.org/distributions/gradle-4.1-all.zip这个文件,不用点什么奇技淫巧,就等AS下载完吧(基本完不了)

这里给出两种解决方案:

两种解决方案的前提条件是先把该文件下载下来,AS下载的奇慢,那么把https://services.gradle.org/distributions/gradle-4.1-all.zip扔到迅雷中,分分钟下载完成(迅雷功能不止于此~);

把文件放到本地的Tomcat服务器,或者IIS服务器中,或者免费的七牛云服务中,获取这个文件的下载地址,修改 gradle-wrapper.properties文件中distributionUrl的值为你的下载地址,关闭AS,重新打开(亲测可行);

找到.gradle文件夹路径:windows一般在 C:\Users<当前登录用户名>.gradle,

mac是在:用户/(当前用户目录)/.gradle,解压下载好的文件到该目录中,关闭AS,重新打开(未亲测);

5.修改输出apk的文件名导致的异常

第二条问题解决后,出现了

Android探索之旅(第三十三篇)手把手教你跨过学习Android Studio 3.0的坑
Cannot set the value of read-only property 'outputFile' for ApkVariantOutputImpl_Decorated{apkData=Main{type=MAIN, fullName=tiger8shopDebug, filters=[]}} of type com.android.build.gradle.internal.api.ApkVariantOutputImpl. Open File

           

点击Open File定位到应用级别的build.gradle文件中的这个位置

static def releaseTime() {
    return new Date().format("yyyy-MM-dd-HH-mm", TimeZone.getDefault())//包含时分秒
}

static def debugTime() {
//    return new Date().format("yyyy-MM-dd", TimeZone.getDefault())
    return new Date().format("yyyy", TimeZone.getDefault())
}

//=============================上面的代码定义在android节点外,AS3.0版本如果需要输出apk文件名带上时间,上面代码你可以参考下===================================

  //文件输出名增加版本号和时间
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def outputFile = output.outputFile
            if (outputFile != null && outputFile.name.endsWith('.apk')) {
                def fileName
                if (outputFile.name.contains("debug")) {//debug版本,使用自己的文件名,方便记忆
                    fileName = "$applicationId _v${defaultConfig.versionName}_${debugTime()}_code${defaultConfig.versionCode}_debug.apk"
                    output.outputFile = new File(outputFile.parent, fileName)//Open File后定位到这个位置,这个配置,识别不出outputFile是啥了
                } else {
                    fileName = "$applicationId _v${defaultConfig.versionName}_code${defaultConfig.versionCode}_${releaseTime()}_${variant.productFlavors[0].name}_release.apk"
                    output.outputFile = new File(outputFile.parent, fileName)
                }
            }
        }
    }
           

这个是自己之前配置的可以控制AS输出的apk文件的名称,新版本不能这样配置了,看官方的引导可以改成

//AS3.版本
    android.applicationVariants.all { variant ->
        variant.outputs.all {
            if (variant.name.endsWith("Debug")) {
                //debug包
                outputFileName = "$applicationId _v${defaultConfig.versionName}_${debugTime()}_code${defaultConfig.versionCode}_debug.apk"
            } else {
                //release包
        outputFileName = "$applicationId _v${defaultConfig.versionName}_code${defaultConfig.versionCode}_${releaseTime()}_release.apk"
            }
        }
    }
           

效果和之前差不多,直接更改,问题KO

6.当然有坑但是也有惊喜,Google 发布最快的 Android 模拟器,一秒快速启动!

过去我们在使用AndroidStudio中自带的模拟器启动比较慢,体验不是太好,逼不得已我们去下载其他第三方的模拟器,随着AndroidStudio3.0强势来袭,相信不会让大家失望

Android探索之旅(第三十三篇)手把手教你跨过学习Android Studio 3.0的坑