android 联系人


1 查询所有会话记录
public static final Map<String,Session> loadSession(ContextWrapper cw)
    {
        Map<String,Session> mapSessionInfo = new HashMap<String,Session>();
        if(cw == null)
            return mapSessionInfo;
 
        String projection = " b.thread_id,b.address from sms b  group by b.address--";
        Cursor cursor1 = cw.getContentResolver().query(
                Uri.parse("content://sms/"),
                new String[] { projection }, null, null, null);
        String address = "";
        int id = 0;
        Map<Integer,String> mapIDToPhone = new HashMap<Integer,String>();
        if (cursor1 != null)
        {
            try
            {
                if (cursor1.moveToFirst())
                {
                    do{
                        id = cursor1.getInt(0);
                        address = cursor1.getString(1);
                        if (address.startsWith("+"))
                        {
                            address = address.substring(3);
                        }
                        mapIDToPhone.put(Integer.valueOf(id), address);
                    } while (cursor1.moveToNext());
 
                }
            }
            catch (Exception e)
            {
                FDebug.e(e.toString());
            }
            finally
            {
                cursor1.close();
            }
        }
 
        String[] ALL_THREADS_PROJECTION = { "_id", "date", "message_count",
                "recipient_ids", "snippet", "snippet_cs", "read", "error",
                "has_attachment" };
        Uri MMSSMS_FULL_CONVERSATION_URI = Uri
                .parse("content://mms-sms/conversations");
        Uri CONVERSATION_URI = MMSSMS_FULL_CONVERSATION_URI.buildUpon()
                .appendQueryParameter("simple", "true").build();
        Cursor cursor = cw.getContentResolver().query(CONVERSATION_URI,
                ALL_THREADS_PROJECTION, null, null, "message_count desc");
        if (cursor != null)
        {
            try
            {
                if (cursor.moveToFirst())
                {
                    do
                    {
                        Session session = new Session();
                        session.mId = (cursor.getInt(Session.ID));
                        session.mTime = cursor.getLong(Session.DATE);
                        session.mMessageCount = (cursor.getInt(Session.MESSAGE_COUNT));
                        session.mRead = (cursor.getInt(Session.READ));
                        session.mRecipiend_ids = (cursor.getString(Session.RECIPIENT_IDS));
                        session.mSnippe = (cursor.getString(Session.SNIPPET));
                        session.mSnippet_cs = (cursor.getLong(Session.SNIPPET_CS));
                        session.mType = (cursor.getInt(Session.TYPE));
 
                        String phone = mapIDToPhone.get(Integer.valueOf(session.mId));
                        if (phone != "" && mapSessionInfo.containsKey(phone) == false)
                            mapSessionInfo.put(phone, session);
                    } while (cursor.moveToNext());
                }
            }
            catch (Exception e)
            {
                FDebug.e(e.toString());
            }
            finally
            {
                cursor.close();
            }
        }
 
        return mapSessionInfo;
    }

2 查询一条通话记录

 public static final List<CallLogMessage> queryCallLogs(ContextWrapper cw)
    {
        List<CallLogMessage> calllogList = new ArrayList<CallLogMessage>();
        if (cw == null)
            return calllogList;
 
        String number = "";
        String name = "";
        int id = -1;
        int type = -1;
        long callTime = 0;
        long duration = 0;
        String[] projection = new String[] { CallLog.Calls._ID,
                CallLog.Calls.NUMBER, CallLog.Calls.CACHED_NAME,
                CallLog.Calls.TYPE, CallLog.Calls.DURATION, CallLog.Calls.DATE };
        Cursor cursor = cw.getContentResolver().query(
                CallLog.Calls.CONTENT_URI, projection, null, null,
                CallLog.Calls.DEFAULT_SORT_ORDER);
 
        if (cursor != null)
        {
            try
            {
                if (cursor.moveToFirst())
                {
                    do
                    {
                        id = cursor.getInt(0);
                        number = cursor.getString(1);
                        name = cursor.getString(2);
                        type = cursor.getInt(3);
                        duration = cursor.getLong(4);
                        callTime = cursor.getLong(5);
 
                        CallLogMessage calllog = new CallLogMessage();
                        calllog.setID(id);
                        calllog.setPhoneNumber(number);
                        calllog.setName(name);
                        calllog.setContentType(type);
                        calllog.setDuration(duration);
                        calllog.setTimeline(callTime);
                        calllogList.add(calllog);
 
                    } while (cursor.moveToNext());
                }
            }
            catch (Exception e)
            {
                FDebug.e(e.toString());
            }
            finally
            {
                cursor.close();
                projection = null;
            }
        }
 
        return calllogList;
    }

