如何缩小代码 - dex中的65k方法限制

Jar*_*ler 90 android guava dex google-drive-api android-multidex

我有一个相当大的Android应用程序,它依赖于许多库项目.Android编译器对每个.dex文件有65536个方法的限制,我超过了这个数字.

当你达到方法限制时,你可以选择两种途径(至少我知道).

1)缩小你的代码

2)构建多个dex文件(参见此博文)

我调查了两个并试图找出导致我的方法计数变得如此之高的原因.Google Drive API占据了Guava依赖的最大块,超过12,000.Drive API v2的总库存超过23,000!

我想我的问题是,你认为我该怎么做?我应该删除Google云端硬盘集成作为我应用的功能吗?有没有办法缩小API(是的,我使用proguard)?我应该采用多重dex路由(看起来相当痛苦,尤其是处理第三方API)?

Jar*_*ler 68

看起来谷歌最终实施了一种解决方法/修复方法,超越了dex文件的65K方法限制.

关于65K参考限制

Android应用程序(APK)文件包含Dalvik可执行文件(DEX)文件形式的可执行字节码文件,其中包含用于运行应用程序的编译代码.Dalvik可执行规范将单个DEX文件中可引用的方法总数限制为65,536,包括Android框架方法,库方法和您自己的代码中的方法.超过此限制要求您配置应用程序构建过程以生成多个DEX文件,称为多索引配置.

Android 5.0之前的Multidex支持

Android 5.0之前的平台版本使用Dalvik运行时来执行应用程序代码.默认情况下,Dalvik将应用程序限制为每个APK的单个classes.dex字节码文件.为了解决这个限制,您可以使用multidex支持库,它将成为应用程序主要DEX文件的一部分,然后管理对其他DEX文件及其包含的代码的访问.

适用于Android 5.0及更高版本的Multidex支持

Android 5.0及更高版本使用名为ART的运行时,它本身支持从应用程序APK文件加载多个dex文件.ART在应用程序安装时执行预编译,扫描类(.. N).dex文件并将它们编译成单个.oat文件以供Android设备执行.有关Android 5.0运行时的更多信息,请参阅ART简介.

请参阅:使用超过65K方法构建应用程序


Multidex支持库

该库为使用多个Dalvik可执行文件(DEX)构建应用程序提供支持.使用multidex配置需要引用超过65536种方法的应用程序.有关使用multidex的更多信息,请参阅使用超过65K方法构建应用程序.

下载Android支持库后,此库位于/ extras/android/support/multidex /目录中.该库不包含用户界面资源.要将其包含在应用程序项目中,请按照添加无资源库的说明进行操作.

此库的Gradle构建脚本依赖项标识符如下:

com.android.support:multidex:1.0.+此依赖项表示法指定发行版本1.0.0或更高版本.


您仍应通过主动使用proguard并查看依赖项来避免达到65K方法限制.

  • +1,当同一个人回答时,为什么人们没有正确的答案? (6认同)
  • 我们编写了一个小的Gradle插件,为您提供每个构建的当前方法计数.对我们管理库有帮助 - https://github.com/KeepSafe/dexcount-gradle-plugin (5认同)

Pra*_*har 52

你可以使用multidex支持库来启用multidex

1)将它包含在依赖项中:

dependencies {
  ...
  compile 'com.android.support:multidex:1.0.0'
}
Run Code Online (Sandbox Code Playgroud)

2)在您的应用中启用它:

defaultConfig {
    ...
    minSdkVersion 14
    targetSdkVersion 21
    ....
    multiDexEnabled true
}
Run Code Online (Sandbox Code Playgroud)

3)如果您的应用程序应用程序类,则覆盖attachBaseContext方法,如下所示:

package ....;
...
import android.support.multidex.MultiDex;

public class MyApplication extends Application {
  ....
   @Override
   protected void attachBaseContext(Context context) {
    super.attachBaseContext(context);
    MultiDex.install(this);
   }
}
Run Code Online (Sandbox Code Playgroud)

