最近在学习Android内容提供商(Content Providers)这部分时,模仿书上的获取通讯录的程序,基本一样的程序代码,打开应用却秒退了:
看了一下运行记录,有以下这段错误提示:
“Caused by: java.lang.SecurityException: Permission Denial:
opening provider com.android.providers.contacts.ContactsProvider2 from
ProcessRecord{ea02adc 6872:com.example.administrator.phonebook/u0a85}
(pid=6872, uid=10085) requires android.permission.READ_CONTACTS or
android.permission.WRITE_CONTACTS”
错误来源是下面这句获取通讯录信息的代码:
Cursor cursor = this.getContentResolver().query(contacts,null,null,null,null);
看到permission就大概知道是权限的问题了,在网上查了一下,好像要在Manifest里面添加下面这句标签:
<uses-permission android:name="android.permission.READ_CONTACTS" />
然后又满怀期待地运行了一下。。。还是停止运行+一样的问题提示。突然间就觉得碰上大麻烦了,权限已经允许了,却还是给我报告权限问题,大白天见鬼了?
经过一个晚上的资料查找,加上贡献自己的主用机小米做试验,终于知道了问题产生的原因:
Android系统的SDK在23以上的版本对于权限的获取需要开发者自己添加代码去询问用户!
换句话说,在Android 6.0 以下的版本,在安装app时,会有一堆一般人不会去看的权限获取提示,而这显得不安全,于是在Android 6.0 以上版本,安装app时不再有显示权限,取而代之的是在应用运行时会弹出提示框让用户自己确认是否运行应用的该项权限。
像我这里用的Android 7.0允许环境既没有允许获取通讯录的权限,又没有加入异常处理机制,所以就直接秒退了。
虽然知道了原因,解决办法也找了很长时间,需要在获取通讯录操作前加如下代码:
//判断是否有某种权限
if (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(MainActivity.this,android.Manifest.permission.READ_CONTACTS)) {
//has permission, do operation directly
Toast.makeText(this,"有权限了",Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(this,"没有权限",Toast.LENGTH_SHORT).show();
//没有权限在此处获取权限
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.READ_CONTACTS},1);
//return;
}
总之权限只要询问一次被允许了,以后就不会再被禁止,除非用户手动关闭,ActivityCompat.requestPermissions的最后一个参数”1”是一个与权限状态返回相关的代码,是自己随便定义的,最好用一个final宏代替。