android - 为什么我的联系人查询会提供具有不同 ID 的联系人?
问题描述
我有一个 Activity 允许用户选择联系人。完成后,所选联系人的 id 将在回复 Intent 中传递。在处理结果的地方,将读取所选联系人的详细信息。问题在于,在处理结果时,读取的详细信息是针对与所选联系人不同的联系人。我不知道为什么。在我的情况下,用户只选择一个联系人。
我已经阅读了很多关于阅读联系人的文档和其他问题,但没有看到任何对我的案子有帮助的东西。
从 Activity 从联系人中获取用户选择:
@Override
protected void onCreate (Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_select_from_contacts);
m_view = findViewById(R.id.lv_contactsSelect);
m_view.setVisibility(View.VISIBLE);
getListView().setItemsCanFocus(false);
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
new String[]{ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME},
null, null, "UPPER(" + ContactsContract.Contacts.DISPLAY_NAME + ") ASC");
setListAdapter(new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_multiple_choice,
cursor,
new String[]{ContactsContract.Contacts.DISPLAY_NAME},
new int[]{android.R.id.text1},
0));
Button btn = findViewById(R.id.btn_get_contacts);
btn.setOnClickListener((View view) -> {
Intent replyIntent = new Intent();
ArrayList<Long> ids = pickContacts();
replyIntent.putExtra(Activities.ARG_SELECTED, ids);
setResult(Activities.RESULT_CONTACTS_SELECTED, replyIntent);
finish();
});
}
/** Viewer for list of contacts */
private ListView m_view;
private ListView getListView ()
{ return m_view; }
private CursorAdapter mAdapter;
private void setListAdapter (@NonNull CursorAdapter adapter)
{
mAdapter = adapter;
m_view.setAdapter(adapter);
}
// return id for each selected contact
private ArrayList<Long> pickContacts ()
{
SparseBooleanArray a = getListView().getCheckedItemPositions();
ArrayList<Long> contacts = new ArrayList<>();
for (int i = 0; i < a.size(); i++)
{
if (a.valueAt(i))
{
Cursor c = (Cursor)mAdapter.getItem(a.keyAt(i));
// TODO use RawContacts or Contacts? Currently the result is the same.
//Long idContact = c.getLong(c.getColumnIndex(ContactsContract.Contacts._ID));
Long idRaw = c.getLong(c.getColumnIndex(ContactsContract.RawContacts._ID));
contacts.add(idRaw);
}
}
return contacts;
}
处理结果:
@Override
protected void onActivityResult (int requestCode, int resultCode, Intent data)
{
if (resultCode == Activities.RESULT_CONTACTS_SELECTED)
{
ArrayList<Long> ids = (ArrayList<Long>)data.getSerializableExtra(Activities.ARG_SELECTED);
for (long id : ids)
{
getContactDetails(id);
}
}
}
/**
* As mentioned in https://developer.android.com/reference/android/provider/ContactsContract.RawContacts
* the best way to read a raw contact along with associated data is by using the Entity directory.
*/
// FIXME: The id from the received result matches what was selected,
// but this function reads details for a different contact.
private void getContactDetails (long rawContactId)
{
System.out.println("Get contact with id " + rawContactId);
Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
Uri entityUri = Uri.withAppendedPath(rawContactUri, Entity.CONTENT_DIRECTORY);
// For example, this output can be "Get contact from entity uri content://com.android.contacts/raw_contacts/615/entity"
// (Where 615 is the id for the selected contact.)
System.out.println("Get contact from entity uri " + entityUri);
Cursor c = getContentResolver().query(entityUri,
new String[]{RawContacts.SOURCE_ID, Entity.DATA_ID, Entity.MIMETYPE, Entity.DATA1}, // projection
null, null, null);
if (c == null)
return;
try
{
while (c.moveToNext())
{
// In this example I'm just dumping data to the console.
if (!c.isNull(1))
{
String mimeType = c.getString(2);
String data = c.getString(3);
System.out.println("mimeType = " + mimeType);
System.out.println("data = " + data);
}
}
}
finally
{
c.close();
}
}
例如,处理程序的控制台输出包括:
mimeType = vnd.android.cursor.item/name
data = A name
名称与联系人选择活动中选择的名称不同。
解决方案
在 method 中pickContacts
,将其更改为 get Contacts._ID
,它偶然找到了一个 ID,因为两者RawContacts._ID
和Contacts._ID
都是字符串“_id”,但这完全是错误的。
接下来,由于您实际上是在获取联系人 ID,因此您需要将您的修改getContactDetails
为接受 aContactId
而不是 a RawContactId
。
不知道为什么需要涉及Entity
这样的 API,如果您只需要查询该联系人的数据,请执行以下操作:
private void getContactDetails (long contactId) {
Log.i("Contacts", "Get contact with id " + contactId);
String[] projection = new String[]{Data.DISPLAY_NAME, Data.MIMETYPE, Data.DATA1};
String selection = Data.CONTACT_ID + "=" + contactId;
Cursor c = getContentResolver().query(Data.CONTENT_URI, projection, selection, null, null);
if (c == null) {
return;
}
try {
while (c.moveToNext()) {
String name = c.getString(0);
String mimeType = c.getString(1);
String data = c.getString(2);
Log.i("Contacts", contactId + ", " + name + ", " + mimetype + ", " + data);
}
} finally {
c.close();
}
}
推荐阅读
- r - 从相邻单元格栅格 R 中获取值
- c++ - 进入函数前如何设置前一个数组值?
- java - Java 迭代器:这是什么意思:java.util.ArrayList$Itr
- jboss - 无效的
eap 6.4 中的过滤器映射中的 jsp/* - c# - 从 Windows 10 瞄准 .NET 4.0?
- excel - 如何激活目标
- mysql - 如何在搜索查询 Jpa 中同时使用 Starts with 和 contains?
- python - 如何在我的本地环境中使用 sympy 输出乳胶?
- jquery - 如何将防伪令牌和序列化对象作为参数传递给 MVC 操作
- java - Using SharedPreferences to save variable makes my app crash