Android中每个dex文件的方法限制为64K

我遇到了这个问题java.lang.IllegalArgumentException: method ID not in [0, 0xffff]: 65536 ,我决定从dex文件中排除一些方法。 我的gradle.build:

 compile ('com.google.android.gms:play-services:+') { exclude group: "com.google.android.gms.analytics" exclude group: "com.google.android.gms.games" exclude group: "com.google.android.gms.plus" exclude group: "com.google.android.gms.drive" exclude group: "com.google.android.gms.ads" } 

我认为这段代码是错误的,因为错误method ID not in [0, 0xffff]... 。 如何排除Google Play服务的不必要部分? 我只使用地图和GCM。

更新。

谢谢reVerse。 这是非常有用的代码。 有一个获取方法的脚本(也可以看到现有的软件包的名称) https://gist.github.com/JakeWharton/6002797 ( source ./dex.sh; dex-method-count-by-package test.apk

在使用reVerse的答案代码片段之前

 Count of methods / Package ... 22484 com.google.android.gms 2 com.google.android.gms.actions 578 com.google.android.gms.ads 152 com.google.android.gms.ads.doubleclick 25 com.google.android.gms.ads.identifier 86 com.google.android.gms.ads.internal 86 com.google.android.gms.ads.internal.rawhtmlad 86 com.google.android.gms.ads.internal.rawhtmlad.client 88 com.google.android.gms.ads.mediation 4 com.google.android.gms.ads.mediation.admob 73 com.google.android.gms.ads.mediation.customevent 26 com.google.android.gms.ads.purchase 118 com.google.android.gms.ads.search ... 858 com.google.android.gms.games.internal.api 43 com.google.android.gms.games.internal.constants 8 com.google.android.gms.games.internal.data 31 com.google.android.gms.games.internal.events 9 com.google.android.gms.games.internal.experience 215 com.google.android.gms.games.internal.game 56 com.google.android.gms.games.internal.multiplayer 23 com.google.android.gms.games.internal.notification 80 com.google.android.gms.games.internal.player 86 com.google.android.gms.games.internal.request ... 

在使用reVerse的答案代码片段之后,软件包:广告,游戏等被删除。

Solutions Collecting From Web of "Android中每个dex文件的方法限制为64K"

更新 – Google Play Services 6.5(12-08-14)

随着版本6.5谷歌终于把Google Play服务解绑。 所以从现在开始,可以select性地将API编译成可执行文件。

示例(仅使用AdMob和Android Wear API)

 compile 'com.google.android.gms:play-services-wearable:6.5.+' compile 'com.google.android.gms:play-services-ads:6.5.+' 

对于所有其他个人Google Play服务API,请在d.android.com上查看此页面 。

注意:使用+通常是不鼓励的。 截至目前正确的版本将是6.5.87 。 欲了解更多信息,请参阅官方的博客文章(点击) 。


前段时间在Medium.com上有一篇名为“[DEX] Sky是极限的文章吗?不,65K方法是” (绝对值得一读),它描述了一种使用shell脚本去除 Google Play服务的方法可以在这里find(google-play-services-strip-script) 。
虽然这是一个选项,但也有一个gradle任务为你做这个:

 def toCamelCase(String string) { String result = "" string.findAll("[^\\W]+") { String word -> result += word.capitalize() } return result } afterEvaluate { project -> Configuration runtimeConfiguration = project.configurations.getByName('compile') ResolutionResult resolution = runtimeConfiguration.incoming.resolutionResult // Forces resolve of configuration ModuleVersionIdentifier module = resolution.getAllComponents().find { it.moduleVersion.name.equals("play-services") }.moduleVersion String prepareTaskName = "prepare${toCamelCase("${module.group} ${module.name} ${module.version}")}Library" File playServiceRootFolder = project.tasks.find { it.name.equals(prepareTaskName) }.explodedDir Task stripPlayServices = project.tasks.create(name: 'stripPlayServices', group: "Strip") { inputs.files new File(playServiceRootFolder, "classes.jar") outputs.dir playServiceRootFolder description 'Strip useless packages from Google Play Services library to avoid reaching dex limit' doLast { copy { from(file(new File(playServiceRootFolder, "classes.jar"))) into(file(playServiceRootFolder)) rename { fileName -> fileName = "classes_orig.jar" } } tasks.create(name: "stripPlayServices" + module.version, type: Jar) { destinationDir = playServiceRootFolder archiveName = "classes.jar" from(zipTree(new File(playServiceRootFolder, "classes_orig.jar"))) { -----> // Specify what should be removed } }.execute() delete { delete (file(new File(playServiceRootFolder, "classes_orig.jar"))) } } } project.tasks.findAll { it.name.startsWith('prepare') && it.name.endsWith('Dependencies') }.each { Task task -> task.dependsOn stripPlayServices } } 

注意:这是从Gradle任务中取出来去除Google Play服务库@GitHubGist上未使用的软件包

您的相关部分是箭头在task.create(...) 。 在那里你需要指定哪些部分应该被删除。 所以在你的情况下,在这里写这样的东西:

 exclude "com/google/ads/**" exclude "com/google/android/gms/analytics/**" exclude "com/google/android/gms/games/**" exclude "com/google/android/gms/panorama/**" exclude "com/google/android/gms/plus/**" exclude "com/google/android/gms/drive/**" exclude "com/google/android/gms/ads/**" exclude "com/google/android/gms/wallet/**" exclude "com/google/android/gms/wearable/**" 

这将删除除地图和GCM部分以外的所有内容。

注意:为了使用它,只需将gradle-task的内容复制到app模块的build.gradle文件的底部build.gradle