【问题标题】:Android permission denied for window type 2010 in Marshmallow or higher棉花糖或更高版本中窗口类型 2010 的 Android 权限被拒绝
【发布时间】:2016-10-25 05:31:00
【问题描述】:

我尝试让 Chathead 类型在我的应用上过度绘制 via Android Service,如下图所示。

这个聊天头应用程序适用于 Android 版本 5 或更低版本(kitkat、棒棒糖等)。但我在 Marshmallow 和更高版本中尝试它,然后得到这个错误。

 android.view.WindowManager$BadTokenException: Unable to add window
 android.view.ViewRootImpl$W@48f5767 -- permission denied for window type 2010

聊天头代码

注意:我是从 Android 服务调用这个函数

权限列表:

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

private WindowManager windowManager;
private ImageView chatHead;
WindowManager.LayoutParams params;

@Override
    public void onCreate() {
        super.onCreate();
        windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        chatHead = new ImageView(this);
        chatHead.setImageResource(R.drawable.settingsicon);
        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.LEFT;
        params.x = 0;
        params.y = 100;
        windowManager.addView(chatHead, params);

        chatHead.setOnTouchListener(new View.OnTouchListener() {
            private int initialX;
            private int initialY;
            private float initialTouchX;
            private float initialTouchY;
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        initialX = params.x;
                        initialY = params.y;
                        initialTouchX = event.getRawX();
                        initialTouchY = event.getRawY();                       
                        return true;
                    case MotionEvent.ACTION_UP:                        
                        return true;
                    case MotionEvent.ACTION_MOVE:
                        params.x = initialX + (int) (event.getRawX() - initialTouchX);
                        params.y = initialY + (int) (event.getRawY() - initialTouchY);
                        windowManager.updateViewLayout(chatHead, params);
                        return true;
                }
                return false;
            }
        }
    }

如何在 Mashmallow 或更高版本的 Android 上解决此错误?

【问题讨论】:

标签: android android-layout android-permissions


【解决方案1】:

在显示聊天头之前调用此方法请求许可:

 public void addOverlay() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (!Settings.canDrawOverlays(this)) {
            askedForOverlayPermission = true;
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
            startActivityForResult(intent, OVERLAY_PERMISSION_CODE);
        }
    }
}

在权限结果之后,如果用户允许权限,那么只有您可以显示如下聊天头:

 @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == OVERLAY_PERMISSION_CODE) {
        askedForOverlayPermission = false;
        if (Settings.canDrawOverlays(this)) {
            // SYSTEM_ALERT_WINDOW permission not granted...
            //Toast.makeText(MyProtector.getContext(), "ACTION_MANAGE_OVERLAY_PERMISSION Permission Granted", Toast.LENGTH_SHORT).show();
            Intent serviceIntent = new Intent(Homepage.this, ChatHeadService.class);
            serviceIntent.putExtra("removeUserId", friendId);
            startService(serviceIntent);

        } else {
             Toast.makeText(MyProtector.getContext(), "ACTION_MANAGE_OVERLAY_PERMISSION Permission Denied", Toast.LENGTH_SHORT).show();
        }
    }

如果它对你有帮助,请告诉我......祝你好运。

【讨论】:

  • 我通过服务调用这个。如果这个代码块适用于android服务?
  • 是的,它绝对有效,检查上面的代码我正在启动与您想要的服务相同的服务。如果有帮助,请接受并投票。
  • 如何在服务中覆盖onActivityResult?没有方法可以覆盖:(
  • 您应该在开始服务之前添加它。如果用户授予权限,我将在 onActivityResult 中启动我的聊天头服务,请检查上面的代码。
【解决方案2】:

它帮助了我

WindowManager.LayoutParams params = new WindowManager.LayoutParams(); params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;

【讨论】:

    【解决方案3】:

    从 M 版(api 级别 23)开始,Android 有了运行时请求权限的新算法。见这里:https://developer.android.com/training/permissions/requesting.html

    【讨论】:

      【解决方案4】:

      类型 = TYPE_PHONE 的覆盖在 Orea(API 级别 26)中已弃用。 非系统应用仅支持 TYPE_APPLICATION_OVERLAY。

      【讨论】:

        【解决方案5】:

        看起来您的 addView() 方法失败了。 我已经解决了这个问题(在某些情况下),使用 WindowManager.LayoutParams.TYPE_PHONE 用于 8.0 以下的 Android SDK 和 WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY 用于 8.0 及更高版本。 您可以添加一些自动选择以授予主要兼容性(取决于活动的 SDK 平台),但由于 Google Play 不允许 8.0 以下的 APK,这显然是不必要的。 希望对您有所帮助。

        【讨论】:

          猜你喜欢
          • 2016-05-12
          • 2018-01-18
          • 2019-02-03
          • 2016-02-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多