Android利用ContentProvider对联系人进行操作

先在清单文件中添加以下权限:

<uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.READ_PROFILE" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.WRITE_CONTACTS"/>

代码是写在androidTest下的,可以直接copy后直接进行单元测试,也可以根据需要拿去使用。友情提醒:最好在模拟器上测试,因为有删除联系人的操作,千万别不小心把自己手机上的联系人删了;

1.png
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.net.Uri;
import android.os.RemoteException;
import android.provider.ContactsContract;
import android.test.AndroidTestCase;
import android.util.Log;

import java.util.ArrayList;

/**
 * Created by Administrator on 2017/6/28 0028.
 */

public class ContactsTest extends AndroidTestCase {


    /**
     * 获取手机上的电话簿
     * 1、先读取contacts表,获取ContactsID;
     * 2、再在raw_contacts表中根据ContactsID获取RawContactsID;
     * 3、然后就可以在data表中根据RawContactsID获取该联系人的各数据了。
     */
    public void testGetContacts() {
//        Uri uri = Uri.parse("content://com.android.contacts/contacts");//访问所有联系人
        Uri uri = ContactsContract.Contacts.CONTENT_URI;//这个更方便各个版本的Android系统
        ContentResolver contentResolver = getContext().getContentResolver();
        Cursor cursor = contentResolver.query(uri, null, null, null, null);
        while (cursor.moveToNext()) {
            String contact_id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
            String contact_name = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.DISPLAY_NAME));
            StringBuilder stringBuilder = new StringBuilder("contactId =");
            stringBuilder.append(contact_id).append(",contact_name =").append(contact_name);
            Cursor phones = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=?", new String[]{contact_id}, null);
            // 上面的ContactsContract.CommonDataKinds.Phone.CONTENT_URI
            // 可以用下面的phoneUri代替
            // Uri phoneUri=Uri.parse("content://com.android.contacts/data/phones");

