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


170

Hay un problema con la biblioteca de Android appcompat v7 en dispositivos Samsung con Android 4.2. Sigo teniendo bloqueos con el siguiente seguimiento de pila en mi Consola de desarrollador:

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 es la línea 215 de CustomActivity.java:

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

Los bloqueos provienen de una variedad de dispositivos, pero siempre Samsung y siempre Android 4.2.

Una búsqueda rápida en la web me lleva a creer que muchas personas tienen el mismo problema, algunos de los pasos que he tratado de resolver son:

  • Verifique las propiedades del proyecto de Android, asegúrese de que la biblioteca appcompat se haya agregado correctamente.
  • Compruebe las propiedades del proyecto Java Build Path Order y Export, asegúrese de que las dependencias de Android y las bibliotecas privadas de Android estén marcadas.
  • Confirme que la clase está incluida en la biblioteca (android.support.v7.internal.view.menu.MenuBuilder).
  • Confirme que R.java se encuentra en el directorio gen para android.support.v7.appcompat.
  • Confirme que el tema AppCompat está incluido en la actividad Manifest.xml.
  • Proyecto de limpieza y reconstrucción.

A pesar de estos pasos, y a pesar de que funciona en todos los demás dispositivos y versiones de Android, los informes de fallas aún se reciben.


44
Nota: También he visto que esto ocurre en el QMobile X25, un teléfono de gama baja de Pakistán. Por lo tanto, parece que otros han tenido el mismo enfoque o la misma ROM que la ROM Samsung fallida.
William

Dado que Google y Samsung no son útiles para resolver este problema ENORME, ¿alguien puede pensar en una solución que no implique a Proguard (que plantea otros problemas)?
lista de verificación

Google no va a hacer nada al respecto, ya que es Samsung quien parece haber realizado modificaciones adicionales que causan una colisión de nombres entre las bibliotecas. Proguard evita la colisión. Tampoco he visto ninguna solución mejor en el foro Android Issue Tracker .
Matt K

También puedo agregar un QMobile A290, de Pakistán.
sstn

2
mismo problema [QMobile X30 - Android 4.4.2]
shanraisshan

Respuestas:


100

EDITAR:

La solución que funcionó para mí fue (Usando Proguard) para reemplazar esto:

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

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

con este:

# 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.** {*;}

El crédito va al grupo de google, # 138 .

Respuesta anterior (solución temporal): sucede en un proyecto en el que uso una ruleta en la barra de acciones. Mi solución fue verificar esas condiciones y cambiar el flujo de la aplicación:

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");
}

Luego, en el método onCreate de la actividad:

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

Como se señaló, esta no es una solución definitiva, es solo una forma de permitir a los usuarios tener acceso a una funcionalidad limitada mientras se encuentra una solución más permanente.


2
¿Alguien más puede verificar esta respuesta? No tengo acceso a un Samsung y la aplicación en la que estaba trabajando ya no está activa, por lo que no puedo probarla.
Matt K

3
@JaredBurrows No eliminas la biblioteca, solo le dices a proguard que la ignore de forma predeterminada, con la solución ignoras todo bajo android.support excepto android.support.v7.internal.view.menu
unifica el

2
He estado usando una solución de ese informe tema desde hace meses y de repente después de actualizar a las últimas bibliotecas de soporte y SDK 23 he empezado a conseguir este nuevo informe sobre crashlytics:java.lang.NoClassDefFoundError: android.support.v7.internal.view.menu.i
casolorz

3
El problema regresó en mi aplicación cuando me actualicé a AppCompat v23. Analicé el archivo jar AppCompat v.23.1.1, y vi que habían eliminado el directorio "interno" dentro de v7, por lo que parece que la línea de instrucciones de Proguard debería ser ahora: [-keep class! Android.support.v7.view. menu. **, android.support. ** {*;}] Todavía no tengo una confirmación de las pruebas en un dispositivo real donde ocurrió el problema. ¿Podría alguien con un dispositivo así probar esto? ¿O tal vez la eliminación del directorio 'interno' es en realidad la solución para el problema y ya no tenemos que meternos con el cambio de nombre de la clase Proguard?
gregko

77
Agregue esto a su configuración de protección, resolverá el problema: PARA APPCOMPAT 23.1.1: -keep class! Android.support.v7.view.menu. * MenuBuilder *, android.support.v7. ** { ; } interfaz -keep android.support.v7. * { ; } Para mayores APPCOMPAT VERSIÓN:!. -Keep clase android.support.v7.internal.view.menu * MenuBuilder ., Android.support.v7 ** { ; } interfaz -keep android.support.v7. * {*; }
Andrea Bellitto

26

Como dijo el # 150 de los grupos de google

Porque cuidado con -keep class! Android.support.v7.internal.view.menu. **. Hay una serie de clases allí a las que se hace referencia desde los recursos de appcompat.

La mejor solución es agregar las siguientes líneas en su lugar:

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

En mis pruebas, basadas en una revisión del archivo de mapeo de proguard generado, esta configuración de proguard sugerida no da como resultado la ofuscación del nombre de la clase MenuBuilder, aunque ofusca a SubMenuBuilder.
Andy Dennie

3
@William Alguien lo eliminó, no sé por qué. De todos modos, aquí está mi solución: -keep class !android.support.v7.internal.view.menu.* implements android.support.v4.internal.view.SupportMenu, android.support.v7.** {*;}
Andy Dennie

3
Esto funcionó para mí donde -keep class !android.support.v7.internal.view.menu.**,** {*;} ya no funcionaba con v23 de compatibilidad de aplicaciones .
Quentin Klein

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

