I'm trying to obtain a list of contacts from the native database with their Display Name and Phone Number (any or all). There are many methods for obtaining this information with several queries to the phone's database, but this introduces considerable overhead.
我试图从本机数据库中获取一个联系人列表,其中包含他们的显示名和电话号码(任何或全部)。有许多方法可以通过对手机数据库的多个查询来获取这些信息,但是这会带来相当大的开销。
Here is the query I've been working on, but it results in
这是我一直在处理的查询,但它产生了结果
Uri uri = ContactsContract.Contacts.CONTENT_URI;
String[] projection = new String[] { ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER};
String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER + " = '1'";
String[] selectionArgs = null;
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
Cursor people = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);
int index_id = people.getColumnIndex(ContactsContract.Contacts._ID);
int indexName = people.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
int indexNumber = people.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
people.moveToFirst();
do {
String _id = people.getString(index_id);
String name = people.getString(indexName);
String number = people.getString(indexNumber);
// Do work...
} while (people.moveToNext());
And here's the resulting error.
这是结果误差。
E/AndroidRuntime(21549): Caused by: java.lang.IllegalArgumentException: Invalid column data1
E/AndroidRuntime(21549): at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:144)
E/AndroidRuntime(21549): at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:114)
E/AndroidRuntime(21549): at android.content.ContentProviderProxy.bulkQueryInternal(ContentProviderNative.java:372)
E/AndroidRuntime(21549): at android.content.ContentProviderProxy.query(ContentProviderNative.java:408)
E/AndroidRuntime(21549): at android.content.ContentResolver.query(ContentResolver.java:264)
Thoughts? I believe a join may be needed to get all the columns in a single query.
想法吗?我认为在一个查询中获取所有列可能需要一个连接。
3 个解决方案
#1
103
Try this code:
试试这段代码:
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String[] projection = new String[] {ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER};
Cursor people = getContentResolver().query(uri, projection, null, null, null);
int indexName = people.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
int indexNumber = people.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
if(people.moveToFirst()) {
do {
String name = people.getString(indexName);
String number = people.getString(indexNumber);
// Do work...
} while (people.moveToNext());
}
#2
14
The contacts API is extremly tricky and has several implicit joins.
contacts API非常棘手,有几个隐式连接。
Read the ContactContract and ContactsProvider2 if you can afford the time.
如果你有时间的话,阅读合同和合同提供方2。
What do you want? The tables are chained like this:
你想要什么?桌子像这样被拴着:
- Contact 1--* Raw Contact
- 1——*生联系联系
- Raw Contact 1--* Phone Number (data table)
- 原始联系人1——*电话号码(数据表)
The API works like this: you select the bottom-most element (a phone number) and implicit join to the topmost element (contact).
API的工作方式如下:选择最底的元素(电话号码)和最顶层元素(contact)的隐式连接。
You want to use the PHONE URI case (ContactsProvider2 / line 4377). This should select all phone numbers and join up to the contact.
您希望使用电话URI案例(ContactsProvider2 / line 4377)。这应该选择所有的电话号码并连接到联系人。
Combine the PHONE uri with some UI magic (for grouping), request the DISPLAY_NAME and the PHONE number (DATA1?) and you should be able to solve the problem.
将电话uri与一些UI魔术(用于分组)结合,请求DISPLAY_NAME和电话号码(DATA1?),您应该能够解决这个问题。
#3
1
Phone numbers are stored in their own table and need to be queried separately. To query the phone number table use the URI stored in the SDK variable ContactsContract.CommonDataKinds.Phone.CONTENT_URI. Use a WHERE conditional to get the phone numbers for the specified contact.
电话号码存储在它们自己的表中,需要分别查询。要查询电话号码表,请使用SDK变量ContactsContract.CommonDataKinds.Phone.CONTENT_URI中存储的URI。使用WHERE条件获取指定联系人的电话号码。
private String displayName(Uri contactUri) {
HashSet detail = ContactDetail.getInstance().getContactArray();
Log.d("ITEM", contactUri.toString());
String[] projection = new String[]{ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER};
Cursor queryCursor = getActivity().getContentResolver()
.query(contactUri, null, null, null, null);
queryCursor.moveToFirst();
String name = queryCursor.getString(queryCursor.getColumnIndex("display_name"));
String id = queryCursor.getString(
queryCursor.getColumnIndex(ContactsContract.Contacts._ID));
if (Integer.parseInt(queryCursor.getString(queryCursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
Cursor pCur = getActivity().getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
new String[]{id}, null);
while (pCur.moveToNext()) {
String number = pCur.getString(pCur.getColumnIndex("data1"));
Log.d("Contact Name: ", number);
}
pCur.close();
}
return name;
}
Perform a second query against the Android contacts SQLite database. The phone numbers are queried against the URI stored in ContactsContract.CommonDataKinds.Phone.CONTENT_URI. The contact ID is stored in the phone table as ContactsContract.CommonDataKinds.Phone.CONTACT_ID and the WHERE clause is used to limit the data returned.
对Android contacts SQLite数据库执行第二个查询。根据存储在ContactsContract.CommonDataKinds.Phone.CONTENT_URI中的URI查询电话号码。联系人ID作为ContactsContract.CommonDataKinds.Phone存储在电话表中。CONTACT_ID和WHERE子句用于限制返回的数据。
#1
103
Try this code:
试试这段代码:
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String[] projection = new String[] {ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER};
Cursor people = getContentResolver().query(uri, projection, null, null, null);
int indexName = people.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
int indexNumber = people.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
if(people.moveToFirst()) {
do {
String name = people.getString(indexName);
String number = people.getString(indexNumber);
// Do work...
} while (people.moveToNext());
}
#2
14
The contacts API is extremly tricky and has several implicit joins.
contacts API非常棘手,有几个隐式连接。
Read the ContactContract and ContactsProvider2 if you can afford the time.
如果你有时间的话,阅读合同和合同提供方2。
What do you want? The tables are chained like this:
你想要什么?桌子像这样被拴着:
- Contact 1--* Raw Contact
- 1——*生联系联系
- Raw Contact 1--* Phone Number (data table)
- 原始联系人1——*电话号码(数据表)
The API works like this: you select the bottom-most element (a phone number) and implicit join to the topmost element (contact).
API的工作方式如下:选择最底的元素(电话号码)和最顶层元素(contact)的隐式连接。
You want to use the PHONE URI case (ContactsProvider2 / line 4377). This should select all phone numbers and join up to the contact.
您希望使用电话URI案例(ContactsProvider2 / line 4377)。这应该选择所有的电话号码并连接到联系人。
Combine the PHONE uri with some UI magic (for grouping), request the DISPLAY_NAME and the PHONE number (DATA1?) and you should be able to solve the problem.
将电话uri与一些UI魔术(用于分组)结合,请求DISPLAY_NAME和电话号码(DATA1?),您应该能够解决这个问题。
#3
1
Phone numbers are stored in their own table and need to be queried separately. To query the phone number table use the URI stored in the SDK variable ContactsContract.CommonDataKinds.Phone.CONTENT_URI. Use a WHERE conditional to get the phone numbers for the specified contact.
电话号码存储在它们自己的表中,需要分别查询。要查询电话号码表,请使用SDK变量ContactsContract.CommonDataKinds.Phone.CONTENT_URI中存储的URI。使用WHERE条件获取指定联系人的电话号码。
private String displayName(Uri contactUri) {
HashSet detail = ContactDetail.getInstance().getContactArray();
Log.d("ITEM", contactUri.toString());
String[] projection = new String[]{ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER};
Cursor queryCursor = getActivity().getContentResolver()
.query(contactUri, null, null, null, null);
queryCursor.moveToFirst();
String name = queryCursor.getString(queryCursor.getColumnIndex("display_name"));
String id = queryCursor.getString(
queryCursor.getColumnIndex(ContactsContract.Contacts._ID));
if (Integer.parseInt(queryCursor.getString(queryCursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
Cursor pCur = getActivity().getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
new String[]{id}, null);
while (pCur.moveToNext()) {
String number = pCur.getString(pCur.getColumnIndex("data1"));
Log.d("Contact Name: ", number);
}
pCur.close();
}
return name;
}
Perform a second query against the Android contacts SQLite database. The phone numbers are queried against the URI stored in ContactsContract.CommonDataKinds.Phone.CONTENT_URI. The contact ID is stored in the phone table as ContactsContract.CommonDataKinds.Phone.CONTACT_ID and the WHERE clause is used to limit the data returned.
对Android contacts SQLite数据库执行第二个查询。根据存储在ContactsContract.CommonDataKinds.Phone.CONTENT_URI中的URI查询电话号码。联系人ID作为ContactsContract.CommonDataKinds.Phone存储在电话表中。CONTACT_ID和WHERE子句用于限制返回的数据。