android.view.WindowManager$BadTokenException: ไม่สามารถเพิ่มหน้าต่าง android.view.ViewRootImpl$W@c745883 - การอนุญาตถูกปฏิเสธ

นี่คือการติดตามสแต็กของฉัน:

01-30 15:11:41.037 13010-13010/project.app E/AndroidRuntime: FATAL EXCEPTION: main
 Process: project.app, PID: 13010
 android.view.WindowManager$BadTokenException:
   Unable to add window android.view.ViewRootImpl$W@c745883 -- permission denied for window type 2003
   at android.view.ViewRootImpl.setView(ViewRootImpl.java:789)
   at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:356)
   at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
   at android.app.Dialog.show(Dialog.java:330)
   at com.facebook.react.devsupport.DevSupportManagerImpl$4.run(DevSupportManagerImpl.java:344)
   at android.os.Handler.handleCallback(Handler.java:790)
   at android.os.Handler.dispatchMessage(Handler.java:99)
   at android.os.Looper.loop(Looper.java:164)
   at android.app.ActivityThread.main(ActivityThread.java:6494)
   at java.lang.reflect.Method.invoke(Native Method)
   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

ฉันพบคำตอบเกี่ยวกับ TYPE_SYSTEM_ERROR ที่เลิกใช้แล้วใน Android Oreo (8) ดังนั้นฉันจึงใช้วิธีต่อไปนี้ที่ฉันพบด้วย:

public void fixAndroid() {
    WindowManager.LayoutParams params;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
      params = new WindowManager.LayoutParams(
              WindowManager.LayoutParams.MATCH_PARENT,
              WindowManager.LayoutParams.MATCH_PARENT,
              WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
              WindowManager.LayoutParams.FLAG_FULLSCREEN,
              PixelFormat.TRANSLUCENT);
    } else {
      params = new WindowManager.LayoutParams(
              WindowManager.LayoutParams.MATCH_PARENT,
              WindowManager.LayoutParams.MATCH_PARENT,
              WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
              WindowManager.LayoutParams.FLAG_FULLSCREEN,
              PixelFormat.TRANSLUCENT);
    }
  }

ภายในวิธีการ onCreate() ของฉันฉันมี:

  @Override
  public void onCreate (Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Checking permissions on init
    fixAndroid();
  }

ฉันยังคงได้รับข้อผิดพลาด

ฉันใช้ Expo SDK 21, React Native 0.48 แอปพลิเคชันถูกแยกออกจาก ExpoKit แล้ว

หลังจากการเปลี่ยนแปลงแต่ละครั้ง ฉันจะล้างโปรเจ็กต์ของฉันแล้วรันบน Emulator ผ่าน Android Studio

แก้ไข: ฉันกำลังใช้งานสิ่งนี้บนเครื่องจำลอง Nexus 5X ซึ่งทำงานบน API 27


comment
ฉันคิดว่ามันเกี่ยวข้องกับWindowManager.LayoutParams น่าสนใจที่จะเห็นว่าเกิดอะไรขึ้นกับ: WindowManager.LayoutParams.TYPE_TOAST หรือ WindowManager.LayoutParams.TYPE_APPLICATION_PANEL และ WindowManager.LayoutParams.TYPE_SYSTEM_ALERT ด้วย: <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> ในรายการ   -  person Jon Goodwin    schedule 02.02.2018
comment
เฮ้ จอน มีการอนุญาตอยู่ใน AndroidManifest.xml ฉันจะลองทำตามคำแนะนำของคุณ ขอบคุณ   -  person Dan    schedule 02.02.2018
comment
สวัสดี Dan ฉันอยากให้คุณช่วย ฉันก็เลยพยายาม หงุดหงิด แต้มเพิ่มเติมจาก การดีบัก WebView ในแอป React Native อาจคุ้มค่าที่จะดูเพื่อวัตถุประสงค์ในการดีบัก หรือคุณสามารถรับข้อเสนอ 500 คะแนนให้ฉันได้!   -  person Jon Goodwin    schedule 03.02.2018
comment
ฉันคิดว่าคุณสามารถใช้กล่องโต้ตอบการแทนที่กิจกรรม Ttranslucent สำหรับโทรศัพท์ Android จำนวนมากปฏิเสธการอนุญาตเกี่ยวกับ TYPE_SYSTEM_ALERT   -  person Cyrus    schedule 09.02.2018


คำตอบ (3)


