Android 关于操作联系人数据库的实际问题的解析和处理

一,联系人数据库

联系人数据库路径:/data/data/com.android.providers.contacts/databases/contact2.db 

联系人数据库中的表非常多,但实际要用到的比较重要的有4张表:contacts、data、mimetypes和raw_contacts

1、contacts表 
display_name: 联系人名称 
photo_id:头像的ID,如果没有设置联系人头像,这个字段就为空 
times_contacted:通话记录的次数 
last_time_contacted: 最后的通话时间 
lookup :是一个持久化的储存,因为用户可能会改名,但是它改不了lookup 
该表保存了本机保存的所有联系人,每个联系人占一行,该表保存了联系人的ContactID、联系次数、最后一次联系的时间、是否含有号码、是否被添加到收藏夹等信息

2、data表

raw_contact_id:通过raw_contact_id可以找到 raw_contact表中相对的数据。 
data1 到 data15 这里保存着联系人的信息 联系人名称 联系人电话号码 电子邮件 备注 等等。 
该表保存了所有创建过的手机测联系人的所有信息,每个字段占一行 ,该表保存了两个ID: MimeTypeID和RawContactID,从而将data表和raw_contacts表联系起来。联系人的所有信息保存在列data1至data15中,各列中保存的内容根据MimeTypeID的不同而不同。如保存号码(MimeTypeID=5)的那行数据中,data1列保存号码,data2列保存号码类型(手机号码、家庭号码、工作号码等)
 

3、mimetypes

该表定义的各个联系人字段的唯一标志,及联系人信息的类别标志

4、raw_contacts

version :版本号,用于监听变化 
deleted :删除标志, 0为默认 1 表示这行数据已经删除 
display_name : 联系人名称 
last_time_contacts : 最后联系的时间 
该表保存了所有创建过的手机联系人,包括已经删除的联系人、每个联系人占一行,表里有一列标识该联系人是否被删除,该表保存了两个ID: RawContactID和ContactID,从而将contacts表和raw_contacts表联系起来。该表保存了联系人的RawContactID、ContactID、联系次数、最后一次联系的时间、是否被添加到收藏夹、显示的名字、用于排序的汉语拼音等信息

二、关于操作联系人数据库

对于换机类型的应用,最重要的是联系人数据、短信数据和通话记录数据的迁移,需要进行读取和写入操作

1、读取联系人数据

正常可以在读取之前按照各个联系人来读取各个表中的数据,还有比较简便的方法,直接读取每个表,这种方法也是不会对之后写入数据库造成影响,在需要获取手机中联系人数量时,要获取contacts表的数量而不是raw_contacts表

public int getContactsCount() {
        ArrayList<DataInfo> rawList = new ArrayList<>();
        ContentResolver resolver = MainApplication.getContext().getContentResolver();
//        final Cursor c = resolver.query(ContactsContract.RawContacts.CONTENT_URI, null, null, null, null);
        final Cursor c = resolver.query(ContactsContract.Contacts.CONTENT_URI,null,null,null,null);

        int contactsCount = c.getCount();
        Log.d(TAG, "getContactsCount: " + contactsCount);
        return contactsCount;

    }

2、写入数据库

在写入时,无需对各个联系人信息按照每个联系人进行写入,直接向相关表中插入数据,后续再实现表的关联

