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


170

มีปัญหากับไลบรารี Android appcompat v7 บนอุปกรณ์ Samsung ที่ใช้ Android 4.2 ฉันได้รับความขัดข้องด้วยการติดตามสแต็กต่อไปนี้ในคอนโซลนักพัฒนาซอฟต์แวร์ของฉัน:

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)

นี่คือสาย 215 ของ CustomActivity.java:

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

การขัดข้องเกิดจากอุปกรณ์หลายอย่าง แต่เป็น Samsung และ Android 4.2 เสมอ

การค้นหาเว็บอย่างรวดเร็วทำให้ฉันเชื่อว่าหลายคนมีปัญหาเดียวกันขั้นตอนบางอย่างที่ฉันพยายามแก้ไขปัญหาคือ:

  • ตรวจสอบคุณสมบัติของโครงการ Android ตรวจสอบให้แน่ใจว่าเพิ่ม appcompat library อย่างถูกต้อง
  • ตรวจสอบคุณสมบัติของ Java Build Path Order และ Export project ตรวจสอบให้แน่ใจว่า Android Dependencies และ Android Private Libraries ได้รับการตรวจสอบแล้ว
  • ยืนยันคลาสที่รวมอยู่ในไลบรารี (android.support.v7.internal.view.menu.MenuBuilder)
  • ยืนยันว่า R.java อยู่ในไดเรกทอรี gen สำหรับ android.support.v7.appcompat
  • ยืนยันว่าธีม AppCompat รวมอยู่ในกิจกรรม Manifest.xml
  • ทำความสะอาดและสร้างโครงการใหม่

แม้จะมีขั้นตอนเหล่านี้และแม้ว่ามันจะทำงานบนอุปกรณ์อื่น ๆ และ Android ทุกรุ่นรายงานความผิดพลาดก็ยังคงเกิดขึ้น


4
หมายเหตุ: ฉันเคยเห็นสิ่งนี้เกิดขึ้นใน QMobile X25 ซึ่งเป็นโทรศัพท์ระดับต่ำสุดของปากีสถาน ดังนั้นดูเหมือนว่า oythers ใช้วิธีการเดียวกันหรือ ROM เดียวกันกับ Samsung ROM ที่ล้มเหลว
วิลเลียม

เนื่องจากทั้ง Google และ Samsung ไม่ได้มีประโยชน์ในการแก้ไขปัญหาขนาดใหญ่นี้ทุกคนสามารถคิดถึงวิธีแก้ปัญหาที่ไม่เกี่ยวข้องกับ Proguard (ซึ่งทำให้เกิดปัญหาอื่น)
รายการตรวจสอบ

Google จะไม่ทำอะไรเกี่ยวกับเรื่องนี้เนื่องจากเป็น Samsung ที่ดูเหมือนว่าได้ทำการแก้ไขเพิ่มเติมทำให้เกิดการชนกันของชื่อระหว่างไลบรารี Proguard หลีกเลี่ยงการชน ไม่เคยเห็นโซลูชันที่ดีขึ้นในฟอรัม Android Issue Trackerเช่นกัน
Matt K

ฉันสามารถเพิ่ม QMobile A290 จากปากีสถานได้เช่นกัน
sstn

2
ปัญหาเดียวกัน [QMobile X30 - Android 4.4.2]
shanraisshan

คำตอบ:


100

แก้ไข:

โซลูชันที่ใช้งานได้สำหรับฉันคือ (ใช้ 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, #

คำตอบเก่า (วิธีแก้ปัญหาชั่วคราว): มันเกิดขึ้นในโครงการที่ฉันใช้สปินเนอร์ใน 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);
}

ตามที่ระบุไว้นี่ไม่ใช่วิธีการแก้ปัญหาที่ชัดเจนมันเป็นเพียงวิธีการอนุญาตให้ผู้ใช้สามารถเข้าถึงฟังก์ชันการทำงานที่ จำกัด ในขณะที่พบวิธีแก้ไขปัญหาที่ถาวรมากขึ้น


