【Android ContentProvider 一】关于ContactsContract.CommonDataKinds.Phone.CONTENT_URI的一点理解
来源:互联网 发布:linux脚本怎么写 编辑:程序博客网 时间:2024/05/22 07:50
一切都要从ContactsContract.CommonDataKinds.Phone.CONTENT_URI说起。
前两天在学习Google官方培训课程中的《Android联系人信息与位置信息》部分时,始终没有理解到getActivity().getContentResolver().query(Uri uri,
方法中uri这个参数的使用,当时很傻逼的认为搜索电话号码不就是将uri赋值为
String[] projection, String selection,String[] selectionArgs, String sortOrder)ContactsContract.Contacts.CONTENT_URI
搜索,结果发现Contacts中只有一个HAS_PHONE_NUMBER
参数,之后搜索发现URI有很多种,比如
ContactsContract.CommonDataKinds.Phone.CONTENT_URI
ContactsContract.Data.CONTENT_URI
ContactsContract.RawContacts.CONTENT_URI
因为对uri参数不熟悉的原因,同时发现ContactsContract联想出来的类很多,参数也很多,然后开始各种胡乱尝试uri,比如ContactsContract.CommonDataKinds.Phone.NUMBER
,结果不出所料的程序开始疯狂崩溃。。。
然后我开始重新学习了下联系人数据库contacts2.db、ContentResolver.query()中uri、uri等于ContactsContract.CommonDataKinds.Phone.CONTENT_URI时,ContactsProvider是怎样工作的。
先了解到关于联系人数据库重要的有以下几个表:
1. contacts
2. raw_contacts
3. data
4. mimetypes
当把getContentResolver().query()方法中的uri参数赋值为ContactsContract.CommonDataKinds.Phone.CONTENT_URI查找联系人数据时,实际上是在对data表进行查找。直接从ContactsProvider接口中ContactsProvider2类的query()方法看起。
随着query()方法一步步往下走:
ContactsProvider2.java
@Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { //第一步:直接return query() return query(uri, projection, selection, selectionArgs, sortOrder, null); } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal) { if (mapsToProfileDb(uri)) { switchToProfileMode(); //第二步:return mProfileProvider.query() return mProfileProvider.query(uri, projection, selection, selectionArgs, sortOrder, cancellationSignal); }} @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal) { incrementStats(mQueryStats); try { //第三步:mDelegate.queryLocal(),这个方法就是关键了 return mDelegate.queryLocal(uri, projection, selection, selectionArgs, sortOrder, -1, cancellationSignal); } finally { finishOperation(); } }
queryLocal()方法中根据sUriMatcher.match()所返回的code值,在switch语句中进行了匹配处理工作,而在开始的时候sUriMatcher有addURI,所以可以知道ContactsContract.CommonDataKinds.Phone.CONTENT_URI对应的code就是PHONES
ContactsProvider2.java
static { // Contacts URI matching table final UriMatcher matcher = sUriMatcher; matcher.addURI(ContactsContract.AUTHORITY, "data", DATA); matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID); matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES); matcher.addURI(ContactsContract.AUTHORITY, "data_enterprise/phones", PHONES_ENTERPRISE); matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID); matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER);}
所以在queryLocal()方法中进入case PHONES:
ContactsProvider2.java
final int match = sUriMatcher.match(uri);switch(match){ //此处省略...... case PHONES: //在mimetypes表中找Phone的MIME类型ID值 final String mimeTypeIsPhoneExpression = DataColumns.MIMETYPE_ID + "=" + mDbHelper.get().getMimeTypeIdForPhone(); final String mimeTypeIsSipExpression = DataColumns.MIMETYPE_ID + "=" + mDbHelper.get().getMimeTypeIdForSip(); setTablesAndProjectionMapForData(qb, uri, projection, false); if (match == CALLABLES) { qb.appendWhere(" AND ((" + mimeTypeIsPhoneExpression + ") OR (" + mimeTypeIsSipExpression + "))"); } else { //match=PHONES,将 _id = 1作为查询条件添加到where语句中 qb.appendWhere(" AND " + mimeTypeIsPhoneExpression); } final boolean removeDuplicates = readBooleanQueryParameter( uri, ContactsContract.REMOVE_DUPLICATE_ENTRIES, false); if (removeDuplicates) { groupBy = RawContacts.CONTACT_ID + ", " + Data.DATA1; addressBookIndexerCountExpression = "DISTINCT " + RawContacts.CONTACT_ID + "||','||" + Data.DATA1; } break; } qb.setStrict(true); // Auto-rewrite SORT_KEY_{PRIMARY, ALTERNATIVE} sort orders. String localizedSortOrder = getLocalizedSortOrder(sortOrder); Cursor cursor = doQuery(db, qb, projection, selection, selectionArgs, localizedSortOrder, groupBy, having, limit, cancellationSignal); if (readBooleanQueryParameter(uri, Contacts.EXTRA_ADDRESS_BOOK_INDEX, false)) { bundleFastScrollingIndexExtras(cursor, uri, db, qb, selection, selectionArgs, sortOrder, addressBookIndexerCountExpression, cancellationSignal); } if (snippetDeferred) { cursor = addDeferredSnippetingExtra(cursor); } return cursor;}
通过getMimeTypeIdForPhone()方法在mimetypes表中根据vnd.android.cursor.item/phone_v2类型来找到Phone对应的_ID,添加到查找的where语句中,最后返回一个cusor
总结:
当使用ContactsContract.CommonDataKinds.Phone.CONTENT_URI作为uri的参数查找联系人时,实际上默认查找条件已经变成了在data表中mimetype_id = 1(即类型为vnd.android.cursor.item/phone_v2)的结果集里面查找。这时候再在query()方法里添加自己自定义的projection、selection、selectionArgs,就能在电话号码结果集中搜索到自己想要的结果了。
- 【Android ContentProvider 一】关于ContactsContract.CommonDataKinds.Phone.CONTENT_URI的一点理解
- ContactsContract.Contacts与ContactsContract.CommonDataKinds.Phone的区别
- ContactsContract.Contacts.CONTENT_URI无法获取手机号码
- Android中关于ContentProvider类的getType()方法的理解
- 关于android的contentProvider
- 关于ContactsContract
- Android的ContentProvider(一)
- 对ContentProvider中getType方法的一点理解
- 关于ContentProvider的理解与简单应用
- 关于contentProvider和ContentResolver的个人理解
- 关于Android Webkit的Flash插件加载的一点理解
- 关于android 和 耗时操作的一点理解
- 关于Android中View滑动知识的一点个人理解
- 关于android触摸事件传递机制的一点理解
- 关于StrutsFormBean 的一点理解
- 关于Action的一点理解
- 关于闪光灯的一点理解
- 关于fourcc的一点理解
- IT与风投
- ztree同步加载数据
- 锐浪报表,子报表没数据的原因
- 获取Linux系统信息
- 2017 icpc Southeast USA D 题 Gym
- 【Android ContentProvider 一】关于ContactsContract.CommonDataKinds.Phone.CONTENT_URI的一点理解
- CorelDRAW X6经典不会重演
- network中的weight initialization
- 剑指offer—数据流中的中位数
- Mac OSX Eclipse SVN插件问题
- 一些学习linux network的网络链接资料
- 2017年最赚钱项目,谁做谁发财!
- 工厂方法模式的简单使用
- ubuntu安装python Django