3月31日学习笔记(6.0版本用Broadcast实现强制下线功能问题)

这几天把《第一行代码》里用广播实现强制下线功能的程序实现了一下,发现最后在实现强制下线功能,弹出警告窗口时,会导致程序奔溃。查看日志,发现错误

java.lang.RuntimeException: Unable to start receiver test.zyf.com.broadcasttest.ForceOfflineReceiver: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@7d4996d -- permission denied for this window type

没有获得警告窗口权限,可是明明已经声明权限android.permission.SYSTEM_ALERT_WINDOW。最后,折腾了好久,终于发现问题出在6.0版本,权限SYSTEM_ALERT_WINDOW属于特殊权限,在申明权限之后还必须发送请求获得用户授权。这是6.0版本的动态权限管理机制,意在提高用户体验和程序安全性。
现在提供一种解决方法,在原先代码的基础上,首先新建一个PermissionUtils类

public class PermissionUtils {
    private static final String TAG = "PermissionUtils";
    public static final int PERMISSION_SETTING_REQ_CODE = 0x1000;

    /**
     * 检测系统弹出权限
     */
    @TargetApi(23)
    public static boolean checkSettingAlertPermission(Object cxt, int req) {
        if (cxt instanceof Activity) {
            Activity activity = (Activity) cxt;
            if (!Settings.canDrawOverlays(activity.getBaseContext())) {
                Log.i(TAG, "Setting not permission");

                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                        Uri.parse("package:" + activity.getPackageName()));
                activity.startActivityForResult(intent, req);
                return false;
            }
        } else if (cxt instanceof Fragment) {
            Fragment fragment = (Fragment) cxt;
            if (!Settings.canDrawOverlays(fragment.getActivity())) {
                Log.i(TAG, "Setting not permission");

                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                        Uri.parse("package:" + fragment.getActivity().getPackageName()));
                fragment.startActivityForResult(intent, req);
                return false;
            }
        } else {
            throw new RuntimeException("cxt is net a activity or fragment");
        }
        return true;
    }
}

接下来为强制下线按钮设置监听事件

forceOffline.setOnClickListener(new View.OnClickListener(){
    @Override
    public void onClick(View v){
        if(PermissionUtils.checkSettingAlertPermission(MainActivity.this, PermissionUtils.PERMISSION_SETTING_REQ_CODE == true)){
            Intent intent = new Intent("test.zyf.com.broadcasttest.FORCE_OFFLINE");
            sendBroadcast(intent);
      }
    }
});

重写方法onActivityResult()或着onRequestPermissionsResult()方法,这里我自己用第一种方法实现

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == PermissionUtils.PERMISSION_SETTING_REQ_CODE) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (Settings.canDrawOverlays(this)) {
                    return;
                } else {
                    Toast.makeText(this, "not has setting permission", Toast.LENGTH_LONG).show();
                    finish();
                }
            }
        }
    }

折腾好几天,记录一下。

PS:6.0版本前的几个版本均可以正常运行《第一行代码》上的程序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值