Não foi possível executar dex: ID do método que não está em [0, 0xffff]: 65536

344

Eu já vi várias versões dos dex erros antes, mas esta é nova. limpar / reiniciar etc não vai ajudar. Os projetos da biblioteca parecem intactos e a dependência parece estar vinculada corretamente.

Unable to execute dex: method ID not in [0, 0xffff]: 65536
Conversion to Dalvik format failed: Unable to execute dex: method ID not in [0, 0xffff]: 65536

ou

Cannot merge new index 65950 into a non-jumbo instruction

ou

java.util.concurrent.ExecutionException: com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536

tl; dr : A solução oficial do Google finalmente chegou!

http://developer.android.com/tools/building/multidex.html

Apenas uma pequena dica, você provavelmente precisará fazer isso para evitar falta de memória ao fazer dex-ing.

dexOptions {
        javaMaxHeapSize "4g"
}

Há também um modo jumbo que pode corrigir isso de uma maneira menos confiável:

dexOptions {
        jumboMode true
}

Atualização: se seu aplicativo é gordo e você tem muitos métodos dentro do aplicativo principal, pode ser necessário reorganizá-lo conforme

http://blog.osom.info/2014/12/too-many-methods-in-main-dex.html

Edison
fonte
11
Você usa API que não está disponível no seu dispositivo?
Rekire
Está lá, porque outro projeto é compilado visando a mesma versão da API.
Edison
Então você usa em algum momento a API que não está disponível? Você verifica com uma linha como if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)essa que não chama esta função se ela não está disponível?
Rekire
Sim eu faço. O projeto foi desenvolvido antes. Além disso, isso deve ser um erro de tempo de execução, mesmo que eu tenha perdido a linha.
Edison
Provavelmente, uma das dependências está bagunçada. (fazendo uma mistura de maven lib + projeto agora)
Edison

Respostas:

379

Atualização 3 (03/11/2014) O
Google finalmente divulgou a descrição oficial .


A atualização 2 (31/10/2014)
Gradle plugin v0.14.0 para Android adiciona suporte para multi-dex. Para habilitar, basta declará-lo em build.gradle :

android {
   defaultConfig {
      ...
      multiDexEnabled  true
   }
}

Se seu aplicativo oferecer suporte ao Android anterior à versão 5.0 (ou seja, se você minSdkVersiontiver 20 anos ou menos), também será necessário aplicar um patch dinâmico ao ClassLoader do aplicativo , para que ele possa carregar classes de dexes secundários. Felizmente, há uma biblioteca que faz isso por você. Adicione-o às dependências do seu aplicativo:

dependencies {
  ...
  compile 'com.android.support:multidex:1.0.0'
} 

Você precisa chamar o código de patch do ClassLoader o mais rápido possível. MultiDexApplicationA documentação da turma sugere três maneiras de fazer isso (escolha uma delas , a mais conveniente para você):

1 - Declare a MultiDexApplicationclasse como o aplicativo no seu AndroidManifest.xml :

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.multidex.myapplication">
    <application
        ...
        android:name="android.support.multidex.MultiDexApplication">
        ...
    </application>
</manifest>

2 - Faça sua Applicationclasse estender a classe MultiDexApplication :

public class MyApplication extends MultiDexApplication { .. }

3 - Ligue MultiDex#installdo seu Application#attachBaseContextmétodo:

public class MyApplication {
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
        ....
    }
    ....
}

Atualização 1 (17/10/2014):
Conforme previsto, o suporte multidex é enviado na revisão 21 da Biblioteca de suporte do Android. Você pode encontrar o android-support-multidex.jar na pasta / sdk / extras / android / support / multidex / library / libs.


O suporte multi-dex resolve esse problema. O dx 1.8 já permite gerar vários arquivos dex.
O Android L oferecerá suporte a vários dex nativamente, e a próxima revisão da biblioteca de suporte cobrirá versões mais antigas da API 4.

