Receiver里面启动dialog引发的一系列错误解决(SYSTEM_ALERT_WINDOW)
来源:互联网 发布:php空间试用 编辑:程序博客网 时间:2024/05/22 07:54
首先,在receiver中show出dialog的做法:
@Overridepublic void onReceive(final Context context, Intent intent) { if (GlobalConstantHolder.sTimer != null) { GlobalConstantHolder.sTimer.cancel(); GlobalConstantHolder.sTimer = null; } //对话框 AlertDialog.Builder builder = new AlertDialog.Builder(TheApplication.getContext()); builder.setTitle("强制下线通知"); //正文 builder.setMessage("您的账号已在别地登录,如不是本人操作,请尽快修改密码"); //不可取消 builder.setCancelable(false); //按钮 builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //销毁所有活动 GlobalConstantHolder.finishAll(); //启动登陆活动 Intent intent = new Intent(TheApplication.getContext(),LoginActivity.class); //在广播中启动活动,需要添加如下代码 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); } }); AlertDialog alterDialog = builder.create(); //添加对话框类型:保证在广播中正常弹出 alterDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); //对话框展示 alterDialog.show();}
其中所有的TheApplication.getContext()方法原来我是写成context的,就是传过来的context,但是有一些手机不行,会崩溃,所以我就换成了TheApplication.getContext(),他是全局的context(Application级别的)。
本来以为这就解决了,然而啊然而,居然在6.0及以上的手机中又蹦出了权限问题,检查AndroidManifest文件中的权限,发现漏掉了
<!--不加这个receiver弹出AlertDialog会出错.而且6.0以上要判断是否授权--><uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>这个权限。
加上之后,发现还是不行,查阅资料知,原来6.0之后,权限的配置没有那么简单了,原来6.0以上的权限分成了3个部分:normal permission、dangerous permission和special permission,其中前两种随便百度都能找到解释,第三种请看这位大神的链接点击打开链接。
第一种的权限只需要在AndroidManifest配置即可;
第二种则不仅仅需要在manifest中配置,而且还需要在java代码中设置:
首先
//先判断android版本(大于6.0执行)int SDK_VERSION = android.os.Build.VERSION.SDK_INT;if (SDK_VERSION >= 23) { //检测权限授权(针对6.0以上先安装后检查权限的情况) List<String> permissionsList = new ArrayList<>(); String[] permissions = null; if (ActivityCompat.checkSelfPermission(this,android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { permissionsList.add(android.Manifest.permission.WRITE_EXTERNAL_STORAGE); } if(ActivityCompat.checkSelfPermission(this,android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){ permissionsList.add(android.Manifest.permission.CAMERA) ; } if (permissionsList.size()!=0) { permissions = new String[permissionsList.size()]; for (int i = 0; i < permissionsList.size(); i++) { permissions[i] = permissionsList.get(i); } //此句调起权限授权框 ActivityCompat.requestPermissions(this, permissions, MY_PERMISSIONS_REQUEST_CODE); }然后在要使用的Activity中重写
@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == MY_PERMISSIONS_REQUEST_CODE) { for (int i = 0; i < grantResults.length; i++) { if (grantResults[i] != PackageManager.PERMISSION_GRANTED) { // Permission Denied // Toast.makeText(MainActivity.this, "Permission Denied", Toast.LENGTH_SHORT).show(); //若没有通过授权就直接退出程序,要不然后面需要权限的时候会崩 GlobalConstantHolder.finishAll(); finish(); break; } } return; } super.onRequestPermissionsResult(requestCode, permissions, grantResults);}我在这做的是,如果有一个我需要的权限没授权就退出程序不让用,防止之后因权限导致的问题出现。
第三种还不一样,不一样在于在代码中设置的规则不一样:
// 判断是否有SYSTEM_ALERT_WINDOW权限(特殊!既不属于normal permission,也不属于dangerous permission,属于special permission)if(!Settings.canDrawOverlays(this)) { // 申请SYSTEM_ALERT_WINDOW权限 Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())); // REQUEST_CODE2是本次申请的请求码 startActivityForResult(intent, SYSTEM_ALERT_WINDOW_REQUEST_CODE2);} else { //Do some thing else here.}
先是判断是否有SYSTEM_ALERT_WINDOW权限的方法是Settings.canDrawOverlays(context),为true为已授权,反之亦然。然后调起授权的方式不一样,它会以action的形式启动一个Activity来设置权限授权,SYSTEM_ALERT_WINDOW_REQUEST_CODE2是我定义的请求码,因为授权完成要在onActivityForResult中处理,根据这个请求码来判断:
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case SYSTEM_ALERT_WINDOW_REQUEST_CODE2: // 判断是否有SYSTEM_ALERT_WINDOW权限 if (Settings.canDrawOverlays(this)) { }else{ GlobalConstantHolder.finishAll(); } break; }}同样我做的是如果未授权就退出程序。
需要注意的是,这种类型的权限,不一定会使程序崩溃,像CAMERA和WRITE_EXTERNAL_STORAGE等权限,如果只在manifest中配置了而没有在代码中设置,则可能会出现拍的照存不上或者相册里的取不出来等问题。
这个第三种还有一个权限:WRITE_SETTINGS。不过我现在并不知道他是干什么的,等到以后用时再说。
最后,附上各种权限的分类:(以下内容出自点击打开链接)
Normal Permissions如下:
ACCESS_LOCATION_EXTRA_COMMANDS
ACCESS_NETWORK_STATE
ACCESS_NOTIFICATION_POLICY
ACCESS_WIFI_STATE
BLUETOOTH
BLUETOOTH_ADMIN
BROADCAST_STICKY
CHANGE_NETWORK_STATE
CHANGE_WIFI_MULTICAST_STATE
CHANGE_WIFI_STATE
DISABLE_KEYGUARD
EXPAND_STATUS_BAR
GET_PACKAGE_SIZE
INSTALL_SHORTCUT
INTERNET
KILL_BACKGROUND_PROCESSES
MODIFY_AUDIO_SETTINGS
NFC
READ_SYNC_SETTINGS
READ_SYNC_STATS
RECEIVE_BOOT_COMPLETED
REORDER_TASKS
REQUEST_INSTALL_PACKAGES
SET_ALARM
SET_TIME_ZONE
SET_WALLPAPER
SET_WALLPAPER_HINTS
TRANSMIT_IR
UNINSTALL_SHORTCUT
USE_FINGERPRINT
VIBRATE
WAKE_LOCK
WRITE_SYNC_SETTINGS
Dangerous Permissions:
group:android.permission-group.CONTACTS
permission:android.permission.WRITE_CONTACTS
permission:android.permission.GET_ACCOUNTS
permission:android.permission.READ_CONTACTS
group:android.permission-group.PHONE
permission:android.permission.READ_CALL_LOG
permission:android.permission.READ_PHONE_STATE
permission:android.permission.CALL_PHONE
permission:android.permission.WRITE_CALL_LOG
permission:android.permission.USE_SIP
permission:android.permission.PROCESS_OUTGOING_CALLS
permission:com.android.voicemail.permission.ADD_VOICEMAIL
group:android.permission-group.CALENDAR
permission:android.permission.READ_CALENDAR
permission:android.permission.WRITE_CALENDAR
group:android.permission-group.CAMERA
permission:android.permission.CAMERA
group:android.permission-group.SENSORS
permission:android.permission.BODY_SENSORS
group:android.permission-group.LOCATION
permission:android.permission.ACCESS_FINE_LOCATION
permission:android.permission.ACCESS_COARSE_LOCATION
group:android.permission-group.STORAGE
permission:android.permission.READ_EXTERNAL_STORAGE
permission:android.permission.WRITE_EXTERNAL_STORAGE
group:android.permission-group.MICROPHONE
permission:android.permission.RECORD_AUDIO
group:android.permission-group.SMS
permission:android.permission.READ_SMS
permission:android.permission.RECEIVE_WAP_PUSH
permission:android.permission.RECEIVE_MMS
permission:android.permission.RECEIVE_SMS
permission:android.permission.SEND_SMS
permission:android.permission.READ_CELL_BROADCASTS
补充优化:
当你第一次拒绝后再次启动程序就会有“拒绝后不再提醒”的选项,选了之后会不再提醒,根据以上的代码则不会退出程序,所以就会有潜在危险存在。怎么办呢?
先看我在SYSTEM_ALERT_WINDOW权限返回方法里加入:
//如果没有对SYSTEM_ALERT_WINDOW权限授权,则弹出框提示new AlertDialog.Builder(this).setCancelable(false) .setTitle("警告").setMessage("您还没有对悬浮窗权限授权,将无法继续使用该程序!\n\n是否去开启悬浮窗权限?") .setPositiveButton("是", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //以下代码可以调到该应用相关信息框,然后那个页点击权限管理就可以设置了 Intent localIntent = new Intent(); localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if (Build.VERSION.SDK_INT >= 9) { localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS"); localIntent.setData(Uri.fromParts("package", getPackageName(), null)); } else if (Build.VERSION.SDK_INT <= 8) { localIntent.setAction(Intent.ACTION_VIEW); localIntent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails"); localIntent.putExtra("com.android.settings.ApplicationPkgName", getPackageName()); } startActivity(localIntent); //若没有通过授权就直接退出程序,要不然后面需要权限的时候会崩 GlobalConstantHolder.finishAll(); } }).setNegativeButton("否", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //若没有通过授权就直接退出程序,要不然后面需要权限的时候会崩 GlobalConstantHolder.finishAll(); }}).show();如果未授权,则弹出框提示他,点击“是”跳到权限设置相关界面让他选择,之所以“是”和“否”都关闭程序是为了防止他点击了“是”,但是并没有实际选择打开权限,所以都要关闭,权限设置了之后他自己再去打开app。
同样的,看dangerous permission的返回方法:
for (int i = 0; i < grantResults.length; i++) { if (grantResults[i] != PackageManager.PERMISSION_GRANTED) { // Permission Denied // Toast.makeText(MainActivity.this, "Permission Denied", Toast.LENGTH_SHORT).show(); new AlertDialog.Builder(this).setCancelable(false) .setTitle("警告").setMessage("您有必要的权限还没有授权,将无法继续使用该程序!\n\n是否去开启权限?") .setPositiveButton("是", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //以下代码可以调到该应用相关信息框,然后那个页点击权限管理就可以设置了 Intent localIntent = new Intent(); localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if (Build.VERSION.SDK_INT >= 9) { localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS"); localIntent.setData(Uri.fromParts("package", getPackageName(), null)); } else if (Build.VERSION.SDK_INT <= 8) { localIntent.setAction(Intent.ACTION_VIEW); localIntent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails"); localIntent.putExtra("com.android.settings.ApplicationPkgName", getPackageName()); } startActivity(localIntent); //若没有通过授权就直接退出程序,要不然后面需要权限的时候会崩 GlobalConstantHolder.finishAll(); } }).setNegativeButton("否", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //若没有通过授权就直接退出程序,要不然后面需要权限的时候会崩 GlobalConstantHolder.finishAll(); } }).show(); break; }}如果有拒绝的,就会弹框,哪怕你选择“拒绝之后不再提示”,他下次打开时还会回调这个方法,只不过
//此句调起权限授权框ActivityCompat.requestPermissions(this, permissions, MY_PERMISSIONS_REQUEST_CODE);
这一句没有调起权限授权框而已,这么做的原因同上。
还有一点,看过一个资料,说是fragment中动态设置权限调用requestPermissions(permissions, MY_PERMISSIONS_REQUEST_CODE);这个方法才行,并且他依赖的activity的最终父类必须是AppCompatActivity,不知道真假,先记着。
- Receiver里面启动dialog引发的一系列错误解决(SYSTEM_ALERT_WINDOW)
- Android 使用全局的静态变量,引发一系列诡异错误
- RMaigic 一系列错误解决
- AdPredictor引发的一系列故事
- 记录错误16.8.12 android receiver dialog
- React Native运行Android时提示要下载: gradle-2.4-all.zip 引发的一系列错误
- 由”构造函数“引发的一系列的。。。
- 由”构造函数“引发的一系列的。。
- 重建控制文件引发的一系列ORA
- Wordpress for Sae引发的一系列
- 关于Android SDK更新之后引发的一系列错误及其解决办法——DIY Android SDK 的体验
- 解决eclipse里面的Access restriction错误
- 由矩阵转置引发的一系列思考(线性代数的核心)
- iOS回顾笔记( 02 ) -- 由九宫格布局引发的一系列“惨案”
- iOS回顾笔记( 02 ) -- 由九宫格布局引发的一系列“惨案”
- Eclipse启动错误的解决
- html的em标签引发的一系列思考
- MySQL 5 安装或卸载引发的错误解决
- linux安装rabbitMQ
- IP地址的问题
- iOS五种页面传值方式
- Bootstrap响应式框架初学准备工作
- spacemacs shell layer
- Receiver里面启动dialog引发的一系列错误解决(SYSTEM_ALERT_WINDOW)
- 【leetCode】 Count of Smaller Numbers After Self
- 一号信令详细介绍
- 浅说二叉树路径和
- bzoj 1006: [HNOI2008]神奇的国度
- struts2参数封装
- HDU 1711 Number Sequence
- [我所知道的BIOS]->[系統架構] 2
- SQL 语句性能调优