今天学习android开发的时候,楼主看的是网上很火的《第一行代码----Android》,书中在介绍完广播的时候,写了一个案例,模拟QQ被迫下线的功能。
具体思路大概是,在用户登录系统之后,在主界面点击一个按钮发送一个消息,程序本身接收到这个消息,弹出一个系统级的对话框提示用户被迫下线,用户点击确定按钮之后,即退出到登录界面。
逻辑比较简单,下面是广播接收器代码:
public class ForceReceiver extends BroadcastReceiver {
// 接收到广播之后,关闭所有的活动,打开登录活动
@Override
public void onReceive(final Context context, Intent intent) {
// 弹出对话框
AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setTitle("温馨提示");
alert.setMessage("系统检测到异常,您将被迫下线.");
alert.setCancelable(false);
alert.setPositiveButton("确定", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intentCreate = new Intent(context, LoginActivity.class);
intentCreate.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intentCreate);
ActivityCollector.finishAll();
}
});
AlertDialog alertDialog = alert.create();
alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
alertDialog.show();
}
}
书上介绍,需要弹出一个系统级对话框,也就是这个对话框不论是在哪个活动,都可以弹出这个对话框。所以要设置对话框的属性为:
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
最后在AndroidManifest.xml中加上权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
但是我部署到手机上点击的发送广播的时候,程序直接崩了,出现了以下异常:
java.lang.RuntimeException: Unable to start receiver com.example.broadcastbestpractice.ForceReceiver: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@44f78ce -- permission denied for this window type
觉得很纳闷,都是按照文档上的思路,怎么就出错了。查看了好多资料,终于知道,原来是因为google在6.0上对应用权限进行了优化,需要单独开启,SYSTEM_ALERT_WINDOW,设置悬浮窗需要单独开启权限:
参考网址:点击参考
添加以下代码:
private static final int REQUEST_CODE = 1;
private void requestAlertWindowPermission() {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, REQUEST_CODE);
}
这些个代码都需要sdk版本是在23以上才能运行。
加了之后,完美运行,安装的时候,会提示用户是否开启悬浮窗:
如下图:
允许之后,点击按钮,操作结果如下图: