你的位置:首页 > 操作系统

[操作系统]Android手机通讯录解析


相关图片上传麻烦,原文件到我的博客上传的文件里下载。

 

1、通讯录应用介绍

通讯录应用是Android自带的应用程序,我们看到此应用的时候,可能只认为这是一个应用,用数据库存储数据,但是实际上不是这样的。
通讯录是ContentProvider的应用,通讯录由两部分组成:
(1)com.android.providers.contacts的ContentProvider:真正存储数据的ContentProvider
(2)com.android.contacts:运用ContentResolver获取数据的图形用户界面;

2、通讯录数据库目录结构

(1)、通讯录数据库目录结构的获取

打开Eclipse软件,调出虚拟机。如果已经创建过虚拟机,则只需要运行程序,如下图

 

如果没有创建就需要再去创建一个虚拟机。

调出虚拟机效果如下:

 

接下来就要:

 

 

 

通讯录是存放在/data/data/com.android.providers.contacts/databases/contacts2.db里的

接下来就是导出联系人的数据库:

 

导出后得到这样的数据库:

 

 

这个是QLite DatabaseBrowser 工具

打开它把contacts2.db数据库拖进去就可以了。

得到如下:

 

查看数据库表中数据:

 

到此如何获取手机数据到此结束,前期工作完成。

3、通讯录数据库结构介绍

 

这是手机通讯录直接相关联的几张表,圈出来的比较重要。

(1)       mimetype表

 

(2)       contacts表

 

此处的name_raw_contact_id为raw_contacts表的主键

(3)       raw_contacts表

 

此处_id为raw_contacts表的主键,version翻译后叫版本号,一般一个联系人创建后版本号就从2开始,当这个联系人每做一次操作后version都增加,一般是增加1,但有时不确定反正他会增加。对于Android手机而言,它本身自带了一个通讯录,他对与联系人的删除操作就用户而言是删除了,因为在用户界面没有了该来联系人了。但是事实上Android并没有真正删除它。仅仅是在raw_contacts表中把deleted字段标记为了1,意思是说“1”代表删除了,“0”代表联系人没删除,是存在的。contact_id来自contacts表的主键。这样contacts和raw_contacts联系在一起了。

(4)       data表

 

data表中的mimetype_id来自mimetype表,raw_contact_id来自raw_contacts表。一般来说data1到data15的字段都是存放数据的。

其中mimetype_id=5代表电话号码mimetype_id=7代表姓名。当mimetype_id=5时data1存放电话号码,data2存放电话号码的类型,data2=2,代表电话号码为手机号。

2、3、手机通讯录的操作介绍

(1)新增  这里介绍了两种方法

