Android系统中的联系人也是通过ContentProvider来对外提供数据的,我们这里实现获取所有联系人、通过电话号码获取联系人、添加联系人、使用事务添加联系人
一.获取所有联系人
1. Android系统中的联系人也是通过ContentProvider来对外提供数据的
2. 数据库路径为:/data/data/com.android.providers.contacts/database/contacts2.db
3. 我们需要关注的有3张表
raw_contacts:其中保存了联系人id
data:和raw_contacts是多对一的关系,保存了联系人的各项数据
mimetypes:为数据类型
4. Provider的authorites为com.android.contacts
5. 查询raw_contacts表的路径为:contacts
6. 查询data表的路径为:contacts/#/data
这个路径为连接查询,要查询“mimetype”字段可以根据“mimetype_id”查询到mimetypes表中的数据
7. 先查询raw_contacts得到每个联系人的id,在使用id从data表中查询对应数据,根据mimetype分类数据
public void testGetAll() {
ContentResolver resolver = getContext().getContentResolver();
Uri uri = Uri.parse("content://com.android.contacts/contacts");
Cursor idCursor = resolver.query(uri, new String[] { "_id" }, null, null, null);
while (idCursor.moveToNext()) {
//获取到raw_contacts表中的id
int id = idCursor.getInt(0);
//根据获取到的ID查询data表中的数据
uri = Uri.parse("content://com.android.contacts/contacts/" + id + "/data");
Cursor dataCursor = resolver.query(uri, new String[] { "data1", "mimetype" }, null, null, null);
StringBuilder sb = new StringBuilder();
sb.append("id=" + id);
//查询联系人表中的
while (dataCursor.moveToNext()) {
String data = dataCursor.getString(0);
String type = dataCursor.getString(1);
if ("vnd.android.cursor.item/name".equals(type))
sb.append(", name=" + data);
else if ("vnd.android.cursor.item/phone_v2".equals(type))
sb.append(", phone=" + data);
else if ("vnd.android.cursor.item/email_v2".equals(type))
sb.append(", email=" + data);
}
System.out.println(sb);
}
}
二.存储联系人
public class AddContactAPI5 {
public void addContact(Context context, String name, String organisation,
String phone, String fax, String email, String address,
String website, Bitmap logo) {
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null)
.withValue(ContactsContract.RawContacts.AGGREGATION_MODE, ContactsContract.RawContacts.AGGREGATION_MODE_DISABLED)
.build());
// add name
if (!AppUtils.isBlank(name)) {
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name)
.build());
}
// add company
if (!AppUtils.isBlank(organisation)) {
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Organization.COMPANY,
organisation)
.withValue(ContactsContract.CommonDataKinds.Organization.TYPE,
ContactsContract.CommonDataKinds.Organization.TYPE_WORK)
.build());
}
// add phone
if (!AppUtils.isBlank(phone)) {
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone)
.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, 1)
.build());
}
// add Fax
if (!AppUtils.isBlank(fax)) {
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, fax)
.withValue(ContactsContract.CommonDataKinds.Phone.TYPE,
ContactsContract.CommonDataKinds.Phone.TYPE_FAX_WORK)
.build());
}
// add email
if (!AppUtils.isBlank(email)) {
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Email.DATA, email)
.withValue(ContactsContract.CommonDataKinds.Email.TYPE, 1)
.build());
}
// add address
if (!AppUtils.isBlank(address)) {
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredPostal.STREET, address)
.withValue(ContactsContract.CommonDataKinds.StructuredPostal.TYPE,
ContactsContract.CommonDataKinds.StructuredPostal.TYPE_WORK)
.build());
}
// add website
if (!AppUtils.isBlank(website)) {
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Website.URL, website)
.withValue(ContactsContract.CommonDataKinds.Website.TYPE,
ContactsContract.CommonDataKinds.Website.TYPE_WORK)
.build());
}
// add logo image
Bitmap bm = logo;
if (bm != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] photo = baos.toByteArray();
if (photo != null) {
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, photo)
.build());
}
}
try {
context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
} catch (Exception e) {
}
}
}
android 2.0以上至关重要的一点:
.withValue(ContactsContract.RawContacts.AGGREGATION_MODE, ContactsContract.RawContacts.AGGREGATION_MODE_DISABLED)
加上这句才会把同名联系人分开存储,否则一条联系人调用2次存储后,在对联系人进行edit的时候后报错。这条属性在官方API上都没有说明,很重要。
参考文档: