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

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


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

通讯录数据库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();
        }








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值