/**

     * 将一组联系人添加到手机通讯录中

     *

     * @param Contacts

     * @param context

     */

    public static void AddContact(ContactInfo[] Contacts, Context context) {

 

        for (int i = 0; i < Contacts.length; i++) {

            ContentValues values = new ContentValues();

            // 下面的操作会根据RawContacts表中已有的rawContactId使用情况自动生成新联系人的rawContactId

            UrirawContactUri = context.getContentResolver().insert(

                    RawContacts.CONTENT_URI, values);

            long rawContactId = ContentUris.parseId(rawContactUri);

            // 向data表插入姓名数据

            if (Contacts[i].Name != "") {

                values.clear();

                values.put(Data.RAW_CONTACT_ID, rawContactId);

                values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);

                values.put(StructuredName.GIVEN_NAME, Contacts[i].Name);

                context.getContentResolver().insert(

                        ContactsContract.Data.CONTENT_URI, values);

            }

 

            // 向data表插入电话数据

            if (Contacts[i].Num != "") {

                values.clear();

                values.put(Data.RAW_CONTACT_ID, rawContactId);

                values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);

                values.put(Phone.NUMBER, Contacts[i].Num);

                values.put(Phone.TYPE, Phone.TYPE_MOBILE);

                context.getContentResolver().insert(

                        ContactsContract.Data.CONTENT_URI, values);

            }

        }

    }

 

    /**

     * 将单个联系人添加到通讯录中

     *

     * @param Contact

     * @param context

     */

    public static void AddContact(ContactInfo Contact, Context context) {

 

        ContentValues values = new ContentValues();

        // 下面的操作会根据RawContacts表中已有的rawContactId使用情况自动生成新联系人的rawContactId

        Uri rawContactUri =context.getContentResolver().insert(

                RawContacts.CONTENT_URI, values);

        long rawContactId = ContentUris.parseId(rawContactUri);

   

        // 向data表插入姓名数据

        if (Contact.Name != "") {

            values.clear();

            values.put(Data.RAW_CONTACT_ID, rawContactId);

            values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);

            values.put(StructuredName.GIVEN_NAME, Contact.Name);

            context.getContentResolver().insert(

                    ContactsContract.Data.CONTENT_URI, values);

        }

       

        // 向data表插入电话数据

        if (Contact.Num != "") {

            values.clear();

            values.put(Data.RAW_CONTACT_ID, rawContactId);

            values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);

            values.put(Phone.NUMBER, Contact.Num);

            values.put(Phone.TYPE, Phone.TYPE_MOBILE);

            context.getContentResolver().insert(

                    ContactsContract.Data.CONTENT_URI, values);

        }

 

    }

   

       public static void testAddContacts(ContactInfo[] Contacts,Context context){

          for (int i = 0; i < Contacts.length; i++) {

           //插入raw_contacts表,并获取_id属性

           Uri uri = Uri.parse("content://com.android.contacts/raw_contacts"); //获取操作的表的路径

           ContentResolver resolver = context.getContentResolver(); //类似.NET中的上下文对象或数据库操作

           ContentValues values = newContentValues(); //定义一个联系人操作变量

           long contact_id = ContentUris.parseId(resolver.insert(uri,values));

           //插入data表

           

           uri = Uri.parse("content://com.android.contacts/data");

           //addName

           values.put("raw_contact_id", contact_id);

           values.put(Data.MIMETYPE,"vnd.android.cursor.item/name");

           values.put("data2", Contacts[i].Name);

           values.put("data1", Contacts[i].Name);

           resolver.insert(uri, values);

           values.clear();

           //addPhone

           values.put("raw_contact_id", contact_id);

           values.put(Data.MIMETYPE,"vnd.android.cursor.item/phone_v2");

           values.put("data2", "2");   //手机

           values.put("data1", Contacts[i].Num);

           resolver.insert(uri, values);

           values.clear();

          }

     

        }

   

       public static void testAddContacts(ContactInfo Contact, Contextcontext){

           //插入raw_contacts表,并获取_id属性

           Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");

           ContentResolver resolver = context.getContentResolver();

           ContentValues values = newContentValues();

           long contact_id = ContentUris.parseId(resolver.insert(uri,values));

           //插入data表

           

           uri = Uri.parse("content://com.android.contacts/data");

           //addName

           values.put("raw_contact_id", contact_id);

           values.put(Data.MIMETYPE,"vnd.android.cursor.item/name");

           values.put("data2", Contact.Name);

           values.put("data1", Contact.Name);

           resolver.insert(uri, values);

           values.clear();

           //addPhone

           values.put("raw_contact_id", contact_id);

           values.put(Data.MIMETYPE,"vnd.android.cursor.item/phone_v2");

           values.put("data2", "2");   //手机

           values.put("data1", Contact.Num);

           resolver.insert(uri, values);

           values.clear();

         /**  //add email

           values.put("raw_contact_id", contact_id);

           values.put(Data.MIMETYPE,"vnd.android.cursor.item/email_v2");

           values.put("data2", "2");   //单位

           values.put("data1", "www.2cto.com");

           resolver.insert(uri, values); */

        }

(2)修改  此处也介绍两种方法针对ID的来源

/**

     * 更新联系人

     *

     * @param context

     *           上下文对象

     * @param name

     *           联系人姓名

     * @param number

     *           手机号

     * @param ContactId

     *           ID(此ID是由通讯录数据库自动生成的,并且该ID为contacts表中的主键)

     */

       public static void testUpdate(Context context, String name,

                String number, StringContactId){

          String version="0";

          String rawContactsId ="";

          ContentResolver cr = context.getContentResolver();

          //依contacts表中的主键查找raw_contacts表中的ID即主键

          Cursor rawContactsIdCur = cr.query(RawContacts.CONTENT_URI,

                    null, RawContacts.CONTACT_ID + " = ?",

                    new String[] { ContactId }, null);

          

          if (rawContactsIdCur.moveToFirst()) {

              version = rawContactsIdCur.getString(rawContactsIdCur

                        .getColumnIndex(RawContacts.VERSION));

              //获得raw_contacts表中的主键

              rawContactsId = rawContactsIdCur.getString(rawContactsIdCur

                        .getColumnIndex(RawContacts._ID));

              

          }

         

          ContentResolver resolver = context.getContentResolver();

          ContentValues values = newContentValues();

          

          Uri uri = Uri.parse("content://com.android.contacts/data");//对data表的所有数据操作

           resolver = context.getContentResolver();

           values.clear();

           values = new ContentValues();

           values.put("data1", number);

            //依raw_contacts表中的ID对data表做相应的修改

           resolver.update(uri, values, "mimetype=? and raw_contact_id=?", new String[]{"vnd.android.cursor.item/phone_v2",rawContactsId}) ;

           values.clear();

           values.put("data2", name);

           values.put("data1", name);

           resolver.update(uri, values, "mimetype=? and raw_contact_id=?", new String[]{"vnd.android.cursor.item/name",rawContactsId}) ;

        rawContactsIdCur.close();

      

       }

      

       /**

         *更新联系人

         *

         *@param context

         *           上下文对象

         *@param name

         *           联系人姓名

         *@param number

         *           手机号

         *@param ContactId

         *           ID(此ID是由通讯录数据库自动生成的,并且该ID为raw_contacts表中的主键)

         */

    public static void updateContact(Context context, String name,

            String number, String ContactId)

 

    {

 

        ContentValues values = new ContentValues();

 

        // 更新姓名

        values.clear();

        values.put(StructuredName.GIVEN_NAME, name);

       

        context.getContentResolver().update(ContactsContract.Data.CONTENT_URI,

 

        values,

 

        Data.RAW_CONTACT_ID + "=? and " + Data.MIMETYPE + "=?",

 

        new String[] { ContactId, StructuredName.CONTENT_ITEM_TYPE });

 

        // 更新电话

 

        values.clear();

 

        values.put(ContactsContract.CommonDataKinds.Phone.NUMBER, number);

       

        context.getContentResolver().update(ContactsContract.Data.CONTENT_URI,

 

        values,

 

        Data.RAW_CONTACT_ID + "=? and " + Data.MIMETYPE + "=?",

 

        new String[] { ContactId, Phone.CONTENT_ITEM_TYPE });

 

    }

(3)删除

这里是彻底删除,把data,contacts,raw_contacts 表中的数据以并删除,而Android自带的手机通讯录删除操作不是真正意义上的删除,仅仅是将raw_contacts表中的deleted字段改为了“1”。

      /**

             * 删除联系人

             *

             * @param context

             *           上下文对象

             * @param ContactId

             *           联系人ID

             *           ID(此ID是请求数据传递过来的,并且该ID为raw_contacts表中的主键)

             */

    public static void DeleteContact(Context context, String ContactId)

    {

         Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");

         ContentResolver resolver = context.getContentResolver();

         Cursor cursor = resolver.query(uri, new String[]{RawContacts._ID},"contact_id=?", new String[]{ContactId}, null);

          if(cursor.moveToFirst()){

           int id = cursor.getInt(0);

           //根据id删除data中的相应数据

           resolver.delete(uri, "_id=?", new String[]{id+""});

           uri = Uri.parse("content://com.android.contacts/data");

           resolver.delete(uri, "raw_contact_id=?", new String[]{id+""});

           }

    }

(4)读取联系人

