2014-09-01 40 views
8

我面临这个问题java.lang.IllegalArgumentException: method ID not in [0, 0xffff]: 65536,我决定从dex文件中排除一些方法。我gradle.build:方法限制64K每个Android中的dex文件

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/6002797source ./dex.sh; dex-method-count-by-package test.apk

使用的代码片段从反向的答案

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 
... 

之前使用的代码片段从反向的后答案,包:广告,游戏等被删除。

回答

9

更新 - 谷歌Play服务6.5(14年12月8日)

随着6.5版本的谷歌终于拆零的谷歌游戏服务。所以从现在开始,将有可能有选择地将API编译到您的可执行文件中。

例(仅使用AdMob和Android穿戴API)的

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

对于所有其他个别谷歌播放服务API检查this page on d.android.com

注意:通常不鼓励使用+。截至目前,当前正确的版本将是6.5.87。欲了解更多信息,请参阅official Blog-Post (click)


前一段时间还有的是对Medium.com的一篇名为"[DEX] Sky’s the limit? No, 65K methods is"(绝对值得一读),它描述了一种谷歌播放服务用shell脚本,你可以找到here (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 task to strip unused packages on Google Play Services library @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/**" 

这将删除除Maps-和GCM-部分的一切。

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

+0

我还加了'exclude“com/google/android/gms/fitness/**”' – Vladimir 2014-09-02 09:44:39

相关问题