您的位置:首页 > 其它

项目总结之关于系统通讯录的操作

2016-03-20 17:03 531 查看
最近做了个项目, 主要是基于系统通讯录操作的, 大概的功能说下把, 联系人列表, 通话记录列表, 联系人名片, 新增群组与智能分组, 联系人收藏列表, 短信群发, 导航电话与位置分享功能, 自定义拨号键盘, 通讯录备份, 换肤功能.

其实做完这个项目后, 我觉得我对通讯录的关键的那几张表有了更深入的了解, 之前我并没有接触过类似的项目, 在做这个项目的时候也做得很蛋疼, 因为对表的不熟悉, 所以在查询, 操作时会出现很多问题.

通讯录数据库contacts2.db, 主要操作的表是contacts, raw_contacts, data, mimetypes.

contacts表:



在这张表中我们主要可以获取到contact_id, starred

可以通过CONTENT_URI来得到contacts表的游标.

步骤:

Cursor cursor = resolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);

String id         = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
Logger.e("Contacts._id---->>" + id); //联系人ID
String displayname = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));//姓名
String starred     = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.STARRED));//是否被添加到收藏夹


raw_ contacts表:





现在我们可以拿着contact_id来得到raw_contacts表的游标, 再进行crud操作.

步骤:

Cursor rawCursor = resolver.query(ContactsContract.RawContacts.CONTENT_URI, null, ContactsContract.RawContacts._ID + "=?", new String[]{id}, null);
//该查询结果一般只返回一条记录
if (rawCursor != null) {
if (rawCursor.moveToFirst()) {
//2.读取raw_contacts表中第一条记录的RawContacts._ID列的值
rawContactsId = rawCursor.getString(rawCursor.getColumnIndex(ContactsContract.RawContacts._ID));
Logger.e("RawContacts._ID--->>" + rawContactsId);
}
rawCursor.close();
}


data表:



也是通过contact_id可以得到data表的游标, 有了游标就可以crud操作

步骤:

Cursor dataCursor = resolver.query(ContactsContract.Data.CONTENT_URI, null, ContactsContract.Data.CONTACT_ID + "=?", new String[]{id}, null);
//读取号码
if (Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
//3.在data表中根据RAW_CONTACTS_ID来查询联系人的各数据.
// ContactsContract.CommonDataKinds.Phone.CONTENT_URI
// 相当于下面的Uri
// phoneUri=Uri.parse("content://com.android.contacts/data/phones");
Cursor phoneCursor = resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=?", new String[]{id}, null);
Cursor emailCursor = resolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null,
ContactsContract.CommonDataKinds.Email.CONTACT_ID + "=?", new String[]{id}, null);
Cursor postalCursor = resolver.query(ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_URI, null,
ContactsContract.CommonDataKinds.StructuredPostal.CONTACT_ID + "=?", new String[]{id}, null);

//一个联系人可能有多个号码, 需要遍历
if (phoneCursor != null && phoneCursor.getCount() > 0) {
for (int i = 0; i < phoneCursor.getCount(); i++) {  //电话信息
phoneCursor.moveToPosition(i);
int phone_id = phoneCursor.getInt(phoneCursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));
String number   = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
int    type     = phoneCursor.getInt(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
String photoUri = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.PHOTO_URI)); //头像Uri
String photoFileId = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.PHOTO_FILE_ID)); //头像
String photoId = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.PHOTO_ID)); //头像

JSONObject tellObj = new JSONObject();

/*********************************  读取头像信息  *********************************/
if (TextUtils.isEmpty(photoUri)) {
photoUri = "";
}
//com.android.contacts/display_photo/7
//                                        Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, phone_id);
contactObj.put("Img_Url", photoUri);

/*********************************  读取电话信息  *********************************/
if (TextUtils.isEmpty(number)) {
number = "";
type = 1;
}
tellObj.put("TellType", type);
tellObj.put("Mobile", number);

tellArray.put(tellObj);
}
phoneCursor.close();
}