Foi declarado neste episódio de podcast do Android Developers Backstage por Anwar Ghuloum. Eu já postou uma transcrição (e explicação geral multi-dex) da parte relevante.

Alex Lipov
fonte
2
postagem no blog é uma poupança! : D
nadavfima
39
Alguma coisa para usuários do eclipse?
Muhammad Babar 23/02
52
@MuhammadBabar Existe um estúdio Android para usuários do Eclipse.
VipulKumar
2
@MohammedAli Claro, evite usá-lo se puder. Mas o que você deve fazer se realmente tiver muitos métodos em seu aplicativo e já tiver experimentado todos os truques como o mencionado? Em relação ao tempo de compilação - não há solução para isso, pelo menos para o desenvolvimento constrói - veja minha resposta aqui: stackoverflow.com/a/30799491/1233652
Alex Lipov
2
No Qt for Android, eu estava tendo problemas em tempo de execução para o meu aplicativo ao integrar os SDKs do Facebook + do Twitter, mesmo depois de ativar o suporte multidex (esse erro em particular me deu pesadelos:) java.lang.ClassNotFoundException: Didn't find class "org.qtproject.qt5.android.QtActivityDelegate" on path: DexPathList[[],nativeLibraryDirectories=[/vendor/lib, /system/lib]]. Meu erro foi que eu não estava aplicando as etapas adicionais para o suporte ao Android antes da versão 5.0. Com isso dito, a opção 3 resolveu e não tive mais ClassNotFoundExceptionproblemas. Obrigado, @Alex Lipov!
rob
78

Como já foi dito, você tem muitos métodos (mais de 65k) em seu projeto e bibliotecas.

Evite o problema: reduza o número de métodos com o Play Services 6.5+ e support-v4 24.2+

Como muitas vezes os serviços do Google Play são um dos principais suspeitos de "desperdiçar" métodos com seus métodos de mais de 20k . Serviços do Google Play versão 6.5 ou posterior, é possível incluir os serviços do Google Play no seu aplicativo usando várias bibliotecas de clientes menores. Por exemplo, se você precisar apenas de GCM e mapas, poderá optar por usar apenas essas dependências:

dependencies {
    compile 'com.google.android.gms:play-services-base:6.5.+'
    compile 'com.google.android.gms:play-services-maps:6.5.+'
}

A lista completa de sub-bibliotecas e suas responsabilidades pode ser encontrada no documento oficial do google .

Atualização : Desde a Biblioteca de suporte v4 v24.2.0, ela foi dividida nos seguintes módulos:

support-compat, support-core-utils, support-core-ui, support-media-compatEsupport-fragment

dependencies {
    compile 'com.android.support:support-fragment:24.2.+'
}

Observe, no entanto, se você usar support-fragment, ele terá dependências para todos os outros módulos (ou seja, se você usar, android.support.v4.app.Fragmentnão há benefício)

Veja aqui as notas de versão oficiais do support-v4 lib


Ativar MultiDexing

Desde o Lollipop (aka build tools 21+), é muito fácil de manusear. A abordagem é solucionar o problema de 65 mil métodos por arquivo dex para criar vários arquivos dex para o seu aplicativo. Adicione o seguinte ao seu arquivo de compilação gradle ( isso é obtido no google doc oficial em aplicativos com mais de 65 mil métodos ):

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.0"

    defaultConfig {
        ...
        // Enabling multidex support.
        multiDexEnabled true
    }
    ...
}

dependencies {
  compile 'com.android.support:multidex:1.0.1'
}

A segunda etapa é preparar a classe Application ou, se você não estender o Application, use o MultiDexApplicationno manifesto do Android:

Adicione isso ao seu Application.java

@Override
  protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    MultiDex.install(this);
  }

ou use o aplicativo fornecido na biblioteca mutlidex

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.myapplication">
    <application
        ...
        android:name="android.support.multidex.MultiDexApplication">
        ...
    </application>
</manifest>

Impedir OutOfMemory com MultiDex

