NoClassDefFoundError: android.support.v7.internal.view.menu.MenuBuilder


170

Há um problema com a biblioteca appcompat v7 do Android em dispositivos Samsung executando o Android 4.2. Continuo recebendo falhas com o seguinte rastreamento de pilha no meu console do desenvolvedor:

java.lang.NoClassDefFoundError: android.support.v7.internal.view.menu.MenuBuilder
    at android.support.v7.widget.PopupMenu.<init>(PopupMenu.java:66)
    at com.[my-package-name].CustomActivity$5.onClick(CustomActivity.java:215)
    at android.view.View.performClick(View.java:4222)
    at android.view.View$PerformClick.run(View.java:17620)
    at android.os.Handler.handleCallback(Handler.java:800)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:194)
    at android.app.ActivityThread.main(ActivityThread.java:5391)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:525)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
    at dalvik.system.NativeStart.main(Native Method)

Esta é a linha 215 de CustomActivity.java:

PopupMenu popup = new PopupMenu(CustomActivity.this, mImageViewMenu);

As falhas vêm de uma variedade de dispositivos, mas sempre Samsung e sempre Android 4.2.

Uma pesquisa rápida na web me leva a acreditar que muitas pessoas têm o mesmo problema. Algumas das etapas que tentei resolver são:

  • Verifique as propriedades do projeto Android, verifique se a biblioteca appcompat foi adicionada corretamente.
  • Verifique as propriedades do projeto Java Order Path Build e Export e verifique se as Dependências do Android e as Bibliotecas particulares do Android estão marcadas.
  • Confirme se a classe está incluída na biblioteca (android.support.v7.internal.view.menu.MenuBuilder).
  • Confirme R.java está localizado no diretório gen para android.support.v7.appcompat.
  • Confirme se o tema AppCompat está incluído na atividade Manifest.xml.
  • Limpe e reconstrua o projeto.

Apesar dessas etapas, e apesar de funcionar em todos os outros dispositivos e versões do Android, os relatórios de falhas ainda são apresentados.


4
Nota: Eu também vi isso acontecer no QMobile X25, que é um telefone de baixo custo do Paquistão. Portanto, parece que outros adotam a mesma abordagem ou a mesma ROM que a ROM ROM com falha.
William

Como o Google e a Samsung não são úteis para resolver esse enorme problema, alguém pode pensar em uma solução que não envolva o Proguard (o que levanta outros problemas)?
checklist

O Google não fará nada a respeito, já que é a Samsung que parece ter feito modificações adicionais, causando uma colisão de nomes entre as bibliotecas. Proguard evita a colisão. Também não encontrou soluções melhores no fórum Rastreador de problemas do Android .
Matt K

Também posso adicionar um QMobile A290, fora do Paquistão.
Sstn 17/05/19

2
mesmo problema [QMobile X30 - Android 4.4.2]
shanraisshan de 01/09/16

Respostas:


100

EDITAR:

A solução que funcionou para mim foi (Usando Proguard) para substituir isso:

-keep class android.support.v4.** { *; } 
-keep interface android.support.v4.** { *; }

-keep class android.support.v7.** { *; }
-keep interface android.support.v7.** { *; }

com isso:

# Allow obfuscation of android.support.v7.internal.view.menu.**
# to avoid problem on Samsung 4.2.2 devices with appcompat v21
# see https://code.google.com/p/android/issues/detail?id=78377
-keep class !android.support.v7.internal.view.menu.**,android.support.** {*;}

O crédito vai para o grupo do Google, nº 138 .

Resposta antiga (solução temporária): Isso acontece em um projeto em que uso um girador no ActionBar. Minha solução foi verificar essas condições e alterar o fluxo do aplicativo:

public static boolean isSamsung_4_2_2() {
    String deviceMan = Build.MANUFACTURER;
    String deviceRel = Build.VERSION.RELEASE;
    return "samsung".equalsIgnoreCase(deviceMan) && deviceRel.startsWith("4.2.2");
}

Em seguida, no método onCreate da atividade:

if (isSamsung_4_2_2()) {
    setContentView(R.layout.activity_main_no_toolbar);
} else {
    setContentView(R.layout.activity_main);
}

Como apontado, essa não é uma solução definitiva, é apenas uma maneira de permitir que os usuários tenham acesso a funcionalidades limitadas enquanto uma solução mais permanente é encontrada.


2
Alguém mais pode verificar esta resposta? Não tenho acesso a uma Samsung e o aplicativo em que estava trabalhando não está mais ativo, portanto não posso testá-lo.
Matt K

