[java] NoClassDefFoundError : android.support.v7.internal.view.menu.MenuBuilder

Android 4.2를 실행하는 Samsung 장치의 Android appcompat v7 라이브러리에 문제가 있습니다. 개발자 콘솔에서 다음 스택 추적으로 계속 충돌이 발생합니다.

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)

이것은 CustomActivity.java의 215 행입니다.

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

충돌은 일련의 장치에서 발생하지만 항상 Samsung이며 항상 Android 4.2입니다.

빠른 웹 검색을 통해 많은 사람들이 동일한 문제를 겪고 있다고 믿게되는데,이 문제를 해결하기 위해 시도한 단계 중 일부는 다음과 같습니다.

  • Android 프로젝트 특성을 확인하고 appcompat 라이브러리가 올바르게 추가되었는지 확인하십시오.
  • Java 빌드 경로 순서 및 내보내기 프로젝트 특성을 확인하고 Android 종속성 및 Android 개인 라이브러리가 선택되어 있는지 확인하십시오.
  • 클래스가 라이브러리에 포함되어 있는지 확인하십시오 (android.support.v7.internal.view.menu.MenuBuilder).
  • R.java가 android.support.v7.appcompat의 gen 디렉토리에 있는지 확인하십시오.
  • AppCompat 테마가 Manifest.xml 활동에 포함되어 있는지 확인하십시오.
  • 프로젝트를 정리하고 다시 빌드하십시오.

이러한 단계에도 불구하고 다른 모든 장치 및 Android 버전에서 작동하더라도 충돌 보고서는 계속 발생합니다.



답변

편집하다:

나를 위해 일한 해결책은 (Proguard 사용)이 이것을 대체하는 것입니다.

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

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

이것으로 :

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

크레딧은 Google 그룹 # 138으로 갑니다.

이전 답변 (임시 해결 방법) : ActionBar 에서 스피너를 사용하는 프로젝트에서 발생 합니다 . 내 솔루션은 이러한 조건을 확인하고 앱 흐름을 변경하는 것이 었습니다.

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

그런 다음 활동의 onCreate 메소드에서 :

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

이 솔루션은 결정적인 솔루션이 아니라보다 영구적 인 솔루션을 찾는 동안 사용자가 제한된 기능에 액세스 할 수 있도록하는 방법 일뿐입니다.


답변

마찬가지로 구글 홈페이지에서 # 150은 상기

-keep class! android.support.v7.internal.view.menu. **에주의하십시오. 거기에는 appcompat의 리소스에서 참조되는 많은 클래스가 있습니다.

더 나은 해결책은 대신 다음 줄을 추가하는 것입니다.

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


답변

어떤 장치에서이 문제가 발생합니까? (삼성 / HTC 등)

삼성이라면

다양한 삼성 전화는 프레임 워크 또는 클래스 경로에 이전 버전의 Android 지원 라이브러리가 포함되어 있습니다. 새로운 재료 지원 라이브러리를 사용하는 경우 해당 Samsung 장치에서이 충돌이 나타납니다.

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

이 문제를 해결하려면 해당 클래스의 이름을 바꿔야합니다. 가장 쉬운 방법은 proguard를 실행하는 것입니다. 난독 화하지 않으려는 경우 문제가되는 클래스의 이름을 바꾸는 1 개의 라이너가 있습니다.

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

이 문제를 추적하는 데 문제가 있지만 실제로는 삼성 버그이므로 절대로 해결되지 않습니다. Google / AOSP 측에서 수정하는 유일한 방법은 이러한 내부 클래스의 이름을 바꾸는 것입니다.

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


답변

이 문제 AppCompat 23.1.1.internal패키지가 라이브러리 jar에서 제거 된 곳에서 반환되었습니다 .

위의 의견에서 제안한 것처럼 (여기서 제안한 사람들에게 제공되는 신용) 이제 보호 구성도 변경되어야합니다.

위에서 다시 제안한 답변을 얻으려면 proguard 파일에 다음 줄을 추가하십시오.

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

이전 수정 대신 :

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


답변

버그 보고서의 마지막 게시물에 따르면, 이것은 새로운 버전의 지원 라이브러리 (24.0.0)에서 수정되어야합니다.
https://code.google.com/p/android/issues/detail?id=78377 # c374

누군가 그것을 고쳤다 고 주장했다 .

이 버전은 지난 달부터 사용할 수 있으므로 업데이트해야합니다.


답변

예. 삼성 전자는 이미 알고 문제. GitHub 에서 동일한 Popup 구현을 사용하도록 제안 할 수 있습니다 . 가장 좋은 방법은 아니지만 작품이 될 것입니다.


답변

USB 디버깅 모드 에서이 MenuBuilder 클래스와 동일한 문제가 발생했습니다. 나는 간단하게 설정하여이 문제를 해결 minifyEnabled을사실 모두 릴리스 및 디버그에 buildTypes 의 블록 build.gradle . 이처럼 :

buildTypes {

    debug {

        minifyEnabled true
    }

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

USB 디버깅을 통해 라이브 핸드셋으로 앱이 충돌하지 않도록 디버그 유형 에서 minifyEnabled 를 true로 설정했습니다 .