Como dica adicional, se você encontrar OutOfMemoryexceções durante a fase de construção, poderá aumentar o heap com

android {
    ...
    dexOptions {
        javaMaxHeapSize "4g"
    }
}

o que definiria o heap para 4 gigabytes.

Consulte esta pergunta para obter mais detalhes sobre o problema de memória heap dex.


Analise a fonte do problema

Para analisar a fonte dos métodos, o plug-in gradle https://github.com/KeepSafe/dexcount-gradle-plugin pode ajudar em combinação com a árvore de dependência fornecida por gradle com, por exemplo,

.\gradlew app:dependencies

Veja esta resposta e pergunta para obter mais informações sobre a contagem de métodos no android

Patrick Favre
fonte
Usei a solução Play Services 6.5+ e funcionou perfeitamente. Dica útil incrível. Muito obrigado!
Hoang Nguyen Huu
Eu recomendaria mais se pudesse - cortando todas as outras coisas do Play Services que não estávamos usando, corrigimos esse problema, sem ter que recorrer ao multi-dex, que tem implicações negativas de desempenho na criação.
Sean Barbeau
11
Do que você com lágrimas nos meus olhos. Você me salvou
insomniac
Eu usei a biblioteca cliente para o GCM, porque estou usando apenas o serviço gcm do serviço play, agora ele corrigiu meu problema com isso. Obrigado! para economizar meu tempo.
Ankit
57

Seu projeto é muito grande. Você tem muitos métodos. Só pode haver 65536 métodos por aplicativo. veja aqui https://code.google.com/p/android/issues/detail?id=7147#c6

blobbie
fonte
Eu vejo. Eu tenho muitas dependências para este projeto. Ele cria muito bem antes de eu passar a usar o maven, talvez o maven tenha adicionado dependências desnecessárias. Irá verificar novamente.
Edison
5
Para ser mais específico, só pode haver 65.536 métodos por arquivo executável Dalvik (dex). E um aplicativo (APK) pode ter mais de um arquivo dex com itens como carregamento personalizado.
Dennis Sheil
7
É um bug realmente embaraçoso para o Android! De qualquer forma, Em mim caso eu removido Jar que estava nas libs e não estava em uso, e o aplicativo compilado
David
Hora de limpar meu projeto: /
Decoy
11
Uma solução rápida seria usar Proguard também com a compilações de depuração
aleb
12

O código abaixo ajuda, se você usa Gradle. Permite remover facilmente os serviços desnecessários do Google (presumindo que você os esteja usando) para voltar abaixo do limite de 65 mil. Todo o crédito para este post: https://gist.github.com/dmarcato/d7c91b94214acd936e42

Edit 22/10/2014 : Houve muitas discussões interessantes sobre a essência mencionada acima. TLDR? veja este: https://gist.github.com/Takhion/10a37046b9e6d259bb31

Cole esse código na parte inferior do arquivo build.gradle e ajuste a lista de serviços do Google que você não precisa:

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"))) {
                    exclude "com/google/ads/**"
                    exclude "com/google/android/gms/analytics/**"
                    exclude "com/google/android/gms/games/**"
                    exclude "com/google/android/gms/plus/**"
                    exclude "com/google/android/gms/drive/**"
                    exclude "com/google/android/gms/ads/**"
                }
            }.execute()
            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
    }
}
mcm
fonte
Adoro! def necessário, pois empresas como o Google continuam inflando os pacotes.
Edison
11
Nice - isso fez o trabalho no local. Sem problemas e sem preocupações!
slott
Nota: este serviço excluído do Google Play é jarro no SDK do Android no Android Studio! Uma péssima idéia, pois não é fácil voltar aos frascos originais. O autor deve modificar o script para alterar os jars no diretório de compilação.
inder
@inder: Eu não tive esse problema. No entanto, eu precisava fazer cleancada vez que usava as exclusões (usamos análises).
JohnnyLambada
como excluir isso das compilações de versão?
precisa saber é o seguinte
6