2
ใครช่วยยืนยันคำตอบนี้ได้ไหม ฉันไม่สามารถเข้าถึง Samsung และแอพที่ฉันทำงานอยู่ไม่ทำงานอีกต่อไปดังนั้นฉันจึงไม่สามารถทดสอบได้
Matt K

3
@ JaredBurrows คุณไม่ได้ลบไลบรารีคุณเพียงแค่บอก proguard ให้เพิกเฉยโดยค่าเริ่มต้นพร้อมการแก้ไขที่คุณไม่สนใจทุกอย่างภายใต้ android.support ยกเว้น android.support.v7.internal.view.menu
รวม

2
ฉันใช้วิธีแก้ไขปัญหาจากรายงานปัญหานี้มาหลายเดือนแล้วและในทันทีหลังจากอัปเดตเป็นไลบรารีสนับสนุนล่าสุดและ sdk 23 ฉันเริ่มได้รับรายงานใหม่เรื่อง crashlytics:java.lang.NoClassDefFoundError: android.support.v7.internal.view.menu.i
casolorz

3
ปัญหาถูกส่งคืนในแอพของฉันเมื่ออัพเกรดเป็น AppCompat v23 ฉันวิเคราะห์ไฟล์ jar AppCompat v.23.1.1 และเห็นว่าพวกเขาได้ลบไดเรกทอรี "ภายใน" ภายใน v7 ดังนั้นดูเหมือนว่าบรรทัดคำสั่ง Proguard ควรเป็นตอนนี้: [-keep class! android.support.v7.view เมนู. **, android.support. ** {*;}] ฉันยังไม่มีคำยืนยันจากการทดสอบบนอุปกรณ์จริงที่เกิดปัญหาขึ้น ทุกคนที่มีอุปกรณ์เช่นนี้ทดสอบหรือไม่ หรือบางทีการลบ 'ภายใน' dir เป็นจริงการแก้ไขปัญหาและเราไม่จำเป็นต้องยุ่งกับการเปลี่ยนชื่อคลาส Proguard อีกต่อไป?
gregko

7
เพิ่มไปยังการตั้งค่า proguard ของคุณมันจะแก้ปัญหาได้: สำหรับ APPCOMPAT 23.1.1: -keep class! android.support.v7.view.menu. * MenuBuilder *, android.support.v7. ** { ; } -keep interface android.support.v7. * { ; } สำหรับรุ่น APPCOMPAT ที่เก่ากว่า: -keep class! android.support.v7.internal.view.menu * MenuBuilder , android.support.v7. ** { ; } -keep interface android.support.v7. * {*; }
Andrea Bellitto

26

ในฐานะที่เป็น# 150 จากกลุ่ม Googleกล่าวว่า

เพราะระวังด้วย -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.** { *; }

ในการทดสอบของฉันจากการตรวจสอบไฟล์การแม็พตัวสร้างที่สร้างขึ้นการกำหนดค่าตัวพรอพเพอร์ตี้ที่แนะนำนี้ไม่ได้ทำให้ชื่อคลาสของ MenuBuilder มีความสับสน
Andy Dennie

3
@William มีคนลบออกไปไม่รู้ว่าทำไม อย่างไรก็ตามนี่คือวิธีแก้ปัญหาของฉัน: -keep class !android.support.v7.internal.view.menu.* implements android.support.v4.internal.view.SupportMenu, android.support.v7.** {*;}
Andy Dennie

3
นี้ทำงานสำหรับฉันที่-keep class !android.support.v7.internal.view.menu.**,** {*;} ไม่ได้ทำงานอีกต่อไปกับV23ของcompat แอป
เควนตินไคลน์

1
-keep class !android.support.v7.internal.view.menu.*MenuBuilder*, android.support.v7.** { *; } -keep interface android.support.v7.** { *; }เป็นคำตอบ :)
เควนตินไคลน์

2
บนไลบรารีการสนับสนุน 23.1.1 พา ธ แพ็กเกจภายในถูกแก้ไขดังนั้นตอนนี้การตั้งค่า proguard ที่ถูกต้องคือ: -keep class! android.support.v7.view.menu. * MenuBuilder *, android.support.v7. ** { ; } -keep interface android.support.v7. * {*; }
Andrea Bellitto