3 查询某一会话下的所有短信SMS

public static final List<UnifiedMessage> querySMSsFromDB(ContextWrapper cw,int threadId)
    {
        List<UnifiedMessage> listSMS = new ArrayList<UnifiedMessage>();
        if(null == cw || threadId < 0)
            return listSMS;
 
        final String SMS_URI_ALL   = "content://sms";
        String[] projection = new String[] { "_id", "address", "body", "date", "type" };  
        Uri uri = Uri.parse(SMS_URI_ALL);  
        Cursor cursor = cw.getContentResolver().query(uri, projection, "thread_id=?",  
                new String[] { Integer.toString(threadId) }, "date desc");
 
        if(cursor != null)
        {
            try
            {
                if (cursor.moveToFirst())
                {
                    do
                    {
                        int idColume = cursor.getColumnIndex("_id"); 
                        int phoneNumberColumn = cursor.getColumnIndex("address");
                        int smsBodyColumn = cursor.getColumnIndex("body");  
                        int dateColumn = cursor.getColumnIndex("date");  
                        int typeColumn = cursor.getColumnIndex("type");
 
                        SMSMessage smsMessage = new SMSMessage();
                        smsMessage.setID(cursor.getInt(idColume));
                        smsMessage.setPhoneNumber(cursor.getString(phoneNumberColumn));
                        smsMessage.setContent(cursor.getString(smsBodyColumn));
                        smsMessage.setTimeline(Long.parseLong(cursor.getString(dateColumn)));
                        smsMessage.setCategory(cursor.getInt(typeColumn));
                        listSMS.add(smsMessage);
 
                    } while (cursor.moveToNext());
                }
            }
            catch (Exception e)
            {
                FDebug.e(e.toString());
            }
            finally
            {
                cursor.close();
                projection = null;
            }
        }
        return listSMS;
    }

4 常用删除操作:删除SMS、MMS、CallLog、Conversion

 public static final int deleteSMSFromDB(ContextWrapper cw,int msgId)
    {
        if(cw == null || msgId < 0)
            return 0;
 
        int result = cw.getContentResolver().delete(Uri.parse("content://sms"), "_id=?",
                new String[] { String.valueOf(msgId) });
        return result;
    }
 
    public static final int deleteMMSFromDB(ContextWrapper cw,int msgId)
    {
        if(cw == null || msgId < 0)
            return 0;
 
        int result = cw.getContentResolver().delete(Uri.parse("content://mms"), "_id=?",
                new String[] { String.valueOf(msgId) });
        return result;
    }
 
    public static final int deleteCallLogFromDB(ContextWrapper cw,int calllogId)
    {
        if(cw == null || calllogId < 0)
            return 0;
 
        int result = cw.getContentResolver().delete(CallLog.Calls.CONTENT_URI, "_id=?",
                new String[] { String.valueOf(calllogId) });
        return result;
    }
 
    public static final int deleteConversionFromDB(ContextWrapper cw,int conversionId)
    {
        if(cw == null || conversionId < 0)
            return 0;
 
        Uri uri = Uri.parse("content://sms/conversations/" + conversionId);
 
        int result = cw.getContentResolver().delete(uri, null, null);
        return result;
    }