ฉันเห็นข้อผิดพลาดนี้เมื่อไม่นานมานี้ เมื่อฉันอัปเดตแอปเนทิฟ&รีแอคเป็น SDK 26 ปัญหาคือฟังก์ชันรีแอคเนทีฟที่สร้างกล่องโต้ตอบสีแดงสำหรับการพัฒนา ฟังก์ชันนั้นใช้ TYPE_SYSTEM_ALERT เป็นประเภท ดังนั้นคุณจึงไม่สามารถใช้ระดับ SDK ที่ใหญ่กว่า 25 ในแอปไฮบริดของคุณด้วยเวอร์ชัน React-Native เวอร์ชันนั้นได้ เว้นแต่คุณจะแพตช์ฟังก์ชันนั้นเพื่อไม่ให้ใช้ TYPE_SYSTEM_ALERT อีกต่อไป

นี่คือโค้ด react-native ใน 0.48:

private void showNewError(
      final String message,
      final StackFrame[] stack,
      final int errorCookie,
      final ErrorType errorType) {
    UiThreadUtil.runOnUiThread(
        new Runnable() {
          @Override
          public void run() {
            if (mRedBoxDialog == null) {
              mRedBoxDialog = new RedBoxDialog(mApplicationContext, DevSupportManagerImpl.this, mRedBoxHandler);
              mRedBoxDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
            }
            if (mRedBoxDialog.isShowing()) {
              // Sometimes errors cause multiple errors to be thrown in JS in quick succession. Only
              // show the first and most actionable one.
              return;
            }
            mRedBoxDialog.setExceptionDetails(message, stack);
            updateLastErrorInfo(message, stack, errorCookie, errorType);
            // Only report native errors here. JS errors are reported
            // inside {@link #updateJSError} after source mapping.
            if (mRedBoxHandler != null && errorType == ErrorType.NATIVE) {
              mRedBoxHandler.handleRedbox(message, stack, RedBoxHandler.ErrorType.NATIVE);
              mRedBoxDialog.resetReporting(true);
            } else {
              mRedBoxDialog.resetReporting(false);
            }
            mRedBoxDialog.show();
          }
        });
  } 

คุณจะต้องเปลี่ยนการเรียก mRedBoxDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); เป็นประเภทอื่น แต่นี่ไม่ได้ให้การรับประกันใด ๆ แก่คุณว่าคุณจะสามารถเรียกใช้แอปของคุณด้วย SDK 26 ได้ เมื่อฉันพยายามคอมไพล์การโต้ตอบด้วย SDK 26 ส่วนอื่น ๆ ของโครงการ "โต้ตอบ" จะระเบิด ดังนั้นจึงไม่น่าจะทำงานได้ในระยะสั้น (คุณอาจต้องเริ่มแก้ไขปัญหาอื่นๆ) ดังนั้นทางเลือกของคุณคือ:

- ดาวน์เกรดแอปเป็นระดับ 25;

- อัปเกรดเป็น React 0.52 โดยที่ฟังก์ชันนั้นไม่มีอยู่แล้ว แล้วลองอีกครั้ง (React Libraries อาจใช้งานไม่ได้หลังจากนี้)

- แพตช์ฟังก์ชันในสาขา react-native 0.48 และลองใช้เวอร์ชันแพตช์ ปัญหาอื่น ๆ ที่เกี่ยวข้องกับ SDK อาจเกิดขึ้น (การตอบสนอง ณ จุดนี้ยังคงถูกคอมไพล์ด้วย SDK 22)

ขอให้มีความสุขในการเขียนโค้ด!

person Fco P.    schedule 07.02.2018

TYPE_SYSTEM_ALERT

ค่าคงที่นี้เลิกใช้แล้วใน API ระดับ 26 สำหรับแอปที่ไม่ใช่ระบบ ใช้ TYPE_APPLICATION_OVERLAY แทน

person Elad    schedule 11.06.2018

ตรวจสอบสิทธิ์ SYSTEM_ALERT_WINDOW หรือพยายามให้สิทธิ์การซ้อนทับด้วยตนเอง

ดังที่ @Fco P. บอกว่าคุณสามารถลองเปลี่ยนแปลงได้

mRedBoxDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

**## หากคุณใช้อุปกรณ์ Lenovo โปรดลองกับอันอื่น การอนุญาตเฉพาะนี้ทำให้เกิดปัญหาในอุปกรณ์ Lenovo ในบางครั้ง ****

person Dipendra Sharma    schedule 08.02.2018