android.view.WindowManager$BadTokenException: Unab

2019-04-04 17:06发布

Here's my stack trace:

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)

I found an answer about TYPE_SYSTEM_ERROR being deprecated in Android Oreo (8) so I implemented the following method that I also found:

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

Inside of my onCreate() method I have:

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

I still get the error.

I am using Expo SDK 21, React Native 0.48. The application has been detached to ExpoKit.

After each change I clean my project and then run it on an Emulator through Android Studio.

Edit: I am running this on a Nexus 5X emulator, running on API 27.

3条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-04-04 17:21

Verify SYSTEM_ALERT_WINDOW Permission Or try to provide Overlay Permission Manually.

As @Fco P. said you can try to change

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

**## If you are using Lenovo device. Please try with another one. This particular permission makes problem sometime in Lenovo device.****

查看更多
放荡不羁爱自由
3楼-- · 2019-04-04 17:24
TYPE_SYSTEM_ALERT

This constant was deprecated in API level 26. for non-system apps. Use TYPE_APPLICATION_OVERLAY instead.

查看更多
Animai°情兽
4楼-- · 2019-04-04 17:29

I saw this error some time ago, when I updated a native&react app to SDK 26. The problem is the react-native function that creates the red dialog for development. That functions uses TYPE_SYSTEM_ALERT as their type, so you can't use an SDK level bigger than 25 in your hybrid app with that version of react-native, unless you patch that function so it no longer uses TYPE_SYSTEM_ALERT.

this is the react-native code in 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();
          }
        });
  } 

You would need to change the mRedBoxDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); call to other type. But, this does not give you any guarantees you'll be able to run your app with SDK 26, when I tried to compile react with SDK 26, other parts of the project "reacted" exploding, so this is unlikely to work at short term (you may need to start fixing other problems). So your options are:

-Downgrade the app to level 25;

-Upgrade to react 0.52, where that function no longer exist, and try again (react libraries may not work after this)

-Patch the function in react-native 0.48 branch and try the patched version. Some other issues related to the SDK may arose (react at this point is still being compiled with SDK 22)

Happy coding!

查看更多
登录 后发表回答