5.查询所有联系人

 public static final List<UnifiedContact> loadContactsFromDB(
            ContextWrapper cw)
    {
        List<UnifiedContact> contactList = new ArrayList<UnifiedContact>();
 
        if (cw == null)
        {
            return contactList;
        }
 
        Map<Long, String> mapPhoneNumbers = new HashMap<Long, String>();
        String[] phoneNumberProjection = new String[] {
                ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
                ContactsContract.CommonDataKinds.Phone.NUMBER,
                ContactsContract.Contacts.DISPLAY_NAME,
                ContactsContract.Contacts.PHOTO_ID };
 
        Cursor phonecursor = cw.getContentResolver().query(
                ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                phoneNumberProjection, null, null, "display_name asc");
        if (phonecursor != null)
        {
            Log.v("FlamingoService", "Contact Count(Has PhoneNumber) :"+phonecursor.getCount());
            try
            {
                while (phonecursor.moveToNext())
                {
                    long contactId = phonecursor.getLong(0);
                    String phoneNumber = phonecursor.getString(1);
                    if (phoneNumber.startsWith("+"))
                    {
                        phoneNumber = phoneNumber.substring(3);
                    }
                    String name = phonecursor.getString(2);
                    long photoid = phonecursor.getLong(3);
 
                    String otherNumber = "";
 
                    if (mapPhoneNumbers.containsKey(contactId))
                    {
                        phoneNumber = phoneNumber + ";"
                                + mapPhoneNumbers.get(contactId);
                        mapPhoneNumbers.put(contactId, phoneNumber);
 
                        phoneNumber = mapPhoneNumbers.get(Long
                                .valueOf(contactId));
                        if (phoneNumber.indexOf(";") > 0)
                        {
                            otherNumber = phoneNumber.substring(
                                    phoneNumber.indexOf(";") + 1,
                                    phoneNumber.length());
                            phoneNumber = phoneNumber.substring(0,
                                    phoneNumber.indexOf(";"));
                        }
                        for (UnifiedContact contact : contactList)
                        {
                            if (contact.getID() == contactId)
                            {
                                ((PhoneContact) contact)
                                        .setPhoneNumber(phoneNumber);
                                ((PhoneContact) contact)
                                        .setOtherPhoneNumber(otherNumber);
                                break;
                            }
                        }
                    }
                    else if (mapPhoneNumbers.containsKey(contactId) == false)
                    {
                        mapPhoneNumbers.put(contactId, phoneNumber);
 
                        PhoneContact contact = new PhoneContact();
                        contact.setID(contactId);
                        contact.setName(name);
                        contact.setPhoneNumber(phoneNumber);
                        contact.setOtherPhoneNumber(otherNumber);
                        contact.setAvatarID(photoid);
                        contactList.add(contact);
                    }
                }
            }
            catch (Exception e)
            {
                FDebug.e(e.toString());
            }
            finally
            {
                phonecursor.close();
                phoneNumberProjection = null;
            }
        }
 
        // 查询电话号码为空的联系人
        String[] projection = new String[] { ContactsContract.Contacts._ID,
                ContactsContract.Contacts.DISPLAY_NAME,
                ContactsContract.Contacts.PHOTO_ID };
        String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER + " = "
                + 0;
 
        Cursor cursor = cw.getContentResolver().query(
                ContactsContract.Contacts.CONTENT_URI, projection, selection,
                null, null);
 
        if (cursor != null)
        {
            try
            {
                while (cursor.moveToNext())
                {
                    PhoneContact contact = new PhoneContact();
                    contact.setID(cursor.getLong(0));
                    contact.setName(cursor.getString(1));
                    contact.setAvatarID(cursor.getLong(2));
                    contactList.add(contact);
                }
            }
            catch (Exception e)
            {
                FDebug.e(e.toString());
            }
            finally
            {
                cursor.close();
            }
        }
        return contactList;
    }


/**
* 获得收藏夹的联系人

*/
private void getKeepedContacts(){
Cursor cur = getContentResolver().query(  
                ContactsContract.Contacts.CONTENT_URI, null, ContactsContract.Contacts.STARRED + " =  1 " , null, null);  
        startManagingCursor(cur);  
        int num = cur.getCount();
        System.out.println(num + "");
        int count = 0;
        while (cur.moveToNext()) {  
         count ++;
   
            long id = cur.getLong(cur.getColumnIndex("_id"));  
            Cursor pcur = getContentResolver().query(  
                    ContactsContract.CommonDataKinds.Phone.CONTENT_URI,  
                    null,  
                    ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "="  
                            + Long.toString(id), null, null);  
   
            // 处理多个号码的情况  
            String phoneNumbers = "";  
            while (pcur.moveToNext()) {  
                String strPhoneNumber = pcur  
                        .getString(pcur  
                                .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));  
                phoneNumbers += strPhoneNumber + ":";  
            }  
            phoneNumbers += "\n";  
            pcur.close();
            String name = cur.getString(cur.getColumnIndex("display_name"));
            contactNameList.add(name);
            contactNumList.add(phoneNumbers);
        }  
        cur.close();
} 



 ContactsContract.RawContacts


