Android: permission denied for window type 2038 using TYPE_APPLICATION_OVERLAY

匿名 (未验证) 提交于 2019-12-03 02:56:01

问题:

I trying to create a view that is above other applications:

WindowManager.LayoutParams paramsDirectorView = new WindowManager.LayoutParams(         WindowManager.LayoutParams.WRAP_CONTENT,         WindowManager.LayoutParams.WRAP_CONTENT,         WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,         WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,         PixelFormat.TRANSLUCENT); 

I have looked in other responses and found the following things for "drawing over applications":

  • I have android.permission.SYSTEM_ALERT_WINDOW in the manifest
  • I am doing the Settings.canDrawOverlays(this) check which comes back true.
  • I have done everything located here permission denied for window type

I am still getting "-- permission denied for window type 2038" error. As of now I am using TYPE_PHONE and it works, but it is deprecated and says to use TYPE_APPLICATION_OVERLAY. Can some one follow up on this as the TYPE_PHONE answer is not truly a resolution but a "patch work" solution that is deprecated in Android O.

I am running on Android 7.1.2

android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@1f47e89 -- permission denied for window type 2038 at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3344) at android.app.ActivityThread.-wrap21(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1583) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6121) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779) Caused by: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@1f47e89 -- permission denied for window type 2038 at android.view.ViewRootImpl.setView(ViewRootImpl.java:703) at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:342) at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93) at HeadService.TwoViewManager.(TwoViewManager.java:99) at HeadService.UIHeadService.onStartCommand(UIHeadService.java:65) at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3327) at android.app.ActivityThread.-wrap21(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1583) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6121) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)

回答1:

I had the exactly same issue. I guess you should differentiate the target (before and after Oreo)

int LAYOUT_FLAG; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {      LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; } else {         LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE; }  params = new WindowManager.LayoutParams(         WindowManager.LayoutParams.WRAP_CONTENT,         WindowManager.LayoutParams.WRAP_CONTENT,         LAYOUT_FLAG,         WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,         PixelFormat.TRANSLUCENT); 


回答2:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> 

I had the exactly same issue in service class(before and after Marshmallow).

if (Build.VERSION.SDK_INT >= 23) {     if (!Settings.canDrawOverlays(this)) {         Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,           Uri.parse("package:" + getPackageName()));         startActivityForResult(intent, 1234);     } } else {     startService(new Intent(SplashActivity.this,                          CheckServicesForApps.class)); }  @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {     super.onActivityResult(requestCode, resultCode, data);     if (requestCode == 1234) {             startService(new Intent(SplashActivity.this,              CheckServicesForApps.class));      } }  public class CheckServicesForApps extends Service {     private Context context = null;      @Override     public void onCreate() {         super.onCreate();          ImageView imageView = new ImageView(context);         imageView.setVisibility(View.GONE);          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {             try {                 windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);                  //here is all the science of params                 final WindowManager.LayoutParams params = new WindowManager.LayoutParams(                         WindowManager.LayoutParams.WRAP_CONTENT,                         WindowManager.LayoutParams.WRAP_CONTENT,                         WindowManager. LayoutParams.TYPE_SYSTEM_ERROR,                         WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED                                 | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON                                 | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,                         PixelFormat.TRANSLUCENT                 );                  windowManager.addView(imageView, params);                 hand=new Handler();              } catch (Exception e) {                 hand=new Handler();                 e.printStackTrace();             }         }else{             windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);              final WindowManager.LayoutParams params = new WindowManager.LayoutParams(                     WindowManager.LayoutParams.WRAP_CONTENT,                     WindowManager.LayoutParams.WRAP_CONTENT,                     WindowManager.LayoutParams.TYPE_PHONE,                     WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,                     PixelFormat.TRANSLUCENT);              params.gravity = Gravity.TOP | Gravity.CENTER;             params.x = ((getApplicationContext().getResources().getDisplayMetrics().widthPixels) / 2);             params.y = ((getApplicationContext().getResources().getDisplayMetrics().heightPixels) / 2);             windowManager.addView(imageView, params);         }     }      @Override     public IBinder onBind(Intent intent) {         return null;     }      @Override     public int onStartCommand(Intent intent, int flags, int startId) {         /* We want this service to continue running until it is explicitly         * stopped, so return sticky.         */         return START_STICKY;     }      @Override     public void onDestroy() {         super.onDestroy();          if (imageView != null) {             try {                 windowManager.removeView(imageView);             } catch (Exception e) {                 e.printStackTrace();             }         }         /**** added to fix the bug of view not attached to window manager ****/     } } 


回答3:

Try to change WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY to WindowManager.LayoutParams.TYPE_PHONE?



回答4:

Did you request runtime permission by calling following intent?

private void requestOverlayPermission() {     if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) {         return;     }      Intent myIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);     myIntent.setData(Uri.parse("package:" + getPackageName()));     startActivityForResult(myIntent, APP_PERMISSIONS); } 

Then in onActivityResult() check if Settings.canDrawOverlays(this) is true otherwise request permission again by calling above method.



回答5:

Source SYSTEM_ALERT_WINDOW String SYSTEM_ALERT_WINDOW Allows an app to create windows using the type TYPE_APPLICATION_OVERLAY, shown on top of all other apps. Very few apps should use this permission; these windows are intended for system-level interaction with the user.

Note: If the app targets API level 23 or higher, the app user must explicitly grant this permission to the app through a permission management screen. The app requests the user's approval by sending an intent with action ACTION_MANAGE_OVERLAY_PERMISSION. The app can check whether it has this authorization by calling Settings.canDrawOverlays().



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!