Límite de métodos 64K por un archivo dex en Android

Me enfrenté a este problema java.lang.IllegalArgumentException: method ID not in [0, 0xffff]: 65536 y decidí excluir algunos métodos de un archivo dex. Mi 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" } 

Creo que este fragmento de código es incorrecto, porque no hay method ID not in [0, 0xffff]... error method ID not in [0, 0xffff]... ¿Cómo puedo excluir partes innecesarias del servicio de Google Play? Utilizo sólo mapas y GCM.

Actualizado.

Gracias reVerse. Es un código realmente útil. Hay un script para obtener la cuenta de los métodos (también puede ver los nombres de los paquetes existentes) https://gist.github.com/JakeWharton/6002797 ( source ./dex.sh; dex-method-count-by-package test.apk )

Antes de usar el fragmento de código de la respuesta de 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 ... 

Después de usar el fragmento de código de la respuesta de reVerse, los paquetes: anuncios, juegos y etc se eliminaron.

Actualización – Google Play Services 6.5 (12-08-14)

Con la versión 6.5, Google finalmente desagrupó Google Play Services. Así que a partir de ahora será posible compilar selectivamente las API en su ejecutable.

Ejemplo (sólo con las API de AdMob y Android Wear)

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

Para todas las otras API individuales de Google Play Services, consulta esta página en d.android.com .

Nota: El uso del + normalmente no se recomienda. A partir de ahora la versión correcta actual sería 6.5.87 . Para obtener más información, vea la publicación oficial del blog (clic) .


Hace algún tiempo ha habido un artículo en Medium.com llamado "[DEX] Sky es el límite? No, 65K métodos es" (definitivamente vale la pena leer), que describe una manera de despojar a los Servicios de Google Play con un script de shell que usted Puede encontrar aquí (google-play-services-strip-script) .
Si bien esto es una opción, también hay una tarea gradle que hace esto para usted:

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

Nota: se extrae de la tarea Gradle para quitar paquetes no utilizados en la biblioteca de servicios de Google Play @GitHubGist

La parte relevante para usted es donde está la flecha en la task.create(...) . Hay que especificar qué partes se deben quitar. Así que en su caso sólo escribir algo como esto en allí:

 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/**" 

Esto eliminará todo, excepto los mapas y GCM-Part.

Nota: Para usarlo, simplemente copie el contenido de la tarea gradle a la parte inferior del archivo build.gradle del módulo de la aplicación.

  • Android Databinding Compile Advertencia: Referencias de método con '.' es obsoleto
  • Cómo generar buildConfigField con el tipo String
  • No se puede instalar la versión de depuración y de liberación en el mismo dispositivo
  • Cambiar nombre de archivo apk en gradle
  • Gradle excluye las librerías arm64
  • ¿Cómo resolver el error de Android Studio donde no puede encontrar el archivo de manifiesto del proyecto?
  • Android Studio 2.2 pegado en el edificio Gradle Project Información sobre la importación de proyectos existentes
  • Dagger 2 y android Studio: funcionan pero no pueden ver las clases generadas
  • Cómo habilitar la descarga automática de los paquetes de SDK de Android que faltan en Gradle
  • Android Gradle - es el uso de divisiones sólo para la liberación posible?
  • Gradle no excluirá un módulo según lo solicitado
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.