long    _ID                 read-only        Row ID;update rather than to delete and re-insert it.
long    CONTACT_ID          read-only        ContactsContract.Contacts 中的ID
int     AGGREGATION_MODE    read/write       组合模式;值为AGGREGATION_MODE_DEFAULT, AGGREGATION_MODE_DISABLED 或AGGREGATION_MODE_SUSPENDED.
int     DELETED             read/write       删除标记;0 or 1;1has been marked for deletion.
int     TIMES_CONTACTED     read/write       已经联系次数
long    LAST_TIME_CONTACTED read/write       上次联系的时间戳
int     STARRED             read/write       特别友好的联系人;1 if favorite;0 otherwise
int     CUSTOM_RINGTONE     read/write       与该记录相关的手机铃声
int     SEND_TO_VOICEMAIL   read/write       当这个Raw来电时,是否转发的语言信箱;1是或0否
String  ACCOUNT_NAME        read/write-once  账号名
String  ACCOUNT_TYPE        read/write-once  账号密码
int     VERSION             read-only        版本;当列或相关数据修改是,将会自动修改
int     DIRTY               read/write       版本发生改变的标记;同步的 当Raw contact发生改变时,自动设为1(除 URI has the CALLER_IS_SYNCADAPTER外)


                          ContactsContract.Contacts


long    _ID                        read-only        Row ID.建议用LOOKUP_KEY代替
String  LOOKUP_KEY                 read-only        与提示如何找到特定联系的值
long    NAME_RAW_CONTACT_ID        read-only        
long    PNOTO_ID                   read-only        ContactsContract.Data table holding the photo. That row has the mime type CONTENT_ITEM_TYPE. 
String  DISPLAY_NAME_PRIMARY       read-only        联系人显示的名字
int     IN_VISIBLE_GROUP           read-only        这个联系人在UI中是否可见;
int     HAS_PHONE_NUMBER           read-only        该联系人否至少有一个手机号码
int     TIMES_CONTACTED            read-only        与该联系人联系的次数
long    LAST_TIME_CONTACTED        read/write       上次联系的时间戳
String  CUSTOM_RINGTONE            read/write       与联系人相关的铃声
int     STARRED                    read/write       是否是常用联系人
int     SEND_TO_VOICEMAIL          read/write       
int     CONTACT_PRESENCE           read-only        Contact IM presence status
String  CONTACT_STATUS             read-only        Contact's latest status update. Automatically computed as the latest of all constituent raw contacts' status updates.
long    CONTACT_STATUS_TIMESTAMP   read-only        插入或修改的最新时间
String  CONTACT_STATUS_RES_PACKAGE read-only        The package containing resources for this status: label and icon
long    CONTACT_STATUS_LABEL       read-only        The resource ID of the label describing the source of contact status, e.g. "Google Talk". This resource is scoped by the CONTACT_STATUS_RES_PACKAGE
long    CONTACT_STATUS_ICON        read-only        The resource ID of the label describing the source of contact status, e.g. "Google Talk". This resource is scoped by the CONTACT_STATUS_RES_PACKAGE.


                            ContactsContract.Data


long    _ID                         read-only        Row ID
String  MIMETYPE                    read/write-once  StructuredName.CONTENT_ITEM_TYPE ;Phone.CONTENT_ITEM_TYPE;Email.CONTENT_ITEM_TYPE ;Organization.CONTENT_ITEM_TYPE;Im.CONTENT_ITEM_TYPE ;Nickname.CONTENT_ITEM_TYPE ;Note.CONTENT_ITEM_TYPE;StructuredPostal.CONTENT_ITEM_TYPE;GroupMembership.CONTENT_ITEM_TYPE ;Website.CONTENT_ITEM_TYPE;Event.CONTENT_ITEM_TYPE ;Relation.CONTENT_ITEM_TYPE;
long    RAW_CONTACT_ID              read/write       The id of the row in the ContactsContract.RawContacts table that this data belongs to.
int     IS_PRIMARY                  read/write       Whether this is the primary entry of its kind for the raw contact it belongs to. "1" if true, "0" if false. 
int     IS_SUPER_PRIMARY            read/write       Whether this is the primary entry of its kind for the aggregate contact it belongs to. Any data record that is "super primary" must also be "primary". For example, the super-primary entry may be interpreted as the default contact value of its kind (for example, the default phone number to use for the contact).
                           

                             ContactsContract.Groups