if (dataCursor != null) {
for (int i = 0; i < dataCursor.getCount(); i++) {  //名字信息
dataCursor.moveToPosition(i);
String mimeType = dataCursor.getString(dataCursor.getColumnIndex("mimetype"));
String data1    = dataCursor.getString(dataCursor.getColumnIndex("data1"));
String data2    = dataCursor.getString(dataCursor.getColumnIndex("data2")); //名字 或者 可以代表邮箱的类型
String data3    = dataCursor.getString(dataCursor.getColumnIndex("data3")); //姓氏
String data4    = dataCursor.getString(dataCursor.getColumnIndex("data4")); //名称前缀
String data5    = dataCursor.getString(dataCursor.getColumnIndex("data5")); //中间名

String company = "", busines = "";

if (MIMETYPE_ORGANIZATION.equals(mimeType)) { //公司信息
company = data1;
busines = data4;

/*********************************  读取公司信息  *********************************/
if (TextUtils.isEmpty(company)) {
company = "";
}
contactObj.put("ComInfomation", company);

/*********************************  读取职务信息  *********************************/
if (TextUtils.isEmpty(busines)) {
busines = "";
}
contactObj.put("Busines", busines);
}
}
dataCursor.close();
}
}


我们可以在这张表中获取到很多联系人资料: 公司, 职务, 邮箱, 地址, 即时消息, 备注, 身份证, 社交账号, 网站, 群组成员, 生日. 获取方法和上面的一样.

mimetype表:



我们在data表中可以通过mimetype类型来获取对应的资料.

在操作数据库的时候, 其实android已经提供了一个很方便的类AsyncQueryHandler

使用方式:

//执行方法
QueryHandler mQueryHandler = new QueryHandler(resolver);
/**
* @param token 一个令牌, 主要用来标识查询, 保证唯一性, 在数据库操作完后会调用相应的onQueryComplete()方法
* @param cookie 传给onQueryComplete()方法使用的一个对象, 没有传null即可
* @param uri 进行查询的统一资源标识符
* @param projection 查询的列
* @param selection 限制条件
* @param selectionArgs 限制条件
* @param orderBy 排序条件
* //
*/
queryHandler.startQuery(0, null, ContactsContract.Data.CONTENT_URI, null,
ContactsContract.Data.CONTACT_ID + "=?", new String[]{contact_id}, null);

class QueryHandler extends AsyncQueryHandler {
public QueryHandler(ContentResolver cr) {
super(cr);
}

/**
* 删除数据后的操作
* @param token
* @param cookie
* @param result
*/
@Override protected void onDeleteComplete(int token, Object cookie, int result) {
super.onDeleteComplete(token, cookie, result);
}

/**
* 插入数据后的操作
* @param token
* @param cookie
* @param uri
*/
@Override protected void onInsertComplete(int token, Object cookie, Uri uri) {
super.onInsertComplete(token, cookie, uri);
}

/**
* 查询数据后的操作
* @param token
* @param cookie
* @param cursor
*/
@Override protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
super.onQueryComplete(token, cookie, cursor);
}

/**
* 更新数据后的操作
* @param token
* @param cookie
* @param result
*/
@Override protected void onUpdateComplete(int token, Object cookie, int result) {
super.onUpdateComplete(token, cookie, result);
}
}


获取通话记录:

