项目总结之关于系统通讯录的操作
2016-03-20 17:03
531 查看
最近做了个项目, 主要是基于系统通讯录操作的, 大概的功能说下把, 联系人列表, 通话记录列表, 联系人名片, 新增群组与智能分组, 联系人收藏列表, 短信群发, 导航电话与位置分享功能, 自定义拨号键盘, 通讯录备份, 换肤功能.
其实做完这个项目后, 我觉得我对通讯录的关键的那几张表有了更深入的了解, 之前我并没有接触过类似的项目, 在做这个项目的时候也做得很蛋疼, 因为对表的不熟悉, 所以在查询, 操作时会出现很多问题.
通讯录数据库contacts2.db, 主要操作的表是contacts, raw_contacts, data, mimetypes.
contacts表:
在这张表中我们主要可以获取到contact_id, starred
可以通过CONTENT_URI来得到contacts表的游标.
步骤:
raw_ contacts表:
现在我们可以拿着contact_id来得到raw_contacts表的游标, 再进行crud操作.
步骤:
data表:
也是通过contact_id可以得到data表的游标, 有了游标就可以crud操作
步骤:
我们可以在这张表中获取到很多联系人资料: 公司, 职务, 邮箱, 地址, 即时消息, 备注, 身份证, 社交账号, 网站, 群组成员, 生日. 获取方法和上面的一样.
mimetype表:
我们在data表中可以通过mimetype类型来获取对应的资料.
在操作数据库的时候, 其实android已经提供了一个很方便的类AsyncQueryHandler
使用方式:
获取通话记录:
其实做完这个项目后, 我觉得我对通讯录的关键的那几张表有了更深入的了解, 之前我并没有接触过类似的项目, 在做这个项目的时候也做得很蛋疼, 因为对表的不熟悉, 所以在查询, 操作时会出现很多问题.
通讯录数据库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(); }
相关文章推荐
- 20142335郝昊第三周学习总结
- 猴子吃桃问题
- 电路常识性概念(3)-TTL与CMOS集成电路
- PHP zend 常用快捷键汇总
- GO语言入门到精通(一)Golang环境搭建
- 136. Single Number
- AsyncTask不会执行doInBackground 的原因
- 集中式总线
- Android利用HttpClient发送Json到后台
- Web负载均衡的几种实现方式
- 98.公共汽车
- 《深入.NET平台和C#编程》内部测试题
- 数据存储和界面展示(一)
- php的数组与数据结构
- Passed Zend Certified PHP Engineer Examination
- hdoj 2015 偶数求和 (水)
- 学习笔记————MAth.方法()和重载.
- LeetCode 217. Contains Duplicate
- Linux c 管道和有名管道(FIFO)
- python 关键字 之 assert(断言)