            while (phones.moveToNext()) {
                String contact_phone = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                stringBuilder.append(",contact_phone =" + contact_phone);
            }
            phones.close();
            Cursor emails = contentResolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null, ContactsContract.CommonDataKinds.Email.CONTACT_ID + "=?", new String[]{contact_id}, null);
            while (emails.moveToNext()) {
                String contact_email = emails.getString(emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
                stringBuilder.append(",emali = " + contact_email);
            }
            emails.close();
            Log.d("testGetContacts", stringBuilder.toString());
        }
        cursor.close();
    }

    /**
     * 单独添加一个联系人
     */
    public void testInsert() {
        ContentValues contentValues = new ContentValues();
        // 首先向RawContacts.CONTENT_URI执行一个空值插入,目的是获取系统返回的rawContactId
        Uri rawContact_uri = getContext().getContentResolver().insert(ContactsContract.RawContacts.CONTENT_URI, contentValues);
        long rawContactId = ContentUris.parseId(rawContact_uri);
        // 往data表入姓名数据
        contentValues.clear();
        contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
        contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);// 内容类型
        contentValues.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, "我就是测试1");
        getContext().getContentResolver().insert(ContactsContract.Data.CONTENT_URI, contentValues);
        // 往data表入电话数据
        contentValues.clear();
        contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
        contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);// 内容类型
        contentValues.put(ContactsContract.CommonDataKinds.Phone.NUMBER, "88888888");
        contentValues.put(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE);
        getContext().getContentResolver().insert(ContactsContract.Data.CONTENT_URI, contentValues);
        // 往data表入Email数据
        contentValues.clear();
        contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
        contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE);// 内容类型
        contentValues.put(ContactsContract.CommonDataKinds.Email.DATA, "xxxx@QQ.con");
        contentValues.put(ContactsContract.CommonDataKinds.Email.TYPE, ContactsContract.CommonDataKinds.Email.TYPE_WORK);
        getContext().getContentResolver().insert(ContactsContract.Data.CONTENT_URI, contentValues);
    }

    /**
     * 批量添加联系人,效率高
     */
    public void testBatchInsert() throws RemoteException, OperationApplicationException {
        ArrayList<ContentProviderOperation> ops = new ArrayList<>();
        int rawContactInsertIndex = 0;
        for (int i = 1; i <= 10; i++) {
            rawContactInsertIndex = ops.size();
            ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
                    .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
                    .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null)
                    .withYieldAllowed(true).build());
            // 添加姓名
            ops.add(ContentProviderOperation
                    .newInsert(android.provider.ContactsContract.Data.CONTENT_URI)
                    .withValueBackReference(ContactsContract.RawContacts.Data.RAW_CONTACT_ID, rawContactInsertIndex)
                    .withValue(ContactsContract.RawContacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
                    .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, "测试" + i)
                    .withYieldAllowed(true).build());
            // 添加号码
            ops.add(ContentProviderOperation
                    .newInsert(android.provider.ContactsContract.Data.CONTENT_URI)
                    .withValueBackReference(ContactsContract.RawContacts.Data.RAW_CONTACT_ID, rawContactInsertIndex)
                    .withValue(ContactsContract.RawContacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
                    .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, "88888" + i)
                    .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE)
                    .withValue(ContactsContract.CommonDataKinds.Phone.LABEL, "").withYieldAllowed(true).build());
            // 添加邮箱
            ops.add(ContentProviderOperation
                    .newInsert(android.provider.ContactsContract.Data.CONTENT_URI)
                    .withValueBackReference(ContactsContract.RawContacts.Data.RAW_CONTACT_ID, rawContactInsertIndex)
                    .withValue(ContactsContract.RawContacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
                    .withValue(ContactsContract.CommonDataKinds.Email.DATA, "xxxx" + i + "@QQ.com")
                    .withValue(ContactsContract.CommonDataKinds.Email.TYPE, ContactsContract.CommonDataKinds.Email.TYPE_WORK)
                    .withYieldAllowed(true).build());
        }
        if (ops != null) {
            // 真正添加
            ContentProviderResult[] results = mContext.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
            for (ContentProviderResult result : results) {
                Log.d("BatchAddContact==", result.uri.toString());
            }
        }
    }

    /**
     * 根据条件删除联系人
     * 非常简单只需要将raw_contacts表中指定RawContactID(其实在raw_contacts表中,应该就是_id列中的数据)的行删除,其他表中与之关联的数据都会自动删除。
     * Android帮助文档:When a raw contact is deleted, all of its Data rows as
     * well as StatusUpdates, AggregationExceptions, PhoneLookup rows are
     * deleted automatically.
     */
    public void testDel() {
        String name = "Hhhh";
        ContentResolver contentResolver = getContext().getContentResolver();
        //方法一
//        Cursor query = contentResolver.query(ContactsContract.RawContacts.CONTENT_URI, new String[]{ContactsContract.Data._ID}, ContactsContract.Data.DISPLAY_NAME + "=?", new String[]{name}, null);
//        while (query.moveToNext()) {
//            String id = query.getString(query.getColumnIndex(ContactsContract.Data._ID));
//            contentResolver.delete(ContactsContract.RawContacts.CONTENT_URI, ContactsContract.Data.DISPLAY_NAME + "=?", new String[]{name});
//            contentResolver.delete(android.provider.ContactsContract.Data.CONTENT_URI, ContactsContract.Contacts.Data.RAW_CONTACT_ID + "=?", new String[]{id});
//        }
//        query.close();

        //方法二
        //根据名字在Contacts表中,找出符合的行,并只需要_ID列
//        Cursor query = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, new String[]{ContactsContract.Data._ID}, ContactsContract.Data.DISPLAY_NAME + "=?", new String[]{name}, null);
//        //遍历每一行
//        while (query.moveToNext()) {
//            //得到此行中的_ID列的内容id
//            String id = query.getString(query.getColumnIndex(ContactsContract.Data._ID));
//            //拿着这个id,去RawContacts表中查找数据(注意的是,这个id在此表中对应的是CONTACT_ID列),得到CONTACT_ID列数据=id的结果;我们只需要此表中的_ID列
//            Cursor query1 = contentResolver.query(ContactsContract.RawContacts.CONTENT_URI, new String[]{ContactsContract.RawContacts.Data._ID}, ContactsContract.RawContacts.CONTACT_ID + "=?", new String[]{id}, null);
//            //再次遍历
//            while (query1.moveToNext()) {
//                //得到RawContacts表中的_ID列的数据id
//                String raw_contact_id = query1.getString(query1.getColumnIndex(ContactsContract.RawContacts.Data._ID));
//                //我们拿着这个id,去删除RawContacts表中对应的数据,就可以删掉所以数据了,两种删法如下:
////                contentResolver.delete(ContactsContract.RawContacts.CONTENT_URI, ContactsContract.RawContacts.Data._ID + "=?", new String[]{raw_contact_id});//方法1
//                contentResolver.delete(ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, Long.parseLong(raw_contact_id)), null, null);//方法2
//            }
//            query1.close();
//        }
//        query.close();

        //方法三
        Cursor query = contentResolver.query(ContactsContract.RawContacts.CONTENT_URI, new String[]{ContactsContract.RawContacts.Data._ID}, ContactsContract.Data.DISPLAY_NAME + "=?", new String[]{name}, null);
        while (query.moveToNext()) {
            //得到此行中的_ID列的内容id
            String id = query.getString(query.getColumnIndex(ContactsContract.RawContacts.Data._ID));
            //我们拿着这个id,去删除RawContacts表中对应的数据,就可以删掉所以数据了,两种删法如下:
//                contentResolver.delete(ContactsContract.RawContacts.CONTENT_URI, ContactsContract.RawContacts.Data._ID + "=?", new String[]{id});//方法1
            contentResolver.delete(ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, Long.parseLong(id)), null, null);//方法2
        }
        query.close();
    }

    /**
     * 更新联系人
     * 联系人的所有信息都是保存在data表中,所以要更新联系人,我们只需要根
     * 据RawContactID和MIMETYPE修改data表中的内容。
     */
    public void testUpdate() {
        //根据名字修改电话号码
        String name = "测试7";
        ContentValues contentValues = new ContentValues();
        contentValues.put(ContactsContract.CommonDataKinds.Phone.NUMBER, "7777777");
        contentValues.put(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_WORK_MOBILE);
        ContentResolver contentResolver = getContext().getContentResolver();
        Cursor cursor = contentResolver.query(ContactsContract.RawContacts.CONTENT_URI, new String[]{ContactsContract.RawContacts.Data._ID}, ContactsContract.Data.DISPLAY_NAME + "=?", new String[]{name}, null);
        while (cursor.moveToNext()) {
            String id = cursor.getString(cursor.getColumnIndex(ContactsContract.RawContacts.Data._ID));
            contentResolver.update(ContactsContract.Data.CONTENT_URI, contentValues, ContactsContract.Data.RAW_CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?", new String[]{id, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE});
        }
        cursor.close();
    }

    /**
     * 删除所有联系人
     */
    public void testdeleteAllContacts(){
        ContentResolver contentResolver = getContext().getContentResolver();
        Cursor query = contentResolver.query(ContactsContract.RawContacts.CONTENT_URI, new String[]{ContactsContract.RawContacts.Data._ID}, null, null, null);
        while (query.moveToNext()) {
            //得到此行中的_ID列的内容id
            String id = query.getString(query.getColumnIndex(ContactsContract.RawContacts.Data._ID));
            //我们拿着这个id,去删除RawContacts表中对应的数据,就可以删掉所以数据了,两种删法如下:
//                contentResolver.delete(ContactsContract.RawContacts.CONTENT_URI, ContactsContract.RawContacts.Data._ID + "=?", new String[]{id});//方法1
            contentResolver.delete(ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, Long.parseLong(id)), null, null);//方法2
        }
        query.close();
    }
}

配合这篇博客,更好理解:http://blog.csdn.net/lksodit_yiyi/article/details/7887348
有不完善的地方,还请评论中指出。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,392评论 25 707
  • 网站: http://ui4app.com/category 技术网站: http://www.bestsdk.c...
    LYPC_下里巴人阅读 978评论 0 1
  • 如今,找热闹的地方容易,寻清静的地方难;找繁华的地方容易,寻拙朴的地方难。十一假期随夫写生,来到太白黑峪,近...
    城南皓月阅读 232评论 0 0
  • 这张牌怎么看都没感觉,不知道能想到什么。慢慢看,一个姜黄色的背景墙,蓝色的像冰山一样的石头,一个像圣物一样被编织的...
    储晴whj阅读 135评论 0 0
  • 经营企业就是经营人才,而经营人才就是经营人才的需求。 单海洋股权激励在非上市公司的成功概率更大。因为不用担心股价的...
    刘敏捷阅读 349评论 3 0