3
@JaredBurrows Você não remove a biblioteca, apenas pede ao proguard que a ignore por padrão, com a correção que você ignora tudo no android.support, exceto android.support.v7.internal.view.menu
unifique

2
Estou usando uma solução a partir desse relatório problema para meses agora e de repente após a atualização para as últimas bibliotecas de apoio e SDK 23 eu comecei a receber este novo relatório sobre crashlytics:java.lang.NoClassDefFoundError: android.support.v7.internal.view.menu.i
casolorz

3
O problema retornou no meu aplicativo quando eu atualizei para o AppCompat v23. Analisei o arquivo jar do AppCompat v.23.1.1 e verifiquei que eles removeram o diretório "interno" da v7; portanto, parece que a linha de instruções Proguard deve estar agora: [-keep class! Android.support.v7.view. menu. **, android.support. ** {*;}] Ainda não tenho confirmação de testes em um dispositivo real onde o problema ocorreu. Alguém com esse dispositivo poderia testar isso? Ou talvez a remoção do diretório 'interno' seja realmente a correção do problema e não precisamos mais mexer na renomeação da classe Proguard?
gregko

7
Adicione isso às suas configurações de programa, pois isso resolverá o problema: FOR APPCOMPAT 23.1.1: -seep class! Android.support.v7.view.menu. * MenuBuilder *, android.support.v7. ** { ; } - interface de manutenção android.support.v7. * { ; } PARA A VERSÃO APPCOMPAT MAIS ANTIGA: - mantenha a classe! Android.support.v7.internal.view.menu. * MenuBuilder , android.support.v7. ** { ; } - interface de manutenção android.support.v7. * {*; }
Andrea Bellitto 16/12

26

Como o número 150 dos grupos do Google disse

Cuidado com a classe -keep! Android.support.v7.internal.view.menu. **. Existem várias classes que são referenciadas nos recursos do appcompat.

A melhor solução é adicionar as seguintes linhas:

-keep class !android.support.v7.internal.view.menu.*MenuBuilder*, android.support.v7.** { *; }
-keep interface android.support.v7.** { *; }

Nos meus testes, com base em uma revisão do arquivo de mapeamento de progresso gerado, essa configuração sugerida de resultado não ofusca o nome da classe MenuBuilder, embora ofusque o SubMenuBuilder.
precisa

3
@ William Alguém excluiu, não sei por quê. Enfim, aqui está a minha solução: -keep class !android.support.v7.internal.view.menu.* implements android.support.v4.internal.view.SupportMenu, android.support.v7.** {*;}
Andy Dennie

3
Isso funcionou para mim onde -keep class !android.support.v7.internal.view.menu.**,** {*;} não estava mais funcionando com a v23 do aplicativo compat .
Quentin Klein

1
-keep class !android.support.v7.internal.view.menu.*MenuBuilder*, android.support.v7.** { *; } -keep interface android.support.v7.** { *; }como a resposta :)
Quentin Klein

2
na biblioteca de suporte 23.1.1, os caminhos internos do pacote foram modificados; agora, a configuração correta do programa é: -keep class! android.support.v7.view.menu. * MenuBuilder *, android.support.v7. ** { ; } - interface de manutenção android.support.v7. * {*; }
Andrea Bellitto 16/12

23

Em qual dispositivo você está enfrentando esse problema? (Samsung / HTC etc.)

Se é Samsung,

Vários telefones Samsung estão incluídos nas versões mais antigas da biblioteca de suporte do Android no framework ou no caminho da classe. Se você usar a nova biblioteca de suporte de material, verá esta falha nos dispositivos Samsung:

java.lang.NoClassDefFoundError: android.support.v7.internal.view.menu.MenuBuilder

Para corrigir isso, você deve renomear essa classe. A maneira mais fácil de fazer isso é executando o proguard. Se você não deseja ofuscar, aqui está um liner para renomear apenas as classes ofensivas:

-keep class !android.support.v7.internal.view.menu.**,** {*;}

Há um problema para rastrear esse problema, mas, como é realmente um bug da Samsung, nunca será corrigido. A única maneira de corrigi-lo no lado do Google / AOSP é renomear essas classes internas.

https://code.google.com/p/android/issues/detail?id=78377


Você usa proguard para suporte v4?
Jared Burrows

@JaredBurrows Eu tentei o suporte v7. Mas para a v4 também funcionará.
Ganesh AB - Android

