Использование Gradle для разделения внешних библиотек в отдельных файлах dex для решения Android Dalvik 64k ограничивает методы
есть proper/easy
способ решить ограничение методов 64k с помощью Gradle?
Я имею в виду некоторые пользовательские задачи Gradle использовать предварительно дексед банки для создания отдельных файлов dex, а не один classes.dex
.
спасибо
Иван
текущее состояние
в настоящее время я борюсь с GMS: он приносит 20k методы для использования аналитики. Я использую Proguard, чтобы снять то, что не нужно, но все же... 72k методы и подсчет...
I может разделить classes.dex
в двух файлах с помощью dx
параметр --multi-dex. Я достиг этого вручную редактирования
sdk/build-tools/android-4.4W/dx
и редактирование последней строки следующим образом:
exec java $javaOpts -jar "$jarpath" --multi-dex "$@"
мой файл APK теперь содержит __classes.dex__ and __classes2.dex__
.
Я пытаюсь динамически загружать второй файл с помощью нескольких методов:
к сожалению, до сих пор не повезло. Я действительно надеюсь, что некоторые гуру Google/Facebook/Square могут предоставить правильное решение.
4 ответов
обновление для Android Gradle плагин 2.2.0: невозможно получить доступ к dex
задач больше, но в обмен additionalParameters
был введен как часть dexOptions
. Используйте его как
android {
dexOptions {
additionalParameters += '--minimal-main-dex'
// additionalParameters += '--main-dex-list=$projectDir/<filename>'.toString()
// additionalParameters += '--set-max-idx-number=55000'
}
}
обновление для Android Gradle плагин 0.14.0: теперь есть прямая поддержка multi-dex через новый multiDexEnabled true
директива (требуется build-tools 21.1.0, поддержка репозитория версии 8 и Android Studio 0.9).
оригинальный ответ: никогда так как Gradle Android плагин 0.9.0 вы на самом деле can передать --multi-dex
to dx
, добавив это к вам приложение в :
afterEvaluate {
tasks.matching {
it.name.startsWith('dex')
}.each { dx ->
if (dx.additionalParameters == null) {
dx.additionalParameters = ['--multi-dex']
} else {
dx.additionalParameters += '--multi-dex'
}
// Add more additional parameters like this:
dx.additionalParameters += '--main-dex-list=class-list.txt'
dx.additionalParameters += '--minimal-main-dex'
}
}
для создание он несколько файлов dex. На самом деле использовать несколько файлов dex, взгляните на https://github.com/casidiablo/multidex (который является вилкой предстоящей библиотеки поддержки MultiDex от Google).
в случае, если gms была вашей проблемой, и вы используете gradle
начиная с GMS версии 6.5 вы можете выбрать отдельные библиотеки API
например, чтобы включить только API Карт:
compile 'com.google.android.gms:play-services-maps:6.5.87'
и вот полный список :
com.google.android.gms:play-services-base:6.5.87
com.google.android.gms:play-services-ads:6.5.87
com.google.android.gms:play-services-appindexing:6.5.87
com.google.android.gms:play-services-maps:6.5.87
com.google.android.gms:play-services-location:6.5.87
com.google.android.gms:play-services-fitness:6.5.87
com.google.android.gms:play-services-panorama:6.5.87
com.google.android.gms:play-services-drive:6.5.87
com.google.android.gms:play-services-games:6.5.87
com.google.android.gms:play-services-wallet:6.5.87
com.google.android.gms:play-services-identity:6.5.87
com.google.android.gms:play-services-cast:6.5.87
com.google.android.gms:play-services-plus:6.5.87
com.google.android.gms:play-services-appstate:6.5.87
com.google.android.gms:play-services-wearable:6.5.87
com.google.android.gms:play-services-all-wear:6.5.87
пример разбиения проекта и загрузки различных файлов dex можно найти здесь:
https://code.google.com/p/android-custom-class-loading-sample/
EDIT: для Gradle у вас уже есть ответ
загрузка пользовательского класса в Dalvik с Gradle (новая система сборки Android)
Я сопровождающий https://github.com/creativepsyco/secondary-dex-gradle/ и я gradle n00b, поэтому я выбрал путь скриптов BASH, хотя я думаю, что это можно сделать непосредственно в файле сборки. Или может быть переработан для запуска в качестве плагина, я мог бы сделать это, когда я до соглашения с Gradle. Вот причина моей логики.
чтобы понять, как разделить DEX, вы должны знать порядок задач системы сборки. Если вы используете gradle, то вы необходимо знать, что существует ряд задач, вводимых внутри цикла сборки.
например:
:sdk:processReleaseJavaRes UP-TO-DATE
:sdk:packageReleaseJar
:sdk:compileReleaseNdk UP-TO-DATE
:sdk:packageReleaseJniLibs UP-TO-DATE
:sdk:packageReleaseLocalJar UP-TO-DATE
:sdk:packageReleaseRenderscript UP-TO-DATE
:sdk:packageReleaseResources UP-TO-DATE
:sdk:bundleRelease
:app:prepareComAndroidSupportAppcompatV71910Library UP-TO-DATE
:app:prepareComFacebookAndroidFacebook3141Library UP-TO-DATE
:app:prepareDebugDependencies
:app:compileDebugAidl UP-TO-DATE
:app:compileDebugRenderscript UP-TO-DATE
:app:generateDebugBuildConfig UP-TO-DATE
:app:generateDebugAssets UP-TO-DATE
:app:mergeDebugAssets UP-TO-DATE
:app:generateDebugResValues UP-TO-DATE
:app:generateDebugResources UP-TO-DATE
:app:mergeDebugResources UP-TO-DATE
:app:processDebugManifest UP-TO-DATE
:app:processDebugResources UP-TO-DATE
:app:generateDebugSources UP-TO-DATE
:app:compileDebugJava
:app:preDexDebug
:app:dexDebug
:app:processDebugJavaRes UP-TO-DATE
:app:validateReleaseConfigSigning
:app:packageDebug
:app:zipalignDebug
:app:assembleDebug
для того, чтобы сделать Дексинг, вы должны иметь возможность вводить свою пользовательскую задачу между DeX* и задачами процесса*. Если вы можете это сделать, то многократное Дексирование становится легким.
сценарий Bash здесь по существу делает это, если вы изучите задачу отладки, она будет в основном:
- получить файл библиотеки Jar в dex, обычно это build specific & существует в
exploded-aar
папка для библиотек Android и запустить инструмент DEX на нем - скопируйте это в папку assets, которая существует в папке final libs для упаковки внутри приложения
- все ресурсы библиотеки и т. д. уже объединены, что означает, что необходимо снова распаковать и zip-файл.
// For Debug simply remove the library from getting dex and create it
//----------------------- Extra Debug Step ----------------//
def libraryFiles = new ArrayList<?>()
def secondaryFile = new ArrayList<?>()
variant.dex.libraries.each {
File file ->
if (!file.absolutePath.contains("lib/unspecified/classes.jar")) {
libraryFiles.add(file)
} else {
secondaryFile.add(file)
}
}
variant.dex.libraries = libraryFiles
//----------------------- Extra Debug Step ----------------//
packagingTask.dependsOn variant.javaCompile
}
это вручную удаляет библиотеку из получать dexed, так что он может быть создан с помощью bash-скрипт.
Я думаю, вы можете выяснить дэсин в процессе освобождения таким же образом. Другая важная вещь, чтобы отметить, что задача Proguard контролируется Android Gradle плагин, и вы не можете изменить многое об этом. Проблема с правилами должны быть:
- каждый проход proguard отличается, мы не хотим оказаться в ситуации, когда наши 2 Декса имеют разные отображения proguard
- это оставляет нас в ситуации, где мы не должны быть наши библиотеки, но это не очень желательно.
- необходимо создать файл dex после proguard, чтобы убедиться, что сопоставления одинаковы. Gradle не поддерживает слияние активов после Proguard (мы хотим поместить файлы dex в папку assets)
другой важный кусок кода находится в SecondaryDex.java который по существу загружает второй файл dex и вводит путь файла DEX в путь класса среды выполнения. Вы можете оптимизировать это и просто ввести путь вместо чтения файла DEX каждый раз, когда приложение возобновляется.
Я сделал вторичный эксперимент Dex на сервисах Google Play (который добавляет методы 20K) и смог отделиться в отдельный файл DEX. Таким образом, мой основной файл dex не влияет на раздувание в службах Google Play.
чтобы понять, как работает цикл задач Gradle, вы можете обратиться к BasePlugin.в Groovy Источник, вы можете видеть, что трудно контролировать некоторые аспекты, пока нет надлежащего API для доступа к вариантным объектам и задачам сборки.