public static void addContact(ArrayList<DataInfo> sdatas, int offset) {

    if (sdatas == null || sdatas.size() == 0) {
        return;
    }

    ContentValues mValues = new ContentValues();
    //首先向RawContacts.CONTENT_URI执行一个空值插入,目的是获得系统返回的rawContactId
    Uri rawContactUri = MainApplication.getContext().getContentResolver().insert(ContactsContract.RawContacts.CONTENT_URI, mValues);
    long rawContactId = ContentUris.parseId(rawContactUri);
    long common_id = sdatas.get(offset).raw_contact_id;//SData数据里的raw_contact_id
    for (int i = offset; i < sdatas.size(); i++) {
        mValues.clear();

        DataInfo sdata = sdatas.get(i);
        //判断这些sdata是否属于同一个联系人
        if (sdata.raw_contact_id == common_id) {
            // 向data表插入数据
            mValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);//插入上面获取到的raw_contact_id
            if (sdata.is_primary != 0) {
                mValues.put(ContactsContract.Data.IS_PRIMARY, sdata.is_primary);
            }
            if (!TextUtils.isEmpty(sdata.mimetype)) {
                mValues.put(ContactsContract.Data.MIMETYPE, sdata.mimetype);
            }

            if (sdata.is_surper_primary != 0) {
                mValues.put(ContactsContract.Data.IS_SUPER_PRIMARY, sdata.is_surper_primary);
            }
            if (sdata.data_version != 0) {
                mValues.put(ContactsContract.Data.DATA_VERSION, sdata.data_version);
            }
            if (!TextUtils.isEmpty(sdata.data1)) {
                mValues.put(ContactsContract.Data.DATA1, sdata.data1);
            }
            if (!TextUtils.isEmpty(sdata.data2)) {
                mValues.put(ContactsContract.Data.DATA2, sdata.data2);
            }
            if (sdata.mimetype.equals(DataInfo.LOCA_GROUP_TYPE)) {
                mValues.put(ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID, sdata.data1);
            } else if (sdata.mimetype.equals(DataInfo.LOCA_NAME)) {
                mValues.put(ContactsContract.Data.DATA2, sdata.data1);
            } else if (sdata.mimetype.equals(ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE)) {
                if (map.get(sdata.data1) != null) {
                    //根据原来的groupId获取最新的groupId
                    String groupId = (String) map.get(sdata.data1);
                    mValues.put(ContactsContract.Data.DATA1, groupId);
                }
            }
            if (!TextUtils.isEmpty(sdata.data3)) {
                mValues.put(ContactsContract.Data.DATA3, sdata.data3);
            }
            if (!TextUtils.isEmpty(sdata.data4)) {
                mValues.put(ContactsContract.Data.DATA4, sdata.data4);
            }
            if (!TextUtils.isEmpty(sdata.data5)) {
                mValues.put(ContactsContract.Data.DATA5, sdata.data5);
            }
            if (!TextUtils.isEmpty(sdata.data6)) {
                mValues.put(ContactsContract.Data.DATA6, sdata.data6);
            }
            if (!TextUtils.isEmpty(sdata.data7)) {
                mValues.put(ContactsContract.Data.DATA7, sdata.data7);
            }
            if (!TextUtils.isEmpty(sdata.data8)) {
                mValues.put(ContactsContract.Data.DATA8, sdata.data8);
            }
            if (!TextUtils.isEmpty(sdata.data9)) {
                mValues.put(ContactsContract.Data.DATA9, sdata.data9);
            }
            if (!TextUtils.isEmpty(sdata.data10)) {
                mValues.put(ContactsContract.Data.DATA10, sdata.data10);
            }
            if (!TextUtils.isEmpty(sdata.data11)) {
                mValues.put(ContactsContract.Data.DATA11, sdata.data11);
            }
            if (!TextUtils.isEmpty(sdata.data12)) {
                mValues.put(ContactsContract.Data.DATA12, sdata.data12);
            }
            if (!TextUtils.isEmpty(sdata.data13)) {
                mValues.put(ContactsContract.Data.DATA13, sdata.data13);
            }
            if (!TextUtils.isEmpty(sdata.data14)) {
                mValues.put(ContactsContract.Data.DATA14, sdata.data14);
            }
            if (!TextUtils.isEmpty(sdata.data_sync1)) {
                mValues.put(ContactsContract.Data.SYNC1, sdata.data_sync1);
            }
            if (!TextUtils.isEmpty(sdata.data_sync2)) {
                mValues.put(ContactsContract.Data.SYNC2, sdata.data_sync2);
            }
            if (!TextUtils.isEmpty(sdata.data_sync3)) {
                mValues.put(ContactsContract.Data.SYNC3, sdata.data_sync3);
            }
            if (!TextUtils.isEmpty(sdata.data_sync4)) {
                mValues.put(ContactsContract.Data.SYNC4, sdata.data_sync4);
            }
            MainApplication.getContext().getContentResolver().insert(ContactsContract.Data.CONTENT_URI, mValues);
        }
        //
        else {
            //使用嵌套
            addContact(sdatas, i);
            break;    //进入嵌套的同时记得结束for循环!!!
        }
    }
}

