黎活明8天快速掌握android视频教程--22_访问通信录中的联系人和添加联系人

Android系统中联系人的通讯录的contentProvide是一个单独的apk,显示在界面的contact也是一个独立的apk,联系人apk通过contentProvide访问底层的数据库。

现在我们自己建立一个apk,访问底层数据库中的联系人

常用的几张表如下

raw_contacts:存放联系人的ID

字段display_name:存放姓+名的组合,便于快速得到用户的姓名。注意,当向该表添加联系人时该字段是为null的,只有在向data表中添加姓名时,才会发出update语句来更新该字段。

首先,我们可以在File Explorer视图下找到contacts2.db文件,这是通讯录的文件

 

然后,我们用SQLite打开,分析下它的数据库结构:

raw_contacts表:

 

raw_contacts:存放联系人的ID

字段display_name:存放姓+名的组合,便于快速得到用户的姓名。注意,当向该表添加联系人时该字段是为null的,只有在向data表中添加姓名时,才会发出update语句来更新该字段。

raw_contacts表中的_id和data表中的_id是一一对应的关系

data:存放联系人的详细信息,如姓名、手机等,主要几个字段的含义如下:

字段data1:存放具体数据

字段data2:对于电话号码,存放类型:家庭电话、手机号等,2代表手机号

            对于邮箱,存放类型

            对于姓名,存放名字部分,data3存放姓氏部分

字段mimetype_id:区分数据的类型,5-电话数据,6-姓名数据,1-email数据,对应表mimetypes中的记录ID

mimetypes表:

 

操作数据库的时候需要添加权限:

使用ContentResolver对通信录中的数据进行添加、删除、修改和查询操作,需要加入读写联系人信息的权限

<uses-permissionandroid:name="android.permission.READ_CONTACTS" />

<uses-permissionandroid:name="android.permission.WRITE_CONTACTS" />

我们来看下面的代码读取联系人的信息:

复制代码
package com.example.test;

import java.util.ArrayList;

import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.test.AndroidTestCase;
import android.util.Log;

public class ContactsTest extends AndroidTestCase {
    private static final String TAG = "ContactsTest";

    /**
     * 获取联系人
     * */
    public void testGetContacts(){
        Uri uri = Uri.parse("content://com.android.contacts/contacts");    // 访问所有联系人
        ContentResolver resolver = getContext().getContentResolver();
        Cursor cursor = resolver.query(uri, new String[]{"_id"}, null, null, null);
        while(cursor.moveToNext()){
            int contactsId = cursor.getInt(0);
            StringBuilder sb = new StringBuilder("contactsId=");
            sb.append(contactsId);
            uri = Uri.parse("content://com.android.contacts/contacts/" + contactsId + "/data");    //某个联系人下面的所有数据
            Cursor dataCursor = resolver.query(uri, new String[]{"mimetype", "data1", "data2"}, null, null, null);
            while(dataCursor.moveToNext()){
                String data = dataCursor.getString(dataCursor.getColumnIndex("data1"));
                String type = dataCursor.getString(dataCursor.getColumnIndex("mimetype"));
                if("vnd.android.cursor.item/name".equals(type)){    // 如果他的mimetype类型是name
                    sb.append(", name=" + data);
                } else if("vnd.android.cursor.item/email_v2".equals(type)){    // 如果他的mimetype类型是email
                    sb.append(", email=" + data);
                } else if("vnd.android.cursor.item/phone_v2".equals(type)){    // 如果他的mimetype类型是phone
                    sb.append(", phone=" + data);
                } 
            }
            Log.i(TAG, sb.toString());
        }
    }
    
    /**
     * 根据来电号码获取联系人名字
     * */
    public void testGetContactsByNumber(){
        String number = "15292328801";
        Uri uri = Uri.parse("content://com.android.contacts/data/phones/filter/" + number);
        ContentResolver resolver = getContext().getContentResolver();
        Cursor cursor = resolver.query(uri, new String[]{"display_name"}, null, null, null);
        if(cursor.moveToFirst()){
            String name = cursor.getString(0);
            Log.i(TAG, name);
        }
    }
    
