1. 程式人生 > >重複引用jar包和造成64k問題的解決方法

重複引用jar包和造成64k問題的解決方法

今天打包app,打包失敗,丟擲一個異常:

Error:The number of method references in a .dex file cannot exceed 64K.
Learn how to resolve this issue at https://developer.android.com/tools/building/multidex.html

意思是,你的程式碼過多,超過規定的64K,也就是65536個函數了!好在官方給了一個網址,上面有詳細的解決過程

去掉重複引用的jar包

不過,在解決之前,也得先去掉重複引用的jar包,但是編譯的時候並不會說明我們引用的工程哪裡引用了jar包,可以使用

gradlew -q dependencies ySILSP_DRIVERSINGLE:dependencies --configuration compile

查詢各個專案下的依賴包

配置方法數超過 64K 的應用

步驟1

如果您的 minSdkVersion 設定為 21 或更高值,您只需在模組級 build.gradle 檔案中將 multiDexEnabled 設定為 true,如此處所示:

android {
    defaultConfig {
        ...
        minSdkVersion 21 
        targetSdkVersion 25
multiDexEnabled true } ... }

但是,如果您的 minSdkVersion 設定為 20 或更低值,則您必須按如下方式使用 Dalvik 可執行檔案分包支援庫:

修改模組級 build.gradle 檔案以啟用 Dalvik 可執行檔案分包,並將 Dalvik 可執行檔案分包庫新增為依賴項,如此處所示:

android {
    defaultConfig {
        ...
        minSdkVersion 15 
        targetSdkVersion 25
        multiDexEnabled true
    }
    ...
} dependencies { compile 'com.android.support:multidex:1.0.1' }

步驟2

根據是否要替換 Application 類,執行以下操作之一:

如果您沒有替換 Application 類,請編輯清單檔案,按如下方式設定 標記中的 android:name:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    <application
            android:name="android.support.multidex.MultiDexApplication" >
        ...
    </application>
</manifest>

如果您替換了 Application 類,請按如下方式對其進行更改以擴充套件 MultiDexApplication(如果可能):

public class MyApplication extends MultiDexApplication { ... }

或者,如果您替換了 Application 類,但無法更改基本類,則可以改為替換 attachBaseContext() 方法並呼叫 MultiDex.install(this) 來啟用 Dalvik 可執行檔案分包:

public class MyApplication extends SomeOtherApplication {
  @Override
  protected void attachBaseContext(Context base) {
     super.attachBaseContext(base);
     MultiDex.install(this);
  }
}

構建應用後,Android 構建工具會根據需要構建主 DEX 檔案 (classes.dex) 和輔助 DEX 檔案(classes2.dex 和 classes3.dex 等)。然後,構建系統會將所有 DEX 檔案打包到您的 APK 中。

執行時,Dalvik 可執行檔案分包 API 使用特殊的類載入器來搜尋適用於您的方法的所有 DEX 檔案(而不是僅在主 classes.dex 檔案中搜索)。

宣告主 DEX 檔案中需要的類

如果啟動期間需要的任何類未在主 DEX 檔案中提供,那麼您的應用將崩潰並出現錯誤 java.lang.NoClassDefFoundError。

如果您收到 java.lang.NoClassDefFoundError,則必須使用構建型別中的 multiDexKeepFile 或 multiDexKeepProguard 屬性宣告它們,以手動將這些其他類指定為主 DEX 檔案中的必需項。如果類在 multiDexKeepFile 或 multiDexKeepProguard 檔案中匹配,則該類會新增至主 DEX 檔案。

multiDexKeepFile 屬性

您在 multiDexKeepFile 中指定的檔案應該每行包含一個類,並且採用 com/example/MyClass.class 的格式。例如,您可以建立一個名為 multidex-config.txt 的檔案,如下所示:

com/example/MyClass.class
com/example/MyOtherClass.class

然後,您可以按以下方式針對構建型別宣告該檔案:

android {
    buildTypes {
        release {
            multiDexKeepFile file 'multidex-config.txt'
            ...
        }
    }
}

請記住,Gradle 會讀取相對於 build.gradle 檔案的路徑,因此如果 multidex-config.txt 與 build.gradle 檔案在同一目錄中,以上示例將有效。

multiDexKeepProguard 屬性

multiDexKeepProguard 檔案使用與 Proguard 相同的格式,並且支援整個 Proguard 語法。如需瞭解有關 Proguard 格式和語法的詳細資訊,請參閱 Proguard 手冊中的 Keep Options 一節。