long    _ID                         read/write       Row ID
String  TITLE                       read/write       The display title of this group
String  NOTE                        read/write       Notes about the group
int     SUMMARY_COUNT               read-only        The total number of Contacts that have ContactsContract.CommonDataKinds.GroupMembership in this group. Read-only value that is only present when querying CONTENT_SUMMARY_URI.
int     SUMMARY_WITH_PHONES         read-only        The total number of Contacts that have both ContactsContract.CommonDataKinds.GroupMembership in this group, and also have phone numbers. Read-only value that is only present when querying CONTENT_SUMMARY_URI.
int     GROUP_VISIBLE               read-only        群组是否在数据库中可见1 or 0
int     DELETED                     read/write       删除标记 0,default;1 if the row has been marked for deletion
int     SHOULD_SYNC                 read/write       Whether this group should be synced if the SYNC_EVERYTHING settings is false for this group's account.


与联系人相关的操作
insert   
         data 
              ContentValues values = new ContentValues(); values.put(Data.RAW_CONTACT_ID, rawContactId); values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); values.put(Phone.NUMBER, "1-800-GOOG-411"); values.put(Phone.TYPE, Phone.TYPE_CUSTOM); values.put(Phone.LABEL, "free directory assistance"); Uri dataUri = getContentResolver().insert(Data.CONTENT_URI, values);   followed are same
              ArrayList<ContentProviderOperation> ops = Lists.newArrayList(); ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI).withValue(Data.RAW_CONTACT_ID, rawContactId).withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE).withValue(Phone.NUMBER, "1-800-GOOG-411").withValue(Phone.TYPE, Phone.TYPE_CUSTOM).withValue(Phone.LABEL, "free directory assistance").build()); getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); 
        ContactsContract.RawContacts
              ContentValues values = new ContentValues(); values.put(RawContacts.ACCOUNT_TYPE, accountType); values.put(RawContacts.ACCOUNT_NAME, accountName); Uri rawContactUri = getContentResolver().insert(RawContacts.CONTENT_URI, values); long rawContactId = ContentUris.parseId(rawContactUri);
              Once ContactsContract.RawContacts.Data values become available, insert those. For example, here's how you would insert a name:
                 values.clear(); values.put(Data.RAW_CONTACT_ID, rawContactId); values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); values.put(StructuredName.DISPLAY_NAME, "Mike Sullivan"); getContentResolver().insert(Data.CONTENT_URI, values);
              ArrayList<ContentProviderOperation> ops = Lists.newArrayList(); ... int rawContactInsertIndex = ops.size(); ops.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)          .withValue(RawContacts.ACCOUNT_TYPE, accountType)          .withValue(RawContacts.ACCOUNT_NAME, accountName)          .build()); ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI)          .withValueBackReference(Data.RAW_CONTACT_ID, rawContactInsertIndex)          .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)          .withValue(StructuredName.DISPLAY_NAME, "Mike Sullivan")          .build()); getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);

update
          data

             ArrayList<ContentProviderOperation> ops = Lists.newArrayList(); ops.add(ContentProviderOperation.newUpdate(Data.CONTENT_URI).withSelection(Data._ID + "=?", new String[]{String.valueOf(dataId)}).withValue(Email.DATA, "somebody@android.com").build()); getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);

        
delete   
          data   
             ArrayList<ContentProviderOperation> ops = Lists.newArrayList(); ops.add(ContentProviderOperation.newDelete(Data.CONTENT_URI).withSelection(Data._ID + "=?", new String[]{String.valueOf(dataId)}).build()); getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);

   
query 
         data      
             Cursor c = getContentResolver().query(Data.CONTENT_URI,new String[] {Data._ID, Phone.NUMBER, Phone.TYPE, Phone.LABEL},Data.RAW_CONTACT_ID + "=?" + " AND "+ Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'", new String[] {String.valueOf(rawContactId)}, null);
         ContactsContract.RawContactsEntity
              Uri entityUri = ContentUris.withAppendedId(RawContactsEntity.CONTENT_URI, rawContactId); Cursor c = getContentResolver().query(entityUri,          new String[]{              RawContactsEntity.SOURCE_ID,              RawContactsEntity.DATA_ID,              RawContactsEntity.MIMETYPE,              RawContactsEntity.DATA1          }, null, null, null); try {     while (c.moveToNext()) {         String sourceId = c.getString(0);         if (!c.isNull(1)) {             String mimeType = c.getString(2);             String data = c.getString(3);             ...         }     } } finally {     c.close(); } 
          
         ContactsContract.RawContacts
             all raw contacts in a Contact:Cursor c = getContentResolver().query(RawContacts.CONTENT_URI,          new String[]{RawContacts._ID},          RawContacts.CONTACT_ID + "=?",          new String[]{String.valueOf(contactId)}, null); 
             To find raw contacts within a specific account, you can either put the account name ....:Uri rawContactUri = RawContacts.URI.buildUpon()          .appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName)          .appendQueryParameter(RawContacts.ACCOUNT_TYPE, accountType)          .build(); Cursor c1 = getContentResolver().query(rawContactUri,          RawContacts.STARRED + "<>0", null, null, null); ... Cursor c2 = getContentResolver().query(rawContactUri,          RawContacts.DELETED + "<>0", null, null, null);
             best for read a raw contact along with all the data associated with: Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId); Uri entityUri = Uri.withAppendedPath(rawContactUri, Entity.CONTENT_DIRECTORY); Cursor c = getContentResolver().query(entityUri,          new String[]{RawContacts.SOURCE_ID, Entity.DATA_ID, Entity.MIMETYPE, Entity.DATA1},          null, null, null); try {     while (c.moveToNext()) {         String sourceId = c.getString(0);         if (!c.isNull(1)) {             String mimeType = c.getString(2);             String data = c.getString(3);             ...         }     } } finally {     c.close(); }






 public static final class
ContactsContract.RawContacts
extends Object
implements BaseColumns ContactsContract.ContactOptionsColumns ContactsContract.RawContactsColumns ContactsContract.SyncColumns
java.lang.Object
        android.provider.ContactsContract.RawContacts
Class Overview
    Constants for the raw contacts table, 
    which contains one row of contact information for each person in each synced account. 

raw contact就对应一个联系人
Sync adapters and contact management apps are the primary consumers of this API. 
Aggregation
    As soon as a raw contact is inserted or whenever its constituent data changes, 
    the provider will check if the raw contact matches other existing raw contacts and if so will aggregate it with those. 
    The aggregation is reflected in the ContactsContract.RawContacts table by the change of the CONTACT_ID field, 
    which is the reference to the aggregate contact.
    Changes to the structured name, organization, phone number, email address, or nickname trigger a re-aggregation. 
参照Contact类的描述
    A Contact cannot be created explicitly.
     When a raw contact is inserted, the provider will first try to find a Contact representing the same person. 
     If one is found, the raw contact's CONTACT_ID column gets the _ID of the aggregate Contact
     . If no match is found, the provider automatically inserts a new Contact and puts its _ID into the CONTACT_ID column of the newly inserted raw contact.
大概可以得出raw contact和组(contact)的匹配过程
    当raw contact被插入或时,系统就会检查是否可以把该raw contact加到已经有的组(contact)。
    如果找到可以加入的组,就把组ID写到raw contact的CONTACT_ID这个数据项中。
    如果没找到就由系统重新创建一组,并把组ID写到raw contact的CONTACT_ID这个数据项中。
    如果raw contact的structured name, organization, phone number, email address, or nickname被改变。
    
    系统就会检查raw contact是否还属于raw contact的CONTACT_ID标记的那个组。
    如果发现raw contact不属于raw contact的CONTACT_ID标记的那个组。
    那么系统就会找是否可以把该raw contact加到已经有的其他组(contact)
    如果找到可以加入的组,就把组ID写到raw contact的CONTACT_ID这个数据项中。
    如果没找到就由系统重新创建一组,并把组ID写到raw contact的CONTACT_ID这个数据项中。
    注意:这的组是指contact(Aggregation of raw contact)
    关于分组机制的编程可参考类ContactsContract.AggregationExceptions.
一个raw contact的信息主要由主表(raw contact类声明的数据列),多项子表数据ContactsContract.Data来进行表示
子表数据可以通过设置MIMETYPE项的值来表示多种类型的数据
比如通过设置MIMETYPE项为StructuredName.CONTENT_ITEM_TYPE来说明是StructuredName数据。
当然对于DATA1~DATA15也要按照StructuredName中定义的数据格式来写入数据。
子表数据可以是
    *  StructuredName.CONTENT_ITEM_TYPE
    * Phone.CONTENT_ITEM_TYPE
    * Email.CONTENT_ITEM_TYPE
    * Photo.CONTENT_ITEM_TYPE
    * Organization.CONTENT_ITEM_TYPE
    * Im.CONTENT_ITEM_TYPE
    * Nickname.CONTENT_ITEM_TYPE
    * Note.CONTENT_ITEM_TYPE
    * StructuredPostal.CONTENT_ITEM_TYPE
    * GroupMembership.CONTENT_ITEM_TYPE
    * Website.CONTENT_ITEM_TYPE
    * Event.CONTENT_ITEM_TYPE
    * Relation.CONTENT_ITEM_TYPE

