问题:
之前在开发作业的时候,在Android 12的环境下,不做任何处理,alarm应用中,闹钟响铃时,alarm应用会crash。
报错信息:
java.lang.RuntimeException: Unable to start service
com.android.deskclock.alarms.AlarmService@c351e33 with Intent { act=START_ALARM
dat=content://com.android.deskclock/instances/44
cmp=com.android.deskclock/.alarms.AlarmService }: java.lang.SecurityException:
getCallState: Neither user 10141 nor current process has
android.permission.READ_PHONE_STATE.
锁定出错位置:
AlarmService中,在startAlarm()中调用了getCallState()方法来获取phone的状态时出现了crash
解决方案:
在Android6.0以后,调用getCallState()需要动态授予READ_PHONE_STATE权限(危险权限)
先在权限清单中加入READ_PHONE_STATE权限
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
在应用的MainActivity中,加入动态授权的流程。一开始进入应用时,判断是否授予READ_PHONE_STATE权限。
建议在onResume(每次打开这个activity都会加载onResume)中加入权限检查,不要在onCreate中(只在第一次打开activity时,才会加载onCreate)加。第一次授予权限以后,在应用还没被杀死的时候,再将权限拒绝,后面的问题无法避免。
@Override
public void onResume() {
super.onResume();
//如果没有授予READ_PHONE_STATE权限
if(ContextCompat.checkSelfPermission(AlarmMainActivity.this, Manifest.
permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED){
//跳转授权界面
ActivityCompat.requestPermissions(AlarmMainActivity.this, new
String[]{ Manifest.permission.READ_PHONE_STATE}, 1);
}else {
// 如果有其他权限(非危险权限)的判断,可在这里进行操作
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode){
case 1:
if(grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED){
//如果没授予此权限,则结束应用
//也可以做其它处理
finish();
}
break;
default:
}
}
附加问题:
本以为这个问题就这样愉快滴解决了。结果这两天,测试来找我说Monkey测试时,clock会发生crash
我看了一下log,发现还是这个问题。
我猜测要么是clock应用没打开就运行了AlarmService.java,调用了getCallState()方法导致的crash,要么是READ_PHONE_STATE权限没生效。
这个问题必须解决,如果clock发生crash太多次,会被杀死,程序就停止了。
ActivityManager: Force-killing crashed app com.android.deskclock at watcher's request
解决方法:
Android Q,去掉了READ_PHONE_STATE权限,取而代之的是一个系统级别的权限:READ_PRIVILEGED_PHONE_STATE,这个权限不是危险权限,不需要动态授权,就不会出现crash了。
开发者网站请参考: