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

来源:互联网 发布:西安信利软件 编辑:程序博客网 时间:2024/05/02 01:33

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


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

通讯录数据库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); //联系人IDString 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
原创粉丝点击