Резервирование ресурсов в нескольких R.java вызывает DexIndexOverflowException

У меня есть несколько проектов библиотеки, и все они имеют зависимость от Support Library. Мое приложение имеет зависимость от этих проектов с несколькими библиотеками. Каждый проект библиотеки содержит ссылки на ресурсы библиотеки поддержки в файле R.java. Это увеличивает количество идентификаторов полей из-за избыточности.

Мое приложение получает

DexIndexOverflowException: идентификатор поля не в [0, 0xffff]: 65536

из-за этой избыточной ссылки R.java.

Из-за этого у моего приложения есть 47k методов, в то время как идентификаторы полей 65k.

Edit:

Я не буду использовать multi-dex, это не решение моей проблемы. Я хочу сбрить избыточные идентификаторы полей.

Вопрос не в том, как обойти проблему, а в том, как избавиться от избыточных идентификаторов полей. Использование multi-dex не удаляет избыточные идентификаторы полей.

Ответ 1

Как @intellij-amiya ответ, использование multidex или proguard решит вашу проблему, и я лично рекомендую это.

Если вы не хотите следовать этому методу, вы можете вручную исключить дублированные зависимости.

Выполните следующую команду в своем терминале, чтобы найти дублированные зависимости.

./gradlew :app:dependencies --configuration compile

или если вы на окнах,

gradlew.bat :app:dependencies --configuration compile

измените :app как название вашего проекта.

Предположим, что ваши зависимости gradle выглядят следующим образом:

compile 'com.android.support:support-compat:26.+'
compile 'com.android.support:support-fragment:26.+'

Вы получите вывод, как показано ниже:

+--- com.android.support:support-compat:26.+ -> 26.0.0-alpha1
|    \--- com.android.support:support-annotations:26.0.0-alpha1
\--- com.android.support:support-fragment:26.+ -> 26.0.0-alpha1
     +--- com.android.support:support-compat:26.0.0-alpha1 (*)
     +--- com.android.support:support-core-ui:26.0.0-alpha1
     |    +--- com.android.support:support-annotations:26.0.0-alpha1
     |    \--- com.android.support:support-compat:26.0.0-alpha1 (*)
     \--- com.android.support:support-core-utils:26.0.0-alpha1
          +--- com.android.support:support-annotations:26.0.0-alpha1
          \--- com.android.support:support-compat:26.0.0-alpha1 (*)

И вы можете видеть зависимости, отмеченные (*), и эти зависимости можно исключить. Вы можете видеть, что support-compat дублируется, и исключить его можно следующим образом:

compile ('com.android.support:support-fragment:26.+') {
    exclude module: 'support-compat'
}

Повторяя это, пока вы не сможете получить счет ниже 64k

И теперь самая сложная часть остается.

По моему опыту исключение некоторых зависимостей может привести к сбою сборки, исключениям времени выполнения и т.д. Поэтому вам нужно проверить работоспособность приложения без проблем.

Надеюсь на эту помощь.

Ответ 2

DexIndexOverflowException: идентификатор поля не в [0, 0xffff]: 65536

  • Android имеет предварительно определенный верхний limit of Methods of 65536.

Когда?

Размер индекса метода файлов DEX - 16 бит, поэтому это означает, что 65536 представляет общее количество ссылок, которые могут быть вызваны код внутри одного файла DEX. Если вы преодолеете, то возникнет эта ошибка.

После того, как вы начнете включать достаточно библиотек, которые приводят к ограничению метода 64K, вам необходимо удалить посторонние зависимости.

Как? Без использования multiDex

  • Вы должны добавить proguard.

ProGuard оптимизирует байт-код, удаляет неиспользуемые инструкции кода и обфускает оставшиеся классы, поля и методы с короткими names.Resource shrinking доступен с плагином Android для Gradle, который удаляет неиспользуемые ресурсы из вашего упакованного приложения, включая неиспользуемые ресурсы в библиотеках кода. Он работает совместно с сокращением кода, так что после удаления неиспользуемого кода любые ресурсы, которые больше не ссылаются, могут быть также безопасно удалены.

Как включить Proguard

добавить minifyEnabled true в соответствующий тип сборки в вашем файле build.gradle.

android {
    buildTypes {
        release { //You can add this in debug mode
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                    'proguard-rules.pro'
        }
    }

}

Примечание

  • Метод getDefaultProguardFile('proguard-android.txt') получает по умолчанию proguard из Android SDK tools->proguard->folder.

  • В файле proguard-rules.pro вы можете добавить пользовательские правила proguard.

Сокращение ресурсов

Сокращение ресурсов работает только в сочетании с сокращением кода. После того, как усадка кода удалит весь неиспользованный код, усадка ресурса может определить, какие ресурсы все еще использует приложение.

buildTypes {
    release {
              minifyEnabled true
              shrinkResources true  //You can add this in debug mode
    }
}

Ответ 3

Моя проблема решена путем добавления "multiDexEnabled true", как указано в модуле build.gradle.

android {
          ...
          defaultConfig {
                          ...
                          multiDexEnabled true
                         }
         }