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

来源:互联网 发布:mac unable to launch 编辑:程序博客网 时间:2024/05/21 11:07

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

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版本前的几个版本均可以正常运行《第一行代码》上的程序

0 0