您在multiDexKeepProguard 中指定的檔案應該在任何有效的 ProGuard 語法中包含 -keep 選項。例如,-keep com.example.MyClass.class。您可以建立一個名為 multidex-config.pro 的檔案,如下所示:

-keep class com.example.MyClass
-keep class com.example.MyClassToo

如果您想要指定包中的所有類,檔案將如下所示:

-keep class com.example.** { *; } // All classes in the com.example package

然後,您可以按以下方式針對構建型別宣告該檔案:

android {
    buildTypes {
        release {
            multiDexKeepProguard 'multidex-config.pro'
            ...
        }
    }
}

縮短耗時更長的 Dalvik 可執行檔案分包輸出構建時間

注意:使用Instant Run時,如果專案中的minSdkVersion引數設為21或更高版本,Android Studio編譯執行時會自動使應用支援multidex。但Instant Run僅僅作用於debug版本,我們依然需要給release版本配置multidex來避開64K方法數的限制。

為了縮短耗時更長的 Dalvik 可執行檔案分包輸出構建時間,請利用 productFlavors(一個開發定製和一個釋出定製,具有不同的 minSdkVersion 值)建立兩個構建變型。

對於開發定製,將 minSdkVersion 設定為 21。該設定將啟用一個名為 pre-dexing 的構建功能,此功能使用僅適用於 Android 5.0(API 級別 21)和更高版本的 ART 格式更快生成 Dalvik 可執行檔案分包輸出。對於釋出定製,將 minSdkVersion 設定為適於您的實際最低支援級別。此設定生成的 Dalvik 可執行檔案分包 APK 可相容更多裝置,但構建時間更長。

以下構建配置示例展示瞭如何在 Gradle 構建檔案中設定這些定製:

android {
    defaultConfig {
        ...
        multiDexEnabled true
    }
    productFlavors {
        dev {
            // Enable pre-dexing to produce an APK that can be tested on
            // Android 5.0+ without the time-consuming DEX build processes.
            minSdkVersion 21
        }
        prod {
            // The actual minSdkVersion for the production version.
            minSdkVersion 14
        }
    }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                                                 'proguard-rules.pro'
        }
    }
}
dependencies {
    compile 'com.android.support:multidex:1.0.1'
}

這些構建的 APK 只能用於在 Android 5.0 裝置上進行測試。

然後又有問題了,你會發現打包的時候會失敗,這是記憶體配置太小了。此時還是在gradle,android的節點下加入:

這裡寫圖片描述

因為我的電腦是8G記憶體,所以打包的時候我選擇了分配4G。

統計方法

儘管安卓系統支援multidex,我們還是要學會分析我們的應用,檢視各個部分的方法數,減少冗餘方法。這裡推薦幾個工具,幫助我們分析。

一個線上統計 Android Library 方法數的網站,能夠統計出Android領域常見libraries的方法數、JAR檔案和DEX檔案大小,並且能夠選擇不同版本,以圖表的形式展示出來。

這裡寫圖片描述

該網站也提供了Android Studio的外掛,幫助我們分析專案中所依賴的libraries的方法數,如圖所示:

Android Methods Count
A simple Studio/IntelliJ plugin that parses your Android library dependencies and shows the methods count as an handy hint.

這裡寫圖片描述

For more information, you can simply tap on the blue circle to the left and you will land on the appropriate library page of this website.

這裡寫圖片描述

Installation
Open Android Studio / IntelliJ IDEA preferences
Select ‘Plugins’
Select ‘Browse repositories…’
Select ‘Android Methods Count’ (or type some keywords in the search box)
Press install and restart the IDE once the installation completes

一個線上統計 APK 檔案方法數的開源專案,只需要將需要分析的APK檔案拖拽上傳至此,即可得到分析結果,如圖:

這裡寫圖片描述

最後,要重磅推薦Android Studio自帶的APK Analyzer,功能齊全,使用方便,絕對是安卓開發人員分析應用的不二選擇。使用 Android Studio APK Analyzer ,我們至少能夠做到:

  • 檢視APK壓縮檔案中各個子檔案的大小(如DEX和resource檔案)

  • 理解DEX檔案的結構

  • 快速檢視APK檔案的版本資訊(直接檢視AndroidManifest.xml內容)

  • 直觀地比較兩個APK檔案內容

這裡寫圖片描述

開發階段使用Android Studio開啟一個專案時,有三種方式使用APK Analyzer工具:

  • 直接拖拽APK檔案到Android Studio的編輯視窗

  • 雙擊開啟專案目錄app/build/outputs/apk/下的APK檔案

  • 點選選單欄Build->Analyse APK…並選擇APK檔案

其他

參考