過完了快樂的國慶,也該安安心心的投入工作中了。再次趁工作項目不是太趕急,因此閒的蛋疼索性更新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 不兼容,會提示
Caused by: java.lang.NoSuchMethodError: com.android.build.gradle.tasks.ProcessAndroidResources.getPackageForR()Ljava/lang/String;
官方 issue 已經有人提過這個問題,貌似是 gradle 的問題。解決辦法:版本降級到 8.5.1 即可解決。
· 項目中同一個第三庫有多個版本導致編譯失敗
不知道是不是 Android Studio 3.0 編譯現在比以前嚴格了,以前有的庫沒有統一過版本,現在直接編譯不過了。解決辦法:統一第三方庫的版本。
在 Terminal 中輸入 gradle app:dependencies (gradle環境配置可以百度)
...
+--- com.meituan.android.walle:library:1.1.5
| +--- com.android.support:support-annotations:24.1.1 -> 25.2.0
| \--- com.meituan.android.walle:payload_reader:1.1.5
...
如果出現了 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項目
第一條中的問題解決後,我出現了
這種提示,在正常的流程中,如果不出現第一個問題,會首先出現這個提示,意思是升級現在項目的編譯插件,相信之前升級過AS版本的同學在第一次運行新版本的時候見過這個提示,直接點擊update按鈕就行了.如果不想接着踩坑那麼點擊Dont’t reminmd me againg for this project按鈕就可以了,它代表你還是用之前版本的插件來運行當前項目,也就不會出現後面一大串的問題;
這裏直接點擊update按鈕;
點擊之後如果你網絡不暢通的話就會一直的
之所以會這樣,是因爲
點擊該按鈕後實際上做了兩件事情
- 在主項目的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-3.3-all.zip
//更改後的插件版本
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-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的文件名導致的異常
第二條問題解決後,出現了
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.0版本
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強勢來襲,相信不會讓大家失望