4)如果您的应用程序没有应用程序类,则在清单文件中将android.support.multidex.MultiDexApplication注册为您的应用程序.像这样:

<application
    ...
    android:name="android.support.multidex.MultiDexApplication">
    ...
</application>
Run Code Online (Sandbox Code Playgroud)

它应该工作正常!


Csa*_*oth 31

Play Services6.5+帮助:http: //android-developers.blogspot.com/2014/12/google-play-services-and-dex-method.html

"从6.5版Google Play服务开始,您将能够从众多个人API中进行选择,您可以看到"

...

"这将传递上包含'基础'库,这些库用于所有API."

这是一个好消息,对于一个简单的游戏,例如你可能只需要base,games也许drive.

"完整的API名称列表如下.更多详细信息可以在Android开发者网站上找到:

  • com.google.android.gms:播放服务基地:87年6月5日
  • com.google.android.gms:播放服务的广告:87年6月5日
  • com.google.android.gms:播放服务,appindexing:87年6月5日
  • com.google.android.gms:播放服务,地图:87年6月5日
  • com.google.android.gms:播放服务地点:87年6月5日
  • com.google.android.gms:播放服务的健身:87年6月5日
  • com.google.android.gms:播放服务全景:87年6月5日
  • com.google.android.gms:播放服务驱动的:87年6月5日
  • com.google.android.gms:游戏服务游戏:87年6月5日
  • com.google.android.gms:播放服务钱包:87年6月5日
  • com.google.android.gms:播放服务身份:87年6月5日
  • com.google.android.gms:播放服务铸:87年6月5日
  • com.google.android.gms:播放服务加:87年6月5日
  • com.google.android.gms:播放服务,APPSTATE:87年6月5日
  • com.google.android.gms:播放服务耐磨:87年6月5日
  • com.google.android.gms:播放服务,所有磨损:87年6月5日


aks*_*hay 9

在6.5之前的Google Play服务版本中,您必须将整个API包编译到您的应用中.在某些情况下,这样做会使您的应用程序中的方法数量(包括框架API,库方法和您自己的代码)在65,536限制下更加困难.

从6.5版开始,您可以选择性地将Google Play服务API编译到您的应用中.例如,要仅包含Google Fit和Android Wear API,请替换build.gradle文件中的以下行:

compile 'com.google.android.gms:play-services:6.5.87'
Run Code Online (Sandbox Code Playgroud)

用这些线:

compile 'com.google.android.gms:play-services-fitness:6.5.87'
compile 'com.google.android.gms:play-services-wearable:6.5.87'
Run Code Online (Sandbox Code Playgroud)

有关更多参考,请单击此处


pet*_*tey 7

使用proguard来减轻你的apk,因为未使用的方法不会在你的最终版本中.仔细检查你的proguard配置文件中是否有以下内容使用带有番石榴的proguard(我很抱歉,如果你已经有了这个,那么在编写时就不知道了):

# Guava exclusions (http://code.google.com/p/guava-libraries/wiki/UsingProGuardWithGuava)
-dontwarn sun.misc.Unsafe
-dontwarn com.google.common.collect.MinMaxPriorityQueue
-keepclasseswithmembers public class * {
    public static void main(java.lang.String[]);
} 

# Guava depends on the annotation and inject packages for its annotations, keep them both
-keep public class javax.annotation.**
-keep public class javax.inject.**
Run Code Online (Sandbox Code Playgroud)

此外,如果您使用的是ActionbarSherlock,切换到v7 appcompat支持库也会减少您的方法数量(基于个人经验).说明位于:


pix*_*xel 7

您可以使用Jar Jar Links缩小巨大的外部库,如Google Play Services(16K方法!)

在您的情况下,您只需从Google Play Services jar common internaldrive子包中删除所有内容.