Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/196.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Gradle在分离的dex文件中拆分外部库以解决Android Dalvik 64k方法的限制_Android_Gradle_Dalvik - Fatal编程技术网

使用Gradle在分离的dex文件中拆分外部库以解决Android Dalvik 64k方法的限制

使用Gradle在分离的dex文件中拆分外部库以解决Android Dalvik 64k方法的限制,android,gradle,dalvik,Android,Gradle,Dalvik,是否有一种合适/简单的方法可以使用Gradle解决64k方法的限制 我指的是一些定制的Gradle任务,使用预先编制索引的jar来创建单独的dex文件,而不是单个的classes.dex 多谢各位 伊万 现状 目前,我正在与GMS抗争:它带来了2万种使用分析的方法。我用Proguard去掉不需要的东西,但仍然。。。72k方法和计数 我可以使用dx参数将classes.dex拆分为两个文件--multi-dex。我是通过手工编辑实现的 sdk/build-tools/android-4.4W/dx

是否有一种
合适/简单的
方法可以使用Gradle解决64k方法的限制

我指的是一些定制的Gradle任务,使用预先编制索引的jar来创建单独的dex文件,而不是单个的
classes.dex

多谢各位

伊万

现状 目前,我正在与GMS抗争:它带来了2万种使用分析的方法。我用Proguard去掉不需要的东西,但仍然。。。72k方法和计数

我可以使用
dx
参数
classes.dex
拆分为两个文件--multi-dex
。我是通过手工编辑实现的

sdk/build-tools/android-4.4W/dx
然后像这样编辑最后一行:

exec java $javaOpts -jar "$jarpath" --multi-dex "$@"
我的APK文件现在包含
类.dex\uu和类2.dex\uu

我尝试使用以下几种方法动态加载第二个文件:

  • 德克斯
  • 德克斯特
  • 次级指数梯度

不幸的是仍然没有运气。我真的希望一些Google/Facebook/Square专家能提供一个合适的解决方案。

在这里可以找到一个示例项目分区和加载不同的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
为了进行Dexing,您应该能够在dex*和process*任务之间插入自定义任务。如果你能做到这一点,那么多重索引就变得容易了

Bash脚本基本上就是这样做的,如果您检查调试任务,它基本上会:

  • 将库Jar文件获取到dex,通常它是特定于构建的&存在于Android库的
    分解aar
    文件夹中,并在其上运行dex工具
  • 将此复制到资产文件夹,该文件夹位于要打包到应用程序中的最终libs文件夹中
  • 所有的库资源等都已经合并,这意味着需要再次解压缩文件

//对于调试,只需从获取dex中删除库并创建它即可
//-----------------------额外调试步骤----------------//
def libraryFiles=new ArrayList()
def secondaryFile=new ArrayList()
variant.dex.libraries.each{
文件->
如果(!file.absolutePath.contains(“lib/unspecified/classes.jar”)){
libraryFiles.add(文件)
}否则{
secondaryFile.add(文件)
}
}
variant.dex.libraries=库文件
//-----------------------额外调试步骤----------------//
packagingTask.dependsOn variant.javaCompile
}
这将手动删除库的索引,以便可以通过bash脚本生成库

我想你可以用同样的方法计算出发布过程中的索引。另一个需要注意的重要事项是,Proguard任务由android gradle插件控制,您不能对此做太多更改。Proguard规则的问题:

  • proguard的每个过程都是不同的,我们不希望最终出现两个索引具有不同的proguard映射的情况
  • 这使我们处于一种无法改进我们的库的情况下,但这并不是真正需要的
  • 必须在proguard之后生成dex文件,以确保映射相同。Gradle不支持在Proguard之后合并资产(我们希望将dex文件放在资产文件夹中)
另一个重要的代码块驻留在其中,它实质上加载了第二个dex文件&将dex文件的路径注入到运行时类路径中。您可以对此进行优化,只需插入路径,而不是每次应用程序恢复时都读取DEX文件

我在GooglePlay服务上做了第二个Dex实验(增加了20K个方法),并且能够分离成一个单独的Dex文件。这样,我的主dex文件就不会受到googleplay服务膨胀的影响


要了解Gradle任务周期是如何工作的,您可以参考源代码,您可以看到,在有合适的API用于访问各种对象和构建任务之前,很难控制某些方面。

Android Gradle插件2.2.0的更新:无法再访问
dex
任务,但作为交换,
附加参数
作为
dexOptions
的一部分引入。像这样使用它

android {
  dexOptions {
    additionalParameters += '--minimal-main-dex'
    // additionalParameters += '--main-dex-list=$projectDir/<filename>'.toString()
    // additionalParameters += '--set-max-idx-number=55000'
  }
}

到目前为止,他正在创建多个dex文件。要实际使用多个dex文件,请查看(这是Google即将推出的MultiDex支持库的一个分支)。

如果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

它使用蚂蚁。我想使用Gradle。关于编辑:这个解决方案似乎是针对Java的,而不是针对Android的。@hamen:Dalvik with Gradle中的自定义类加载”链接指向一个SO问答,这是关于Dalvik with Gradle中的自定义类加载。你能给我指一些文档来拆分Class.dex吗,莫基托,德克斯。。。然后在运行时加载它们?请注意,如果您的问题仅仅出现在调试版本中,因为发布版本使用ProGuard剥离了足够多的内容,那么启用
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