为啥 PhoneLookup 和 ContactsContract.Contacts 选择器之间的联系人 ID 不匹配?
Posted
技术标签:
【中文标题】为啥 PhoneLookup 和 ContactsContract.Contacts 选择器之间的联系人 ID 不匹配?【英文标题】:Why do contact IDs not match between PhoneLookup and the ContactsContract.Contacts picker?为什么 PhoneLookup 和 ContactsContract.Contacts 选择器之间的联系人 ID 不匹配? 【发布时间】:2018-12-03 08:23:49 【问题描述】:我的应用正在扫描 SMS 消息并计算指标,然后将其存储在数据库中,该数据库由与 SMS 上的电话号码关联的联系人 ID 键入。使用PhoneLookup
机制查找第一个联系人ID。稍后,我还让用户使用联系人选择器意图选择联系人。但是即使选择了同一个人,从选择器返回的联系人 ID 与通过PhoneLookup
获取的联系人 ID 不同。这是为什么呢?
这是一个展示这种效果的活动。将PHONE_NUMBER
设置为您手机上已知联系人的电话号码。然后点击“选择联系人”按钮并选择相同的联系人。对我来说,这两种方法的联系人 ID 是不同的。
import android.app.Activity
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.provider.ContactsContract
import android.support.v7.app.AppCompatActivity
import android.util.Log
import com.example.R
import kotlinx.android.synthetic.main.activity_contact_idtest.*
class ContactIDTest : AppCompatActivity()
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_contact_idtest)
companion object
const val TAG = "ContactIDTest"
const val RQST_PICK_CONTACT = 1
const val PHONE_NUMBER = "5551234567"
override fun onResume()
super.onResume()
cmdPickContact.setOnClickListener
val pickContactIntent = Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI)
pickContactIntent.type = ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE // Show user only contacts w/ phone numbers
startActivityForResult(pickContactIntent, RQST_PICK_CONTACT)
contactForPhoneNumber(PHONE_NUMBER, contactID, displayName, photoThumbnailUri ->
txtContactID.text = contactID.toString()
txtContactName.text = displayName
,
Log.e(TAG, "Error getting contact for phone number")
)
private fun contactForPhoneNumber(phoneNumber: String, callback: (contactID: Long, displayName: String?, photoThumbnailUri: String?) -> Unit, error: () -> Unit)
val contactURI = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber))
try
val cursor = contentResolver.query(contactURI,
arrayOf(ContactsContract.PhoneLookup.CONTACT_ID, ContactsContract.PhoneLookup.DISPLAY_NAME, ContactsContract.PhoneLookup.PHOTO_THUMBNAIL_URI),
null,
null,
null
)
if(cursor == null || cursor.count <= 0)
error()
else
cursor.moveToFirst()
val contactID = cursor.getLong(cursor.getColumnIndexOrThrow(ContactsContract.PhoneLookup.CONTACT_ID))
val displayName = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.PhoneLookup.DISPLAY_NAME))
val photoThumbnailUri = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.PhoneLookup.PHOTO_THUMBNAIL_URI))
cursor.close()
callback(contactID, displayName, photoThumbnailUri)
catch(e: Exception)
Log.e(TAG, "Error loading contact for phone number: $phoneNumber", e)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?)
if(requestCode == RQST_PICK_CONTACT)
if(resultCode == Activity.RESULT_OK)
val contactData = data!!.data
val c = contentResolver.query(contactData, null, null, null, null)
if(c.moveToFirst())
val contactID = c.getLong(c.getColumnIndex(ContactsContract.Contacts._ID))
val displayName = c.getString(c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME))
txtPickedContactID.text = contactID.toString()
txtPickedContactName.text = displayName.toString()
c.close()
还有布局文件:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layoutContactIDTest"
android:layout_
android:layout_
tools:context=".activities.ContactIDTest"
tools:layout_editor_absoluteY="81dp">
<TextView
android:id="@+id/txtContactName"
android:layout_
android:layout_
android:text="$CONTACT_NAME"
app:layout_constraintBottom_toTopOf="@+id/cmdPickContact"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtContactID" />
<TextView
android:id="@+id/txtContactID"
android:layout_
android:layout_
android:text="$CONTACT_ID"
app:layout_constraintBottom_toTopOf="@+id/txtContactName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/cmdPickContact"
android:layout_
android:layout_
android:text="Pick Contact"
app:layout_constraintBottom_toTopOf="@+id/txtPickedContactID"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtContactName" />
<TextView
android:id="@+id/txtPickedContactID"
android:layout_
android:layout_
android:text="$PICKED_CONTACT_ID"
app:layout_constraintBottom_toTopOf="@+id/txtPickedContactName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/cmdPickContact" />
<TextView
android:id="@+id/txtPickedContactName"
android:layout_
android:layout_
android:text="$PICKED_CONTACT_NAME"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtPickedContactID" />
</android.support.constraint.ConstraintLayout>
【问题讨论】:
【参考方案1】:这段代码:
val pickContactIntent = Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI)
pickContactIntent.type = ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE
将返回 CommonDataKinds.Phone._ID
而不是 Contacts._ID
【讨论】:
啊,这就是我无法 100% 理解的复制粘贴代码的结果。不知何故,我认为那是在做一些不同的事情。感谢您指出我的错误。以上是关于为啥 PhoneLookup 和 ContactsContract.Contacts 选择器之间的联系人 ID 不匹配?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我需要 READ_CONTACTS 权限才能读取通话记录?
android中RawContacts.CONTENT_URI和ContactsContract.Contacts.CONTENT_URI的区别