Compartilhei um projeto de amostra que resolve esse problema usando o script de construção custom_rules.xml e algumas linhas de código.

Usei-o no meu próprio projeto e é executado sem falhas em dispositivos com mais de 1 milhão (do android-8 ao android-19 mais recente). Espero que ajude.

https://github.com/mmin18/Dex65536

min
fonte
11
Obrigado pelos scripts. você deve prestar atenção à arte. O dispositivo pode converter apenas o dex padrão e não os secundários. As soluções Proguard devem ser preferidas.
Edison
2
Quando eu importo os projetos no Eclipse e o executo, ocorre um erro. "Não foi possível executar dex: ID do método que não está em [0, 0xffff]: 65536". Você pode explaing o uso do projeto
Karacago
6

Enfrentou o mesmo problema e resolveu-o editando meu arquivo build.gradle na seção dependências, removendo:

compile 'com.google.android.gms:play-services:7.8.0'

E substituindo-o por:

compile 'com.google.android.gms:play-services-location:7.8.0'
compile 'com.google.android.gms:play-services-analytics:7.8.0' 
Luis Miguel Ballestas
fonte
Perfeito! Eu apenas uso a API do Google Drive e isso funciona.
vedavis
5

Tente adicionar o código abaixo no build.gradle, funcionou para mim -

compileSdkVersion 23
buildToolsVersion '23.0.1'
defaultConfig {
    multiDexEnabled true
}
Sunita
fonte
2

A solução perfeita para isso seria trabalhar com Proguard. como mencionado no comentário. Diminuirá o tamanho do arquivo dex pela metade.

shimi_tap
fonte
11
Concordou, com um cada vez maior jar serviços Google Play especialmente * (18k métodos por si só)
Edison
2

Você pode analisar o problema (referências de arquivo dex) usando o Android Studio:

Construir -> Analisar APK ..

No painel de resultados, clique no arquivo classes.dex

E você verá:

insira a descrição da imagem aqui

alexshr
fonte
0

solução gradle + proguard:

afterEvaluate {
  tasks.each {
    if (it.name.startsWith('proguard')) {
        it.getInJarFilters().each { filter ->
            if (filter && filter['filter']) {
                filter['filter'] = filter['filter'] +
                        ',!.readme' +
                        ',!META-INF/LICENSE' +
                        ',!META-INF/LICENSE.txt' +
                        ',!META-INF/NOTICE' +
                        ',!META-INF/NOTICE.txt' +
                        ',!com/google/android/gms/ads/**' +
                        ',!com/google/android/gms/cast/**' +
                        ',!com/google/android/gms/games/**' +
                        ',!com/google/android/gms/drive/**' +
                        ',!com/google/android/gms/wallet/**' +
                        ',!com/google/android/gms/wearable/**' +
                        ',!com/google/android/gms/plus/**' +
                        ',!com/google/android/gms/topmanager/**'
            }
        }
    }
  }
}
Oleg Khalidov
fonte
0

Remova algum arquivo jar da pasta Libs e copie para outra pasta. Vá para _Project Properties> Select Java Build Path, selecione Libraries, selecione Add Jar externo, selecione o jar Removido ao seu projeto, clique em Save e será adicionado em Referenced Biblioteca em vez da pasta Libs. Agora limpe e execute seu projeto. Você não precisa adicionar nenhum código para o MultDex. Simplesmente funcionou para mim.

Lakshmanan
fonte
0

Eu estava enfrentando o mesmo problema hoje, o que funcionou é abaixo para baixo

Para ANDROID STUDIO ... Ativar execução instantânea

Em Arquivo-> Preferências-> Compilar, Execução, Implantação-> Execução Instantânea-> Marque Ativar Execução Instantânea para troca a quente ...

Espero que ajude

Abdul Waheed
fonte
11
Isso funcionou para mim - simplesmente desabilitei a opção Ativar execução, cliquei em Aplicar, a reativei e funcionou novamente.
precisa saber é o seguinte