Android 获取联系人列表未在 Android 10 中显示

问题描述

我正在尝试在 android 中获取联系人列表。它在 andorid 6 和 7 中工作正常。但是当我在 andorid 10 中运行相同的代码时,它没有显示任何单个联系人。 Android 10 有什么变化吗? 这是我的代码

 private fun prepareData() {
        contactList.clear()
        val cur: Cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI,null,null)!!
        if (cur.count > 0) {
            while (cur.movetoNext()) {
                val id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID))
                val cur1: Cursor = contentResolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI,ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?",arrayOf(id),null)!!
                while (cur1.movetoNext()) {
                    //to get the contact data
                    val name = cur1.getString(cur1.getColumnIndex(ContactsContract.CommonDataKinds.Phone.disPLAY_NAME))
                    val phoneticName = cur1.getString(cur1.getColumnIndex(ContactsContract.CommonDataKinds.Phone.PHONETIC_NAME))
                    val phoneNumber = getPhoneNumber()
                    val email = cur1.getString(cur1.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA))

                    Log.d("Email","name: " + name)
                    Log.d("Email","phoneticName: " + phoneticName)
                    Log.d("Email","phoneNumber: " + phoneNumber)
                    Log.d("Email","email: " + email)

                    contactList.add(Contact(if (name.isNotEmpty()) name else "",if (phoneNumber.isNotEmpty()) phoneNumber else "",if (phoneticName.isNotEmpty()) phoneticName.trim() else "",if (email.isNotEmpty()) email else ""))
                }
                cur1.close()
            }
        }

        if (contactList.isEmpty()) {
            recyclerView!!.visibility = View.GONE
        } else {
            recyclerView!!.visibility = View.VISIBLE
            mAdapter!!.notifyDataSetChanged()
        }
    }

解决方法

Runtime permissions 是在 Android 6.0(Api 级别 23)中引入的,但从技术上讲,您仍然可以通过定位较低的 API 在不支持运行时权限的情况下在 Android 6 上运行应用程序,我认为这在 Android 10 中不再可能(甚至更低)。

您的应用是否要求 Runtime permission READ_CONTACTS 访问 ContactsContract API?

此外,我认为您的代码在任何 Android 版本中都无法正常工作,您无法查询 CommonDataKinds.Email.CONTENT_URI 并获取电话号码,我想您只能通过此代码获取姓名 + 电子邮件。

此外,您的代码效率非常低,它对每个联系人运行一个查询,这可能导致数百个查询需要一些时间。 您应该将其替换为这样的单个查询(同时支持电子邮件和电话):

val projection: Array<out String> = arrayOf(Data.CONTACT_ID,Data.DISPLAY_NAME,Data.PHONETIC_NAME,Data.MIMETYPE,Data.DATA1)
val selection: String = Data.MIMETYPE + " IN ('" + Phone.CONTENT_ITEM_TYPE + "','" + Email.CONTENT_ITEM_TYPE + "')"

val map = mutableMapOf<Long,Contact>() // map contact-id to Contact object

val cur: Cursor = contentResolver.query(Data.CONTENT_URI,projection,selection,null,null)!!
while (cur.moveToNext()) {
    val id = cur.getLong(0)
    val name = cur.getString(1)
    val phoneticName = cur.getString(2)
    val mimetype = cur.getString(3) // this tells us if this row is a phone or email row
    val data = cur.getString(4) // may hold either phone or email
    
    Log.d("Contact",id + " " + name + " " + mimetype + " " + data)

    val contact = map[id]
    if (contact == null) {
        contact = Contact(name,"",phoneticName,"") // create a new contact without email or phone
        map[id] = contact
    }

    if (mimetype == Phone.CONTENT_ITEM_TYPE) {
        contact.phone = data
    } else {
        contact.email = data
    }
}
,

回答我自己的问题。其实我的代码也工作正常。 Android 10 没有 phoneticName 的概念,这就是它崩溃的原因。任何人都可以通过删除 phoneticName 来使用我的代码,它将完美运行。谢谢!