2
@ Android007: obrigado por apontar a solução alternativa que realmente funciona. No entanto, ninguém parece capaz de explicar por que as ROMs defeituosas que incorporam a antiga Biblioteca de Suporte Android em seu caminho de inicialização causam essa exceção, uma vez que a classe "android.support.v7.internal.view.menu.MenuBuilder" está disponível na. Código DEX apk do aplicativo que sofre com esse problema. Você teria algum ponteiro em mãos que explique como o tempo de execução do Android carrega as classes extraídas dos arquivos jar / dex do bootclasspath e dos aplicativos, por favor? Ou alguma explicação precisa, por favor?
Édouard Mercier

@ ÉdouardMercier Desculpe pela resposta tardia. No momento, não tenho resposta para sua pergunta, mas em breve retornaremos a resposta. :)
Ganesh AB - Android

Obrigado @ Android007, como qualquer programador, não gosto muito de bruxaria;) Uma dica: o caminho de boot incorporado conteria .jar / .dex "selado", o que explicaria o comportamento?
Édouard Mercier

15

Esse problema retornou no AppCompat 23.1.1local em que o .internalpacote foi removido do jar da biblioteca.

Conforme sugerido nos comentários acima (créditos para as pessoas que o sugeriram lá), agora também a configuração do programa precisa mudar.

Para que a resposta sugerida acima funcione novamente, tente adicionar estas linhas aos seus arquivos de programa:

#FOR APPCOMPAT 23.1.1:
-keep class !android.support.v7.view.menu.*MenuBuilder*, android.support.v7.** { *; }
-keep interface android.support.v7.* { *; }

Em vez da correção antiga:

#FOR OLDER APPCOMPAT VERSION:
-keep class !android.support.v7.internal.view.menu.*MenuBuilder, android.support.v7.** { ; }
-keep interface android.support.v7.* { *; }

!android.support.v7.view.menu.**é mais seguro por causa de outras classes, como SubMenuBuilder
JaredBanyard 17/16

12

De acordo com as últimas postagens do relatório de erros, isso deve ser corrigido na nova versão da biblioteca de suporte (24.0.0): https://code.google.com/p/android/issues/detail?id=78377 # c374

Alguém até alegou que o consertou.

Esta versão está disponível desde o mês passado , portanto, você deve atualizá-la.


Nosso teste confirma que 24.0.0 corrige o problema. Atualizamos a biblioteca de suporte para 24.0.0 (não alfa), removemos a ofuscação que estávamos usando como solução alternativa e não vimos falhas em um dispositivo de teste da Samsung onde já vimos a falha anteriormente.
Mark McClelland

4

Sim. A Samsung já conhece esse problema. Posso sugerir que você tente usar a mesma implementação do Popup no GitHub . Não é o melhor caminho, mas serão obras.


1
Sim, vi isso no fórum da Samsung, mas não parece que eles estejam interessados, pois nenhum de seus representantes ou suporte respondeu.
Matt K

4

Eu estava tendo o mesmo problema dessa classe MenuBuilder não encontrada no modo de depuração USB. Resolvi esse problema simplesmente configurando o minifyEnabled como true no bloco buildTypes de lançamento e depuração do build.gradle . como isso:

buildTypes {

    debug {

        minifyEnabled true
    }

    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}

Defino o minifyEnabled como true no tipo de depuração para evitar que o aplicativo falhe via depuração USB em um telefone ativo .


0

Ativei o proguard com as propriedades padrão fornecidas com um projeto eclipse e o problema foi corrigido para mim. Com base em alguns comentários aqui https://code.google.com/p/android/issues/detail?id=78377 , algumas pessoas podem precisar reembalar usando: -repackageclasses "android.support.v7"


Parece que isso não está funcionando para a maioria das pessoas no fórum. Parece que voltar ao appcompat-20 é uma opção mais confiável.
Matt K

Isso supostamente foi resolvido no suporte v23.1.1
Tim Malseed

0

Recebi o mesmo erro ao tentar executar um aplicativo 'Hello World' no meu tablet Samsung Galaxy Tab 3 via Android Studio. O aplicativo parece iniciar e, em seguida, falha instantaneamente e esse erro aparece no console do Android Studio. Fiz uma atualização do sistema no tablet e agora consigo executar o aplicativo 'Hello World' e não estou mais recebendo o erro. Espero que isso ajude alguém a resolver seu problema.

Nota: A atualização do sistema que executei no tablet não atualizou a versão do sistema operacional Android, porque ainda diz que a versão é 4.2.2.


-4

Altere a versão compilar SDK do seu projeto para "API 18: (JellyBean)"

O padrão é definido como "Lollipop

PASSOS

  1. Clique com o botão direito do mouse no seu projeto e selecione Abrir Configurações do Módulo (ou pressione F4)
  2. Na guia Propriedades Versão Sdk compilada
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.