该方法中sdata.raw_contact_id 和 common_id都是旧手机的rawContactsId,仅仅是用来判断当前插入的联系人是否为同一个联系人的数据,而关于实际raw_contact_id的插入要写入新手机实际的新的raw_contact_id,这样才能实现数据关联,获取实际新手机中的rawContactsId:

ContentValues mValues = new ContentValues();
//首先向RawContacts.CONTENT_URI执行一个空值插入,目的是获得系统返回的rawContactId
Uri rawContactUri = MainApplication.getContext().getContentResolver().insert(ContactsContract.RawContacts.CONTENT_URI, mValues);
long rawContactId = ContentUris.parseId(rawContactUri);

使用嵌套循环方式插入全部数据,这种处理方法,仅适用于小量数据时,在需要操作大量数据,建议使用批量插入操作

写入联系人分组时,同样需要获取新手机实际的groupId,方法思路基本和写入联系人差不多

public static void addGroups(ArrayList<GroupInfo> sGroups) {

        if (sGroups == null || sGroups.size() == 0) {
            return;
        }

        ContentValues mValues = new ContentValues();

        for (int i = 0; i < sGroups.size(); i++) {
            mValues.clear();
            GroupInfo sGroup = sGroups.get(i);
            mValues.put(ContactsContract.Groups.TITLE, sGroup.title);
            //首先向RawContacts.CONTENT_URI执行一个空值插入,目的是获得系统返回的rawContactId
            Uri groupUri = MainApplication.getContext().getContentResolver().insert(ContactsContract.Groups.CONTENT_URI, mValues);
            long newGroupId = ContentUris.parseId(groupUri);
//            mValues.put(Groups._ID, groupId);//插入上面获取到的_id
//            SGroup sGroup = sGroups.get(i);
//            // 向表插入数据
//            if (!TextUtils.isEmpty(sGroup.sourceid)) {
//                mValues.put(Groups.SOURCE_ID, sGroup.sourceid);
//            }
//            if (sGroup.dirty != 0) {
//                mValues.put(Groups.DIRTY, sGroup.dirty);
//            }
//            if (!TextUtils.isEmpty(sGroup.title)) {
//                mValues.put(Groups.TITLE, sGroup.title);
//            }
//            if (sGroup.version != 0) {
//                mValues.put(Groups.VERSION, sGroup.version);
//            }
//            context.getContentResolver().insert(Groups.CONTENT_URI, mValues);

            map.put(sGroup.id + "", newGroupId + "");  //关联原有的groupId与新的groupId,添加联系人时替换

        }
    }
private static void inPutContactsDB() {

        String contactPath = getFilePath(CONTACTS_DIRECTORY, CONTACT_PATH_DIR);
        String groupPath = getFilePath(CONTACTS_DIRECTORY, GROUP_PATH_DIR);
//        File contactFile =new File(ContactPath);
        //导入文件到数据库
        final HashMap<String, Object> contactResult = FileUtils.importFile(contactPath, DataInfo.class);
        final HashMap<String, Object> groupResult = FileUtils.importFile(groupPath, GroupInfo.class);


        new Thread(new Runnable() {
            @Override
            public void run() {
                //写入数据库
                //1.写入
//                Log.e(TAG, "1.写入联系人组");
                addGroups((ArrayList<GroupInfo>) groupResult.get(GroupInfo.class.getSimpleName()));
//                Log.e(TAG, "2.写入联系人");
                addContact((ArrayList<DataInfo>) contactResult.get(DataInfo.class.getSimpleName()), 0);

//                if(file.delete()){
//                    Log.e(TAG, "删除临时文件contact.txt");
//                }else {
//                    Log.e(TAG, "删除临时文件失败!");
//                }
            }
        }).start();

    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值