/**

     * 获取联系人

     *

     * @return list数组,包含手机通讯录中的联系人

     */

    private List<Map<String, Object>> getContacts() {

 

        List<Map<String, Object>>list = new ArrayList<Map<String,Object>>();

 

        // 获取用来操作数据的类的对象,对联系人的基本操作都是使用这个对象

        ContentResolver cr =getContentResolver();

        // 查询contacts表的所有记录

        Cursor cur =cr.query(ContactsContract.Contacts.CONTENT_URI, null,

                null, null, null);

 

        String deleted = "1";

        String version = "0";

        // 如果记录不为空

        if (cur.getCount() > 0) {

            // 游标初始指向查询结果的第一条记录的上方,执行moveToNext函数会判断

            // 下一条记录是否存在,如果存在,指向下一条记录。否则,返回false。

            while (cur.moveToNext()) {

 

                // 取得联系人的ID索引值

                String contactId =cur.getString(cur

                        .getColumnIndex(ContactsContract.Contacts._ID));

                if(contactId==null)

                {

                    contactId="No Id";

               

                }

                // 取得联系人的名字索引

                int nameIndex = cur.getColumnIndex(PhoneLookup.DISPLAY_NAME);

                String name =cur.getString(nameIndex);

                if(name==null)

                {

                    name="No name";

                }

                String rawContactsId = "";

                String id = cur.getString(cur

                        .getColumnIndex(ContactsContract.Contacts._ID));

 

                // str += "ID:" + id +"\n";二、对联系人的基本操作(4)

                // 读取rawContactsId

                Cursor rawContactsIdCur =cr.query(RawContacts.CONTENT_URI,

                        null, RawContacts.CONTACT_ID + " = ?",

                        new String[] { id }, null);

 

                // 该查询结果一般只返回一条记录,所以我们直接让游标指向第一条记录

                if (rawContactsIdCur.moveToFirst()) {

                    // 读取第一条记录的RawContacts._ID列的值

                    rawContactsId =rawContactsIdCur.getString(rawContactsIdCur

                            .getColumnIndex(RawContacts._ID));

                    deleted =rawContactsIdCur.getString(rawContactsIdCur

                            .getColumnIndex(RawContacts.DELETED));

                    version =rawContactsIdCur.getString(rawContactsIdCur

                            .getColumnIndex(RawContacts.VERSION));

                }

                rawContactsIdCur.close();

                // 读取号码

                Cursor PhoneCur = cr.query(

                        ContactsContract.CommonDataKinds.Phone.CONTENT_URI,

                        null,

                        ContactsContract.CommonDataKinds.Phone.RAW_CONTACT_ID

                                + " =?", new String[] { rawContactsId }, null);

                // 上面的ContactsContract.CommonDataKinds.Phone.CONTENT_URI

                // 可以用下面的phoneUri代替

                // Uri

                // phoneUri=Uri.parse("content://com.android.contacts/data/phones");

                // 二、对联系人的基本操作(6)

 

                // 一个联系人可能有多个号码,需要遍历

                if(!PhoneCur.moveToNext())

                {

                    //获取电话号码为空的情况即游标未找到的情况

                    String  number="No number";

                    // // 获取号码类型

                    Map<String, Object>map = new HashMap<String, Object>();

                    map.put("phone", number + ",");

                    map.put("name", name + "|");

                    map.put("version", version + ",");

                    map.put("deleted", deleted + ",");

                    map.put("id", contactId + ",");

                    list.add(map);

                   

                }

                else

                {

                    // 号获取码

                    String number = PhoneCur

                            .getString(PhoneCur

                                    .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

               

                    // // 获取号码类型

                    Map<String, Object>map = new HashMap<String, Object>();

                    map.put("phone", number + ",");

                    map.put("name", name + "|");

                    map.put("version", version + ",");

                    map.put("deleted", deleted + ",");

                    map.put("id", contactId + ",");

                    list.add(map);

                }

                while (PhoneCur.moveToNext()) {

 

                    // 号获取码

                    String number = PhoneCur

                            .getString(PhoneCur

                                    .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

                    if(number==null)

                    {

                        number="No number";

                       

                    }

                    // // 获取号码类型

                    Map<String, Object>map = new HashMap<String, Object>();

                    map.put("phone", number + ",");

                    map.put("name", name + "|");

                    map.put("version", version + ",");

                    map.put("deleted", deleted + ",");

                    map.put("id", contactId + ",");

                    list.add(map);

                }

                PhoneCur.close();//关闭游标

            }

        }

        return list;

    }

}