使用Gradle是否有proper/easy
方法来解决64k方法限制?
我的意思是使用pre-dexed jar来创建单独的dex文件而不是单个classes.dex
的一些自定义Gradle任务。
谢谢
伊万
目前,我正在与GMS斗争:它引入了20k种方法来使用Google Analytics。我使用Proguard去除了不需要的东西,但仍然...... 72k方法和计数......
我可以使用classes.dex
参数 - multi-dex 将dx
拆分为两个文件。我实现了手动编辑
sdk/build-tools/android-4.4W/dx
并像这样编辑最后一行:
exec java $javaOpts -jar "$jarpath" --multi-dex "$@"
我的APK文件现在包含__classes.dex__ and __classes2.dex__
。
我尝试使用几种方法动态加载第二个文件:
不幸的是仍然没有运气。我真的希望一些Google / Facebook / Square大师可以提供合适的解决方案。
答案 0 :(得分:24)
Android Gradle插件2.2.0的更新:无法再访问dex
任务,但作为{{1}的一部分,additionalParameters
被引入}}。像
dexOptions
Android Gradle插件更新0.14.0:现在通过新的android {
dexOptions {
additionalParameters += '--minimal-main-dex'
// additionalParameters += '--main-dex-list=$projectDir/<filename>'.toString()
// additionalParameters += '--set-max-idx-number=55000'
}
}
指令直接支持多索引(需要build-tools 21.1.0,支持存储库版本8,和Android Studio 0.9)。
原始回答:自从Gradle Android插件0.9.0以来,您实际上可以将multiDexEnabled true
传递给--multi-dex
,只需将其添加到您的应用中即可dx
档案:
build.gradle
到目前为止,创建多个dex文件。要实际使用多个dex文件,请查看https://github.com/casidiablo/multidex(这是Google即将推出的MultiDex支持库的一个分支)。
答案 1 :(得分:8)
如果gms是你的问题并且你正在使用gradle
从gms 6.5版开始,您可以选择单独的API库
例如,仅包含Maps 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
答案 2 :(得分:2)
可以在此处找到分区和加载不同dex文件的示例项目:
https://code.google.com/p/android-custom-class-loading-sample/
编辑:对于Gradle,您已经有了答案
Custom Class Loading in Dalvik with Gradle (Android New Build System)
答案 3 :(得分:2)
我是https://github.com/creativepsyco/secondary-dex-gradle/的维护者,我是gradle n00b,因此我选择了BASH脚本的路径,尽管我认为它可以直接在构建文件中完成。 OR可以重构为一个插件运行,我可能会这样做,当我达到与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
为了做Dexing,您应该能够在dex *和process *任务之间注入自定义任务。如果你能做到这一点,那么Multiple DEXing变得容易了。
Bash脚本here基本上是这样做的,如果你检查调试任务,它基本上会:
exploded-aar
文件夹中在其上运行DEX工具 // 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脚本生成它。
我认为你可以用同样的方式在发布过程中找出dexing。另一个需要注意的重要事项是,Proguard任务由android gradle插件控制,你无法改变它。 Proguard规则问题:
另一个重要的代码块位于SecondaryDex.java,它基本上加载了第二个dex文件&amp;将DEX文件的路径注入运行时类路径。您可以对此进行优化,只需注入路径,而不是每次恢复应用程序时都读取DEX文件。
我在Google Play服务上进行了二级Dex实验(增加了20K方法)并且可以分成单独的DEX文件。这样我的主要dex文件就不会受到Google Play服务中膨胀的影响。
要了解Gradle任务循环的工作原理,您可以参考BasePlugin.groovy源代码,您可以看到,在有适当的API访问变体对象和构建任务之前,很难控制某些方面。 / p>