2
en la biblioteca de soporte 23.1.1, se modificaron las rutas internas del paquete, por lo que ahora la configuración de protección correcta es: -keep class! android.support.v7.view.menu. * MenuBuilder *, android.support.v7. ** { ; } interfaz -keep android.support.v7. * {*; }
Andrea Bellitto

23

¿En qué dispositivo estás enfrentando este problema? (Samsung / HTC, etc.)

Si es Samsung,

Varios teléfonos Samsung incluyen versiones anteriores de la biblioteca de soporte de Android en el marco o classpath. Si usa la nueva biblioteca de soporte de materiales, verá este bloqueo en esos dispositivos Samsung:

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

Para solucionar esto, debe cambiar el nombre de esa clase. La forma más fácil de hacerlo es ejecutar Proguard. Si no desea ofuscar, aquí hay un 1 liner para renombrar solo las clases ofensivas:

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

Hay un problema para rastrear este problema, pero dado que es realmente un error de Samsung, nunca se solucionará por su parte. La única forma de solucionarlo en el lado de Google / AOSP es cambiar el nombre de estas clases internas.

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


¿Utiliza Proguard para soporte v4?
Jared Burrows

@JaredBurrows He intentado el soporte v7. Pero para v4 también funcionará.
Ganesh AB - Android

2
@ Android007: gracias por señalar esa solución que realmente funciona. Sin embargo, nadie parece poder explicar por qué las ROM defectuosas que incrustan la antigua Biblioteca de soporte de Android en su bootclasspath provocan esta excepción ya que la clase "android.support.v7.internal.view.menu.MenuBuilder" que falta está disponible en la. El código apk DEX de la aplicación que sufre este problema. ¿Tendrá algún puntero a mano que explique cómo el tiempo de ejecución de Android carga las clases tomadas de los archivos jar / dex bootclasspath y las aplicaciones, por favor? ¿O alguna explicación precisa, por favor?
Édouard Mercier

@ ÉdouardMercier Perdón por la respuesta tardía. Actualmente no tengo ninguna respuesta para su pregunta, pero me pondré en contacto con usted pronto. :)
Ganesh AB - Android

Gracias @ Android007, como cualquier programador, no me gusta mucho la brujería;) Una pista: ¿el bootclasspath incrustado contendría .jar / .dex "sellado", lo que explicaría el comportamiento?
Édouard Mercier

15

Este problema volvió AppCompat 23.1.1cuando el .internalpaquete se eliminó del archivo jar de la biblioteca.

Como se sugiere en los comentarios anteriores (créditos a las personas que lo sugirieron allí), ahora también la configuración de protección debe cambiar.

Para que la respuesta sugerida anteriormente vuelva a funcionar, intente agregar estas líneas a sus archivos de protección:

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

En lugar de la vieja solución:

#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.**es más seguro debido a otras clases como SubMenuBuilder
JaredBanyard

12

Según las últimas publicaciones del informe de errores, esto debería corregirse en la nueva versión de la biblioteca de soporte (24.0.0): https://code.google.com/p/android/issues/detail?id=78377 # c374

Alguien incluso afirmó que lo arregló.

Esta versión está disponible desde el mes pasado , por lo que debe actualizarla.


Nuestras pruebas confirman que 24.0.0 soluciona el problema. Actualizamos la biblioteca de soporte a 24.0.0 (no alfa), eliminamos la ofuscación que estábamos usando como solución alternativa y no vimos fallas en un dispositivo de prueba de Samsung donde previamente hemos visto el bloqueo.
Mark McClelland

4

Si. Samsung ya sabe sobre este problema. Puedo sugerirle que intente usar la misma implementación de Popup de GitHub . No es la mejor manera, pero serán obras.


1
Sí, lo vi en el foro de Samsung, pero no parece que estén interesados ​​ya que ninguno de sus representantes o soporte ha respondido.
Matt K

4

Estaba teniendo el mismo problema con esta clase de MenuBuilder que no se encuentra en el modo de depuración USB. He resuelto este problema, simplemente definiendo el minifyEnabled a cierto tanto en la liberación y depurar buildTypes bloque de build.gradle . Me gusta esto:

buildTypes {

    debug {

        minifyEnabled true
    }

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

Configuré minifyEnabled en verdadero en el tipo de depuración para evitar que la aplicación se bloquee a través de la depuración USB en un teléfono en vivo.


0

Habilité proguard con las propiedades de proguard predeterminadas proporcionadas con un proyecto de eclipse y el problema se solucionó para mí. Según algunos comentarios aquí https://code.google.com/p/android/issues/detail?id=78377 , algunas personas podrían tener que volver a empaquetarlas usando: -repackageclasses "android.support.v7"


Parece que eso no funciona para la mayoría de las personas en el foro. Parece que volver a appcompat-20 es una opción más confiable.
Matt K

Esto supuestamente se resolvió en el soporte v23.1.1
Tim Malseed

0

Recibí el mismo error al intentar ejecutar una aplicación 'Hello World' en mi tableta Samsung Galaxy Tab 3 a través de Android Studio. La aplicación parece iniciarse y luego se bloquea instantáneamente y ese error se muestra en la consola en Android Studio. Hice una actualización del sistema en la tableta y ahora puedo ejecutar la aplicación 'Hello World' y ya no recibo el error. Espero que esto ayude a alguien a resolver su problema.

Nota: La actualización del sistema que realicé en la tableta no actualizó la versión del sistema operativo Android, porque todavía dice que la versión es 4.2.2.


-4

Cambie la versión Compile Sdk de su proyecto a "API 18: (JellyBean)"

El valor predeterminado se establece en "Lollipop

PASOS

  1. Haga clic derecho en su proyecto y seleccione Abrir configuración del módulo (o presione F4)
  2. En la pestaña de propiedades Versión compilada de SDK
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.