    /**
     * 添加联系人
     * 数据一个表一个表的添加,每次都调用insert方法
     * */
    public void testAddContacts(){
        /* 往 raw_contacts 中添加数据,并获取添加的id号*/
        Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
        ContentResolver resolver = getContext().getContentResolver();
        ContentValues values = new ContentValues();
        long contactId = ContentUris.parseId(resolver.insert(uri, values));
        
        /* 往 data 中添加数据(要根据前面获取的id号) */
        // 添加姓名
        uri = Uri.parse("content://com.android.contacts/data");
        values.put("raw_contact_id", contactId);
        values.put("mimetype", "vnd.android.cursor.item/name");
        values.put("data2", "周国平");
        resolver.insert(uri, values);
        
        // 添加电话
        values.clear();
        values.put("raw_contact_id", contactId);
        values.put("mimetype", "vnd.android.cursor.item/phone_v2");
        values.put("data2", "2");
        values.put("data1", "15099144117");
        resolver.insert(uri, values);
        
        // 添加Email
        values.clear();
        values.put("raw_contact_id", contactId);
        values.put("mimetype", "vnd.android.cursor.item/email_v2");
        values.put("data2", "2");
        values.put("data1", "zhouguoping@qq.com");
        resolver.insert(uri, values);
    }
    
    /**
     * 添加联系人
     * 在同一个事务中完成联系人各项数据的添加
     * 使用ArrayList<ContentProviderOperation>,把每步操作放在它的对象中执行
     * */
    public void testAddContacts2(){
        Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
        ContentResolver resolver = getContext().getContentResolver();
        // 第一个参数:内容提供者的主机名
        // 第二个参数:要执行的操作
        ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
        
        // 操作1.添加Google账号,这里值为null,表示不添加
        ContentProviderOperation operation = ContentProviderOperation.newInsert(uri)
                .withValue("account_name", null)// account_name:Google账号
                .build();
        
        // 操作2.添加data表中name字段
        uri = Uri.parse("content://com.android.contacts/data");
        ContentProviderOperation operation2 = ContentProviderOperation.newInsert(uri)
                // 第二个参数int previousResult:表示上一个操作的位于operations的第0个索引,
                // 所以能够将上一个操作返回的raw_contact_id作为该方法的参数
                .withValueBackReference("raw_contact_id", 0)
                .withValue("mimetype", "vnd.android.cursor.item/name")
                .withValue("data2", "周国平")
                .build();
        
        // 操作3.添加data表中phone字段
        uri = Uri.parse("content://com.android.contacts/data");
        ContentProviderOperation operation3 = ContentProviderOperation.newInsert(uri)
                .withValueBackReference("raw_contact_id", 0)
                .withValue("mimetype", "vnd.android.cursor.item/phone_v2")
                .withValue("data2", "2")
                .withValue("data1", "15099144117")
                .build();
        
        // 操作4.添加data表中的Email字段
        uri = Uri.parse("content://com.android.contacts/data");
        ContentProviderOperation operation4 = ContentProviderOperation
                .newInsert(uri).withValueBackReference("raw_contact_id", 0)
                .withValue("mimetype", "vnd.android.cursor.item/email_v2")
                .withValue("data2", "2")
                .withValue("data1", "zhouguoping@qq.com").build();
        
        operations.add(operation);
        operations.add(operation2);
        operations.add(operation3);
        operations.add(operation4);
        
        try {
            resolver.applyBatch("com.android.contacts", operations);
        } catch (Exception e) {
            e.printStackTrace();
        } 
    }
}
复制代码

 

posted on   luzhouxiaoshuai  阅读(257)  评论(0编辑  收藏  举报

编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示