:关于子表每种类型的具体数据格式都android.provider.ContactsContract. CommonDataKinds包中相关类找到说明。比如Email是在CommonDataKinds.Email中.
主表数据共18项
变量名                                列名                                备注
 _ID                                _id                                    这个就是 raw_contact_id
 CONTACT_ID                        contact_id
 AGGREGATION_MODE                  aggregation_mode                        分组模式
 DELETED                               deleted                                是否已经被删除
 TIMES_CONTACTED                times_contacted
 LAST_TIME_CONTACTED            last_time_contacted
 STARRED                            starred
 CUSTOM_RINGTONE                    custom_ringtone   来电铃声的Url
 SEND_TO_VOICEMAIL                    send_to_voicemail
 ACCOUNT_NAME                        account_name
 ACCOUNT_TYPE                        account_type
 SOURCE_ID                            sourceid
 VERSION                            version
 DIRTY                                dirty
 SYNC1~SYNC1                        sync1~sync2
  注意1: _ID就是 raw_contact_id
 注意2:当我们查询时,通常是查询没有删除的联系人。所以要加上条件RawContacts.DELETED==0:
 RawContacts.DELETED + "=?", new String[] {String.valueOf(0)}
  注意3:主表中没有名字的信息.名字在子表StructuredName中。
子表数据共有25项
变量名                            列名                                备注
 _ID                              _id       
 MIMETYPE                        mimetype
  RAW_CONTACT_ID                     raw_contact_id
 IS_PRIMARY                        is_primary
 IS_SUPER_PRIMARY                is_super_primary
 DATA_VERSION                    data_version
 DATA1~DATA15                    data1~data15
 SYNC1~SYNC4                    data_sync1~data_sync4一,数据插入可以参考《 raw contact数据插入 》
二,数据查询可以参考《rawContact数据查询 》
三,数据更新

    final int        update(Uri  uri, ContentValues  values, String  where, String[]  selectionArgs)
    Update row(s) in a content URI.
    其使用很简单。
    ContentValues  values可以参考《 rawContact数据插入 》
    String  where, String[]  selectionArgs可以参考《 rawContact数据查询 》
    主表更新也可以用批量进行
     Raw contacts can be updated incrementally or in a batch.
    Batch mode should be used whenever possible. 
    The procedures and considerations are analogous to those documented above for inserts. 
    子表更新也可以用批量进行
    Just as with insert, update can be done incrementally or as a batch, the batch mode being the preferred method:
     ArrayList<ContentProviderOperation> ops = Lists.newArrayList();
     ops.add(ContentProviderOperation.newUpdate(Data.CONTENT_URI)
              .withSelection(Data._ID + "=?", new String[]{String.valueOf(dataId)})
              .withValue(Email.DATA, "somebody@android.com")
              .build());
     getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);

四,数据删除
     主表删除
        getContentResolver().delete(RawContacts.CONTENT_URI, null, null);
         注意:这里会除了会删除主表,也会把相应的子表删除掉。
     子表删除
         getContentResolver().delete(Data.CONTENT_URI, null, null)
     也可以批量删除
        Just as with insert and update, deletion can be done either using the delete(Uri, String, String[]) method 
        or using a ContentProviderOperation:
         ArrayList<ContentProviderOperation> ops = Lists.newArrayList();
         ops.add(ContentProviderOperation.newDelete(Data.CONTENT_URI)
                  .withSelection(Data._ID + "=?", new String[]{String.valueOf(dataId)})
                  .build());
         getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);




1. 删除通话记录

 

2.

       负责存放呼叫记录的内容提供者源码在 ContactsProvider 项目下:

       源码路径:

       com\android\providers\contacts\CallLogProvider.java

      

       使用到的数据库在:

       /data/data/com.android.providers.contacts/databases/contacts2.db

       表名:calls

      

       呼叫记录有三种类型:

       来电:CallLog.Calls.INCOMING_TYPE (常量值:1)

       已拨:CallLog.Calls.OUTGOING_TYPE(常量值:2)

       未接:CallLog.Calls.MISSED_TYPE(常量值:3)

      

       查看源码中的声明:

              <provider android:name="CallLogProvider"

                   android:authorities="call_log"

                   android:syncable="false" android:multiprocess="false"

                   android:readPermission="android.permission.READ_CONTACTS"

                   android:writePermission="android.permission.WRITE_CONTACTS">

               </provider>

