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
主表数据共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.}