在上一章 Android中联系人和通话记录详解(2)中分析了联系人相关的表和字段,在这一章中将分析联系人相关的基本数据操作(Insert,Query,Update,Delete)。
1.添加(Insert)
从contacts,data,mimetypes,raw_contacts表的关系可以看出,表raw_contacts为表data的父表,所以插入数据时,应该先在raw_contacts表中插入数据,再在data表中插入数据。
ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
ContentProviderOperation op1 = ContentProviderOperation
.newInsert(ContactsContract.RawContacts.CONTENT_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null)
.build();// 得到了一个添加内容的对象
operations.add(op1);
ContentProviderOperation op2 = 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.Data.DATA1, "小明").build();// 得到了一个添加内容的对象
operations.add(op2);
ContentProviderOperation op3 = 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.Data.DATA1, "1233232542")
.withValue(ContactsContract.Data.DATA2, "2")// data2=2即type=2,表示移动电话
.build();// 得到了一个添加内容的对象
operations.add(op3);
ContentProviderOperation op4 = 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.Data.DATA1, "test@email.com")
.withValue(ContactsContract.Data.DATA2, "2")// data2=2即type=2,表示工作邮箱
.build();// 得到了一个添加内容的对象
operations.add(op4);
getContext().getContentResolver().applyBatch("com.android.contacts",
operations);// 执行批量操作
ContentProviderOperation类是为了使批量更新、插入、删除数据更加方便而引入的,在官方文档中指出推荐使用ContentProviderOperation类的原因有:1.所有的操作都在一个事务中执行,这样可以保证数据完整性;2.由于批量操作在一个事务中执行,只需要打开和关闭一个事务,比多次打开关闭多个事务性能要好些;3.使用批量操作和多次单个操作相比,减少了应用和content provider之间的上下文切换,这样也会提升应用的性能,并且减少占用CPU的时间,当然也会减少电量的消耗。
2.查询(Query)
public void queryContacts(Context context) {
ContentResolver cr = context.getContentResolver();
Cursor contactCursor = cr.query(ContactsContract.Contacts.CONTENT_URI,
new String[] { ContactsContract.Contacts._ID }, null, null,
ContactsContract.Contacts.SORT_KEY_PRIMARY);//在raw_contacts表中得到contactId
if (contactCursor != null && contactCursor.getCount() > 0)
while (contactCursor.moveToNext()) {
long contactId = contactCursor.getLong(contactCursor
.getColumnIndex(ContactsContract.Contacts._ID));
Cursor dataCursor = cr.query(ContactsContract.Data.CONTENT_URI,
new String[] { ContactsContract.Data.MIMETYPE,
ContactsContract.Data.DATA1,
ContactsContract.Data.DATA2,
ContactsContract.Data.DATA15 },
ContactsContract.Data.RAW_CONTACT_ID + "=" + contactId,
null, null);
if (dataCursor != null && dataCursor.getCount() > 0) {
while (dataCursor.moveToNext()) {
String mimeType = dataCursor
.getString(dataCursor
.getColumnIndex(ContactsContract.Data.MIMETYPE));
if (ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE
.equals(mimeType)) {
//电话号码
dataCursor
.getString(dataCursor
.getColumnIndex(ContactsContract.Data.DATA1));
} else if (ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE
.equals(mimeType)) {
//邮件
dataCursor
.getString(dataCursor
.getColumnIndex(ContactsContract.Data.DATA1));
} else if (ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE
.equals(mimeType)) {
//即时消息
} else if (ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE
.equals(mimeType)) {
//名字
dataCursor
.getString(dataCursor
.getColumnIndex(ContactsContract.Data.DATA1));
} else if (ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE
.equals(mimeType)) {
//头像
byte[] data = dataCursor
.getBlob(dataCursor
.getColumnIndex(ContactsContract.Data.DATA15));
BitmapFactory.decodeByteArray(data, 0, data.length);
} else if (ContactsContract.CommonDataKinds.Nickname.CONTENT_ITEM_TYPE
.equals(mimeType)) {
//昵称
}
}
}
if (dataCursor != null) {
dataCursor.close();
dataCursor = null;
}
}
if (contactCursor != null) {
contactCursor.close();
contactCursor = null;
}
}
3.更新(Update)
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
ContentProviderOperation op1 = ContentProviderOperation
.newUpdate(ContactsContract.Data.CONTENT_URI)
.withSelection(
ContactsContract.Data.RAW_CONTACT_ID + "=? and "
+ ContactsContract.Data.MIMETYPE + "=?",
new String[] {
String.valueOf(contactId),
ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE })
.withValue(
ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,// 对应data表中的data1字段
"小明").build();
ops.add(op1);
ContentProviderOperation op2 = ContentProviderOperation
.newUpdate(ContactsContract.Data.CONTENT_URI)
.withSelection(
ContactsContract.Data.RAW_CONTACT_ID + "=? and "
+ ContactsContract.Data.MIMETYPE + "=?",
new String[] { String.valueOf(contactId),
ContactsContract.CommonDataKinds.Phone.MIMETYPE })
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER,// 对应data表中的data1字段
"12367712322").build();
ops.add(op2);
ContentProviderOperation op3 = ContentProviderOperation
.newUpdate(ContactsContract.Data.CONTENT_URI)
.withSelection(
ContactsContract.Data.RAW_CONTACT_ID + "=? and "
+ ContactsContract.Data.MIMETYPE + "=?",
new String[] { String.valueOf(contactId),
ContactsContract.CommonDataKinds.Phone.MIMETYPE })
.withValue(ContactsContract.CommonDataKinds.Email.ADDRESS,// 对应data表中的data1字段
"test@email.com").build();
ops.add(op3);
try {
context.getContentResolver().applyBatch(ContactsContract.AUTHORITY,
ops);
} catch (Exception e) {
e.printStackTrace();
}
4.删除(Delete)
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
// 先删除子表Contacts中的数据
ops.add(ContentProviderOperation
.newDelete(ContactsContract.Contacts.CONTENT_URI)
.withSelection(
ContactsContract.Contacts._ID + "=?",
new String[] { String.valueOf(mContactId) })
.build());
// 然后删除子表Data中的数据
ops.add(ContentProviderOperation
.newDelete(ContactsContract.Data.CONTENT_URI)
.withSelection(
ContactsContract.Data.RAW_CONTACT_ID + "=?",
new String[] { String.valueOf(mContactId) })
.build());
// 最后删除父表RawContacts中的数据
ops.add(ContentProviderOperation
.newDelete(ContactsContract.RawContacts.CONTENT_URI)
.withSelection(
ContactsContract.RawContacts.CONTACT_ID
+ "=?",
new String[] { String.valueOf(mContactId) })
.build());
try {
getContentResolver().applyBatch(
ContactsContract.AUTHORITY, ops);
} catch (Exception e) {
e.printStackTrace();
}
5.根据联系人电话号码查询名字,头像等等。
//根据联系人电话号码查询名字
public static String queryNameFromContactsByNumber(Context context,
String number) {
String name = null;
if (context != null && number != null && !"".equals(number.trim())) {
Uri uri = Uri.withAppendedPath(
ContactsContract.CommonDataKinds.Phone.CONTENT_FILTER_URI,
number);
Cursor nameCursor = context.getContentResolver().query(uri,
new String[] { "display_name" }, null, null, null);
if (nameCursor != null) {
if (nameCursor.getCount() > 0) {
nameCursor.moveToFirst();
name = nameCursor.getString(0);
}
}
}
return name;
}
//根据联系人电话查询头像
public Bitmap queryPhotoFromContactsByNumber(Context context, String number) {
Bitmap bitmap = null;
if (context != null && number != null && !"".equals(number.trim())) {
Uri numberUri = Uri.withAppendedPath(
ContactsContract.CommonDataKinds.Phone.CONTENT_FILTER_URI,
number);
ContentResolver cr = context.getContentResolver();
Cursor numberCursor = cr.query(numberUri,
new String[] { "contact_id" }, null, null, null);
if (numberCursor != null) {
if (numberCursor.getCount() > 0) {
numberCursor.moveToFirst();
long mContactId = numberCursor.getLong(0);
Uri contactUri = ContentUris.withAppendedId(
ContactsContract.Contacts.CONTENT_URI, mContactId);
InputStream is = ContactsContract.Contacts
.openContactPhotoInputStream(cr, contactUri);
if (is != null) {
bitmap = BitmapFactory.decodeStream(is);
numberCursor.close();
}
}
}
}
return bitmap;
6.通过raw_contacts的字段version,监听联系人的变化
/**
* <br>
* <b> Description: </b> 在raw_contacts表中获得联系人的version,如果联系人有更改,则version会变化
*
* @return int 联系人的version
*/
public static int getContactVersion(Context context, long contactId) {
Cursor cursor = context.getContentResolver().query(
ContactsContract.RawContacts.CONTENT_URI,
new String[] { ContactsContract.RawContacts.CONTACT_ID,
ContactsContract.RawContacts.VERSION },
ContactsContract.RawContacts.CONTACT_ID + "=?",
new String[] { String.valueOf(contactId) }, null);
int version = 0;
if (cursor != null && cursor.getCount() > 0) {
cursor.moveToFirst();
version = cursor.getInt(cursor
.getColumnIndex(ContactsContract.RawContacts.VERSION));
}
if (cursor != null) {
cursor.close();
cursor = null;
}
return version;
}
到这儿联系人的Insert,Query,Update,Delete四大基本数据操作已经完成。