3.需要声明的权限

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

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

 

4. 系统的通话记录,是通过 ContentProvider 来对外共享的

 

5. Uri

       CallLog.Calls.CONTENT_URI : 等价于:Uri.parse("content://call_log/calls");

6. 查询出所有记录

       ContentResolver resolver = getContentResolver();

       resolver.query(CallLog.Calls.CONTENT_URI, null, null, new String[]{"15101689022"}, null);

      

7. 查询某一个联系人的所有记录(按电话号码)

       resolver.query(CallLog.Calls.CONTENT_URI, null, "number=?", new String[]{"15101689022"}, null);

 

8. 查询某一个联系人的所有未接电话记录(按电话号码)

       resolver.query(CallLog.Calls.CONTENT_URI, null, "number=? and type=3", new String[]{"15101689022"}, null);

8. 删除某联系人最近的一次来电

       
view plaincopy to clipboardprint?
01./* 本代码因为在 Activity 中,所以可以直接调用 getContentResolver()。这个方法实际上是 Context 中定义的。 */  
02.ContentResolver resolver = getContentResolver();   
03./* 这里涉及到内容提供者的知识,其实这里是直接在操作 Android 的数据库,十分痛苦 */  
04.Cursor cursor = resolver.query(CallLog.Calls.CONTENT_URI, new String[]{"_id"}, "number=? and (type=1 or type=3)",  new String[]{"15101689022"},  "_id desc limit 1");   
05.if(cursor.moveToFirst()) {   
06.    int id = cursor.getInt(0);   
07.    resolver.delete(CallLog.Calls.CONTENT_URI, "_id=?", new String[] {id + ""});   
08.} 


 

2.

       负责存放呼叫记录的内容提供者源码在 ContactsProvider 项目下:

       源码路径:

       com\android\providers\contacts\CallLogProvider.java

      

       使用到的数据库在:

       /data/data/com.android.providers.contacts/databases/contacts2.db

       表名:calls

      

       呼叫记录有三种类型:

       来电:CallLog.Calls.INCOMING_TYPE (常量值:1)

       已拨:CallLog.Calls.OUTGOING_TYPE(常量值:2)

       未接:CallLog.Calls.MISSED_TYPE(常量值:3)

      

       查看源码中的声明:

              <provider android:name="CallLogProvider"

                   android:authorities="call_log"

                   android:syncable="false" android:multiprocess="false"

                   android:readPermission="android.permission.READ_CONTACTS"

                   android:writePermission="android.permission.WRITE_CONTACTS">

               </provider>

3.需要声明的权限

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

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

 

4. 系统的通话记录,是通过 ContentProvider 来对外共享的

 

5. Uri

       CallLog.Calls.CONTENT_URI : 等价于:Uri.parse("content://call_log/calls");

6. 查询出所有记录

       ContentResolver resolver = getContentResolver();

       resolver.query(CallLog.Calls.CONTENT_URI, null, null, new String[]{"15101689022"}, null);

      

7. 查询某一个联系人的所有记录(按电话号码)

       resolver.query(CallLog.Calls.CONTENT_URI, null, "number=?", new String[]{"15101689022"}, null);

 

8. 查询某一个联系人的所有未接电话记录(按电话号码)

       resolver.query(CallLog.Calls.CONTENT_URI, null, "number=? and type=3", new String[]{"15101689022"}, null);

8. 删除某联系人最近的一次来电

       
view plaincopy to clipboardprint?
01./* 本代码因为在 Activity 中,所以可以直接调用 getContentResolver()。这个方法实际上是 Context 中定义的。 */  
02.ContentResolver resolver = getContentResolver();   
03./* 这里涉及到内容提供者的知识,其实这里是直接在操作 Android 的数据库,十分痛苦 */  
04.Cursor cursor = resolver.query(CallLog.Calls.CONTENT_URI, new String[]{"_id"}, "number=? and (type=1 or type=3)",  new String[]{"15101689022"},  "_id desc limit 1");   
05.if(cursor.moveToFirst()) {   
06.    int id = cursor.getInt(0);   
07.    resolver.delete(CallLog.Calls.CONTENT_URI, "_id=?", new String[] {id + ""});   
08.} 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值