关于读取通讯录时应用秒退的问题

最近在学习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宏代替。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 要在Android Studio中读取通讯录,您需要使用ContentResolver类和ContactsContract类。您可以使用ContentResolver查询ContactsContract.Contacts表以获取所有联系人的ID,然后使用ContactsContract.CommonDataKinds.Phone表查询每个联系人的电话号码。您还可以使用ContactsContract.CommonDataKinds.Email表查询每个联系人的电子邮件地址。请注意,您需要在AndroidManifest.xml文件中添加READ_CONTACTS权限才能访问通讯录数据。 ### 回答2: Android Studio是一款为Android应用程序开发专门设计的集成开发环境(IDE)。通讯录是存储联系人信息的集合,包括姓名、电话号码、电子邮件等。在开发Android应用程序,我们通常需要访问设备上的通讯录,并读取其中的联系人信息。下面我们将详细介绍如何在Android Studio中读取通讯录。 第一步是添加必要的权限。在AndroidManifest.xml文件中添加以下代码: ``` <uses-permission android:name="android.permission.READ_CONTACTS" /> ``` 这将授予应用程序读取通讯录权限。 第二步是编写代码。我们可以使用ContentResolver类来读取通讯录: ``` ContentResolver contentResolver = getContentResolver(); Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null); if (cursor.getCount() > 0) { while (cursor.moveToNext()) { String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); if (Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) { Cursor phoneCursor = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[]{id}, null); while (phoneCursor.moveToNext()) { String phone = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); } phoneCursor.close(); } } } cursor.close(); ``` 以上代码将查询所有联系人,并将它们的姓名和电话号码显示在控制台上。 完成以上两个步骤后,我们便能够在Android Studio中成功读取通讯录了。需要注意的是,读取通讯录的操作可能会很耗,因此应该避免在UI线程上执行此操作,以免造成不良用户体验。建议使用AsyncTask或Loader等异步工具来执行此操作。 ### 回答3: 在Android Studio中读取通讯录需要使用ContentProvider和Cursor对象来获取数据。ContentProvider是一个Android框架的核心组件,用于管理应用程序中的数据,包括通讯录信息。通讯录数据可以使用ContactsContract类来访问。 首先,我们需要在AndroidManifest.xml文件中添加读取通讯录权限: ```xml <uses-permission android:name="android.permission.READ_CONTACTS" /> ``` 接下来,在Activity或Fragment中获取通讯录数据。我们可以用以下代码来获取所有联系人的姓名和手机号码: ```java ContentResolver contentResolver = getContentResolver(); String[] projection = new String[] { ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER }; Cursor cursor = contentResolver.query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projection, null, null, null ); if (cursor != null) { while (cursor.moveToNext()) { String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); String phoneNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); Log.d(TAG, "Name: " + name + " Phone Number: " + phoneNumber); } cursor.close(); } ``` 上面的代码首先获取了ContentResolver对象,然后使用projection数组获取需要的通讯录信息,使用ContentResolver的query方法获取通讯录数据Cursor对象。最后使用while循环遍历Cursor对象,获取每个联系人的姓名和手机号码。 注意,应该在使用完Cursor对象后及关闭它,以释放资源。 以上就是在Android Studio中读取通讯录的方法。读取通讯录Android开发中经常用到的一个功能,也是了解ContentProvider和Cursor对象的重要一步。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值