android开发中悬浮窗被禁用,无权限开启悬浮窗的解决方案

首先,感谢这两篇博文http://blog.csdn.net/cankingapp/article/details/51569576
http://blog.csdn.net/cool_fuwei/article/details/53070232
了解知识:
1.首先要知道6.0版本权限模型跟原来版本是不同的,不再是统一在manifest中默认系统授权,而是有需要的时候,向系统请求授权,提高用户体验。
2.了解权限检测流程,一点注意点是如果系统权限弹窗提示框被不再提醒了,需要我们自定义提示弹窗,引导用户去授权。
3.明白权限类型,分为normal和dangerous类型,同时,在dangerous中还需要注意一点,SYSTEM_ALERT_WINDOW 和 WRITE_SETTINGS这两个特殊授权请求方式,跟一般授权请求方式不同。
4.在判断APP是否运行在Android M上,可以用版本号来判断,可以准确点。

问题一:在安卓开发中处理悬浮窗权限时,发现魅族和小米手机无论android4.4.4、android5.1.1还是android6.0,权限manifest中:android.permission.SYSTEM_ALERT_WINDOW权限也加过了,就是弹不起。这个权限也不是android 6.0中的敏感权限,所以android 6.0动态申请权限也是行不通的,这个问题很难通过diamante打开悬浮窗,没辙之后想到,调用应用的设置界面引导用户去手动的打开。

问题二:在三星6.0或android6.0及android 6.0以上的手机(小米和魅族处理方式另外处理同上),未处理弹窗问题可能会引发以下问题,

android.view.WindowManager$BadTokenException: Unable to add window 

android.view.ViewRootImpl$W@a299900 -- permission denied for this window type


 at android.view.ViewRootImpl.setView(ViewRootImpl.java:879)


 at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:337)


 at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)


 at android.app.Dialog.show(Dialog.java:350)

话不多说,直接上代码处理以上两个疑问。

 @Override
    public void onClick(View view) {
        String user = edit_user.getText().toString();
        String pwd = edit_pwd.getText().toString();
        if (user.equals("123") && pwd.equals("123")) {
            editor = pref.edit();
            editor.putString("user", user);
            editor.putString("pwd", pwd);
            editor.commit();
            //开启悬浮窗前先请求权限
            if ("Xiaomi".equals(Build.MANUFACTURER)) {//小米手机
                LogUtil.E("小米手机");
                requestPermission();
            } else if ("Meizu".equals(Build.MANUFACTURER)) {//魅族手机
                LogUtil.E("魅族手机");
                requestPermission();
            } else {//其他手机
                LogUtil.E("其他手机");
                if (Build.VERSION.SDK_INT >= 23) {
                    if (!Settings.canDrawOverlays(this)) {
                        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
                        startActivityForResult(intent, 12);
                    } else {
                        switchActivity();
                    }
                } else {
                    switchActivity();
                }
            }
        } else {
            ToastUtil.show(this, "这么简单都出错,脑子呢?");
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 11) {
            if (isFloatWindowOpAllowed(this)) {//已经开启
                switchActivity();
            } else {
                ToastUtil.show(this, "开启悬浮窗失败");
            }
        } else if (requestCode == 12) {
            if (Build.VERSION.SDK_INT >= 23) {
                if (!Settings.canDrawOverlays(LoginActivity.this)) {
                    ToastUtil.show(this, "权限授予失败,无法开启悬浮窗");
                } else {
                    switchActivity();
                }
            }
        }

    }

    /**
     * 跳转Activity
     */
    private void switchActivity() {
        startActivity(new Intent(LoginActivity.this, Main2Activity.class));
        ToastUtil.show(LoginActivity.this, "吆,竟然蒙对了!");
        finish();
    }

    /**
     * 判断悬浮窗权限
     *
     * @param context
     * @return
     */
    @TargetApi(Build.VERSION_CODES.KITKAT)
    public static boolean isFloatWindowOpAllowed(Context context) {
        final int version = Build.VERSION.SDK_INT;
        if (version >= 19) {
            return checkOp(context, 24);  // AppOpsManager.OP_SYSTEM_ALERT_WINDOW
        } else {
            if ((context.getApplicationInfo().flags & 1 << 27) == 1 << 27) {
                return true;
            } else {
                return false;
            }
        }
    }

    @TargetApi(Build.VERSION_CODES.KITKAT)
    public static boolean checkOp(Context context, int op) {
        final int version = Build.VERSION.SDK_INT;

        if (version >= 19) {
            AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
            try {
                Class<?> spClazz = Class.forName(manager.getClass().getName());
                Method method = manager.getClass().getDeclaredMethod("checkOp", int.class, int.class, String.class);
                int property = (Integer) method.invoke(manager, op,
                        Binder.getCallingUid(), context.getPackageName());
                Log.e("399", " property: " + property);

                if (AppOpsManager.MODE_ALLOWED == property) {
                    return true;
                } else {
                    return false;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            Log.e("399", "Below API 19 cannot invoke!");
        }
        return false;
    }


    /**
     * 请求用户给予悬浮窗的权限
     */
    public void requestPermission() {
        if (isFloatWindowOpAllowed(this)) {//已经开启
            switchActivity();
        } else {
            openSetting();
        }
    }


    /**
     * 打开权限设置界面
     */
    public void openSetting() {
        try {
            Intent localIntent = new Intent(
                    "miui.intent.action.APP_PERM_EDITOR");
            localIntent.setClassName("com.miui.securitycenter",
                    "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
            localIntent.putExtra("extra_pkgname", getPackageName());
            startActivityForResult(localIntent, 11);
            LogUtil.E("启动小米悬浮窗设置界面");
        } catch (ActivityNotFoundException localActivityNotFoundException) {
            Intent intent1 = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
            Uri uri = Uri.fromParts("package", getPackageName(), null);
            intent1.setData(uri);
            startActivityForResult(intent1, 11);
            LogUtil.E("启动悬浮窗界面");
        }

    }
  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值