private static class LoadCalls extends AsyncQueryHandler {

ContentResolver mResolver;

private LoadComplatedListener mLoadComplatedListener;

public LoadCalls(ContentResolver cr, LoadComplatedListener loadComplatedListener) {
super(cr);
mResolver = cr;
mLoadComplatedListener = loadComplatedListener;
}

public void query() {
//        查询最近3个月的通话记录
//            Calendar calendar = Calendar.getInstance();
//            calendar.add(Calendar.MONTH, -3);
Uri uri = CallLog.Calls.CONTENT_URI;
String projection[] = null;
//            String select = CallLog.Calls.DATE + ">'" + calendar.getTimeInMillis() + "'";
String select = null;
String selectionArgs[] = null;
//            String order = CallLog.Calls.DEFAULT_SORT_ORDER + " LIMIT " + recordCount;
String order = CallLog.Calls.DEFAULT_SORT_ORDER;

startQuery(0, null, uri, projection, select, selectionArgs, order);

}

@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
super.onQueryComplete(token, cookie, cursor);
new Thread(() -> {
if (cursor != null) {
Collection<CallModel> callModels = parserData(cursor);
cursor.close();
if (mLoadComplatedListener != null) {
Log.e("CallModel", "CallModel=" + callModels);
post(() -> mLoadComplatedListener.onComplated(callModels));
}
loadContactsLocus(callModels);
DataHelper.getInstance().getDaoSession().getCallModelDao().insertInTx(callModels);
}
}).start();

}

private Collection<CallModel> parserData(Cursor cursor) {
HashMap<String, CallModel> map = new LinkedHashMap<>();
while (cursor.moveToNext()) {
String number = cursor.getString(cursor.getColumnIndexOrThrow(CallLog.Calls.NUMBER));
String name = cursor.getString(cursor.getColumnIndexOrThrow(CallLog.Calls.CACHED_NAME));
long dateLong = cursor.getLong(cursor.getColumnIndexOrThrow(CallLog.Calls.DATE));
//            Date date = new Date(cursor.getLong(cursor.getColumnIndexOrThrow(CallLog.Calls.DATE)));
int duration = cursor.getInt(cursor.getColumnIndexOrThrow(CallLog.Calls.DURATION));

//TODO 姓名为空为陌生号码,如果用户后来添加为联系人,需要通过手机号码去查询联系人姓名
//                if (TextUtils.isEmpty(name)) {
////                    //姓名为空为陌生号码,如果用户后来添加为联系人后,需要通过手机号码去查询联系人姓名
//                    name = ContactsHelper.queryDisplayNameByNumber(mResolver, number);
//                }

if (!map.containsKey(number)) {
CallModel info = new CallModel();
info.setPhone(number);
info.setName(name);
info.setDate(Long.valueOf(dateLong));
info.setDuration(Integer.valueOf(duration));
map.put(number, info);
}
}
return map.values();
}

/**
* 加载联系人归属地
*
* @param collections
*/
private void loadContactsLocus(Collection<CallModel> collections) {
DBHelper.queryContactLocus2(collections);
}

public interface LoadComplatedListener {
void onComplated(Collection<CallModel> callModels);
}
}
跳转至新增联系人界面:

Intent intent = new Intent(Intent.ACTION_EDIT,Uri.parse("content://com.android.contacts/contacts/"+id));
context.startActivity(intent);
将号码添加至现有联系人界面:

Intent intent=new Intent(Intent.ACTION_EDIT, Uri.parse("content://com.android.contacts/contacts/"+id));
intent.putExtra(Contacts.Intents.Insert.PHONE_TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_HOME);
intent.putExtra(Contacts.Intents.Insert.PHONE, mPhone);
startActivity(intent);
调用系统联系人详情界面:

Uri lookupKeyUri = Uri.withAppendedPath(Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, ContactsContract.Contacts.LOOKUP_KEY), lookupKey);
//        String types[] = {"vnd.android.cursor.item/person", "vnd.android.cursor.item/contact", "vnd.android.cursor.item/raw_contact"};
//        ContactsContract.QuickContact.showQuickContact(getActivity(), new Rect(0, 0, 500, 500), lookupKeyUri, ContactsContract.QuickContact.MODE_SMALL, types);

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setPackage("com.android.contacts");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setData(lookupKeyUri);
context.startActivity(intent);
查询联系人头像:

Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
InputStream is = ContactsContract.Contacts.openContactPhotoInputStream(resolver, uri);
if (is == null) {
return null;
}
Bitmap bitmap = BitmapFactory.decodeStream(is);
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: