天天看點

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的坑