23

คุณประสบปัญหานี้กับอุปกรณ์ใด (Samsung / HTC ฯลฯ )

ถ้าเป็น Samsung

โทรศัพท์ซัมซุงหลากหลายรุ่นนั้นรวมถึงห้องสมุดสนับสนุน Android รุ่นเก่าในกรอบหรือคลาสพา ธ หากคุณใช้ไลบรารีการสนับสนุนวัสดุใหม่คุณจะเห็นความผิดพลาดนี้ในอุปกรณ์ Samsung เหล่านั้น:

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

ในการแก้ไขปัญหานี้คุณต้องเปลี่ยนชื่อชั้นเรียนนั้น วิธีที่ง่ายที่สุดในการทำเช่นนั้นก็คือการเรียกใช้ proguard หากคุณไม่ต้องการทำให้งงงวยต่อไปนี้เป็น 1 ไลเนอร์สำหรับเปลี่ยนชื่อคลาสที่ละเมิด:

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

มีปัญหาในการติดตามปัญหานี้ แต่เนื่องจากเป็นข้อบกพร่องจริง ๆ ของ Samsung จึงไม่มีทางแก้ไขได้ในตอนท้าย วิธีเดียวที่จะแก้ไขด้าน Google / AOSP คือเปลี่ยนชื่อคลาสภายในเหล่านี้

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


คุณใช้ proguard สำหรับการสนับสนุน v4 หรือไม่
Jared Burrows

@ JaredBurrows ฉันพยายามสนับสนุน v7 แล้ว แต่สำหรับ v4 มันจะทำงานด้วยเช่นกัน
Ganesh AB - Android

2
@ Android007: ขอบคุณสำหรับการชี้ให้เห็นว่าการแก้ไขที่ใช้งานได้จริง อย่างไรก็ตามดูเหมือนว่าไม่มีใครสามารถอธิบายได้ว่าทำไม ROM ผิดพลาดที่ฝังไลบรารีการสนับสนุน Android เก่าใน bootclasspath ทำให้เกิดข้อยกเว้นนี้เนื่องจากคลาส "android.support.v7.internal.view.menu.MenuBuilder" หายไปนั้นมีอยู่ในคลาส apk DEX code ของแอปพลิเคชั่นที่ได้รับผลกระทบจากปัญหานี้ คุณจะมีตัวชี้ใด ๆ ที่อธิบายว่า Android รันไทม์โหลดคลาสที่นำมาจากไฟล์ bootclasspath jar / dex และแอปพลิเคชันได้ไหม หรือคำอธิบายที่แม่นยำโปรด
Édouard Mercier

@ ÉdouardMercierขออภัยที่ตอบช้า ขณะนี้ฉันไม่มีคำตอบสำหรับคำถามของคุณ แต่ฉันจะติดต่อกลับในไม่ช้า :)
Ganesh AB - Android

ขอบคุณ @ Android007 ในฐานะโปรแกรมเมอร์ใด ๆ ฉันไม่ชอบคาถามาก;) คำแนะนำอย่างเดียว: bootclasspath แบบฝังจะมี "ซีล" .jar / .dex ซึ่งจะอธิบายพฤติกรรมนี้หรือไม่
Édouard Mercier

15

ปัญหานี้ส่งคืนใน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.* { *; }

!android.support.v7.view.menu.**ปลอดภัยกว่าเพราะคลาสอื่น ๆ เช่น SubMenuBuilder
JaredBanyard

12

ตามการโพสต์ล่าสุดของรายงานข้อผิดพลาดสิ่งนี้ควรได้รับการแก้ไขในเวอร์ชันใหม่ของไลบรารีการสนับสนุน (24.0.0): https://code.google.com/p/android/issues/detail?id=78377 # c374

บางคนถึงกับอ้างว่าได้แก้ไขมันแล้ว

รุ่นนี้มีให้บริการตั้งแต่เดือนที่แล้วดังนั้นคุณควรอัพเดท


การทดสอบของเรายืนยันว่า 24.0.0 แก้ไขปัญหาได้ เราอัปเกรดไลบรารีการสนับสนุนเป็น 24.0.0 (ไม่ใช่อัลฟ่า) ลบการทำให้งงที่เราใช้เป็นวิธีแก้ปัญหาและไม่พบข้อขัดข้องในอุปกรณ์ทดสอบของ Samsung ที่เราเคยเห็นความผิดพลาดมาก่อน
Mark McClelland

4

ใช่. ซัมซุงแล้วรู้เกี่ยวกับเรื่องนี้ปัญหา ฉันจะแนะนำให้คุณพยายามที่จะใช้การดำเนินงานเดียวกันของป๊อปอัพจากGitHub มันไม่ใช่วิธีที่ดีที่สุด แต่จะได้ผล


1
ใช่ฉันเห็นว่าในฟอรัม Samsung แต่ดูเหมือนว่าพวกเขาจะไม่สนใจเพราะไม่มีตัวแทนหรือฝ่ายสนับสนุนของพวกเขาตอบ
Matt K

4

ฉันมีปัญหาเดียวกันของคลาส MenuBuilder นี้ไม่พบในโหมดการแก้ไขข้อบกพร่อง USB ฉันจะแก้ไขปัญหานี้โดยเพียงแค่การตั้งค่าminifyEnabledไปจริงทั้งในการเปิดตัวและการแก้ปัญหาbuildTypesป้องกันของbuild.gradle แบบนี้:

buildTypes {

    debug {

        minifyEnabled true
    }

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

ฉันตั้งค่าminifyEnabledเป็น True ในประเภทการดีบักเพื่อป้องกันไม่ให้แอพหยุดทำงานผ่านการดีบัก USB กับโทรศัพท์มือถือ


0

ฉันเปิดใช้งาน proguard พร้อมด้วยคุณสมบัติ proguard เริ่มต้นที่มาพร้อมกับโครงการ eclipse และปัญหาได้รับการแก้ไขแล้วสำหรับฉัน ตามความคิดเห็นที่นี่https://code.google.com/p/android/issues/detail?id=78377บางคนอาจต้องทำการบรรจุใหม่โดยใช้: -repackageclasses "android.support.v7"


ดูเหมือนว่าจะไม่ได้ผลสำหรับคนส่วนใหญ่ในฟอรัม ดูเหมือนว่าจะกลับไปที่ appcompat-20 เป็นตัวเลือกที่น่าเชื่อถือมากกว่า
Matt K

ปัญหานี้ได้รับการแก้ไขแล้วในการสนับสนุน v23.1.1
Tim Malseed

0

ฉันพบข้อผิดพลาดเดียวกันเมื่อพยายามเรียกใช้แอพ 'Hello World' บนแท็บเล็ต Samsung Galaxy Tab 3 ของฉันผ่าน Android Studio แอปจะปรากฏขึ้นเพื่อเปิดใช้งานและจากนั้นจะเกิดข้อผิดพลาดทันทีและข้อผิดพลาดนั้นจะปรากฏในคอนโซลใน Android Studio ฉันทำการอัปเดตระบบบนแท็บเล็ตและตอนนี้ฉันสามารถเรียกใช้แอพ 'Hello World' และฉันไม่ได้รับข้อผิดพลาดอีกต่อไป ฉันหวังว่านี่จะช่วยให้ใครบางคนแก้ไขปัญหาของพวกเขาได้

หมายเหตุ: การอัปเดตระบบที่ฉันดำเนินการบนแท็บเล็ตไม่ได้อัปเดตเวอร์ชัน Android OS เพราะยังคงบอกว่าเป็นรุ่น 4.2.2


-4

เปลี่ยนเวอร์ชั่นคอมไพล์ Sdk ของโครงการเป็น"API 18: (JellyBean)"

ค่าเริ่มต้นถูกตั้งค่าเป็น "Lollipop

ขั้นตอน

  1. คลิกขวาที่โครงการของคุณและเลือกเปิดการตั้งค่าโมดูล (หรือกด F4)
  2. ในแท็บคุณสมบัติCompiled Sdk Version
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.