创建自己的内容提供器
如果想要實(shí)現(xiàn)跨程序共享數(shù)據(jù)的功能,官方推薦的方式就是使用內(nèi)容提供器,可以通過新建一個(gè)類去繼承ContentProvider的方式來創(chuàng)建一個(gè)自己的內(nèi)容提供器。ContentProvider類中有6個(gè)抽象方法,我們?cè)谑褂米宇惱^承它的時(shí)候,需要將這6個(gè)方法全部重寫。新建MyProvider繼承自ContentProvider,代碼如下所示:
package com.example.administrator.contactstest;import android.content.ContentProvider; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri;public class MyProvider extends ContentProvider {@Overridepublic boolean onCreate() {return false;}@Overridepublic Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {return null;}@Overridepublic String getType(Uri uri) {return null;}@Overridepublic Uri insert(Uri uri, ContentValues values) {return null;}@Overridepublic int delete(Uri uri, String selection, String[] selectionArgs) {return 0;}@Overridepublic int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {return 0;} }1.onCreate():初始化內(nèi)容提供器的時(shí)候調(diào)用。通常會(huì)在這里完成對(duì)數(shù)據(jù)的創(chuàng)建和升級(jí)等操作,返回true表示內(nèi)容提供器初始化成功,返回false則表示失敗。
2.query():從內(nèi)容提供器中查詢數(shù)據(jù)。使用uri參數(shù)來確定查詢哪張表,projection參數(shù)用于確定查詢哪些列,selection和selectionArgs參數(shù)用于約束查詢哪些行,sortOrder參數(shù)用于對(duì)結(jié)果進(jìn)行排序,查詢的結(jié)果存放在Cursor對(duì)象中返回。
3.insert():向內(nèi)容提供器中添加一條數(shù)據(jù)。使用uri參數(shù)來確定要添加到的表,待添加的數(shù)據(jù)保存在values參數(shù)中。添加完成后,返回一個(gè)用于表示這條新記錄的URL。
4.update():更新內(nèi)容提供器中已有的數(shù)據(jù)。使用uri參數(shù)來確定更新哪一張表中的數(shù)據(jù),新數(shù)據(jù)保存在values參數(shù)中,selection和selectionArgs參數(shù)用于約束更新哪些行,受影響的行數(shù)將作為返回值返回。
5.delete():從內(nèi)容提供器中刪除數(shù)據(jù)。使用uri參數(shù)來確定刪除哪一張表中的數(shù)據(jù),selection和selectionArgs參數(shù)用于約束刪除哪行,被刪除的行將作為返回值返回。
6.getType():
根據(jù)傳入的內(nèi)容URI來返回相應(yīng)的MIME類型。
?
匹配任意表的內(nèi)容URI格式:
content://com.example.app.provider/*
匹配table表中的任意一行數(shù)據(jù)的內(nèi)容URI格式:
content://com.example.app.provider/table/#
我們需要使用UriMatcher類來實(shí)現(xiàn)匹配內(nèi)容URI的功能,UriMatcher類中提供了一個(gè)addURI()方法,這個(gè)方法接收3個(gè)參數(shù),可以分別把a(bǔ)uthority、path和自定義int類型標(biāo)識(shí)符傳進(jìn)去。這樣,當(dāng)調(diào)用UriMatcher的match()方法時(shí),就可以將一個(gè)uri對(duì)象傳入,返回值是某個(gè)可以匹配這個(gè)uri對(duì)象所對(duì)應(yīng)的int類型標(biāo)識(shí)符(也就是addURI()方法中的第三個(gè)參數(shù)),利用該int類型標(biāo)識(shí)符,我們就可以判斷出調(diào)用方期望訪問的是哪張表中的數(shù)據(jù)了。
修改MainActivity.java代碼:
package com.example.administrator.contactstest;import android.content.ContentProvider; import android.content.ContentValues; import android.content.UriMatcher; import android.database.Cursor; import android.net.Uri;public class MyProvider extends ContentProvider {public static final int TABLE1_DIR = 0;//table1表中的所有數(shù)據(jù)public static final int TABLE1_ITEM = 1;//table1表中的單條數(shù)據(jù)public static final int TABLE2_DIR = 2;//table2表中的所有數(shù)據(jù)public static final int TABLE2_ITEM = 3;//table2表中的單條數(shù)據(jù)public static UriMatcher uriMatcher;//聲明uri匹配類對(duì)象static {uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);//實(shí)例化uri匹配類對(duì)象//向UriMatcher中添加內(nèi)容URIuriMatcher.addURI("com.example.app.provider", "table1", TABLE1_DIR);uriMatcher.addURI("com.example.app.provider", "table1/#", TABLE1_ITEM);uriMatcher.addURI("com.example.app.provider", "table2", TABLE2_DIR);uriMatcher.addURI("com.example.app.provider", "table2/#", TABLE2_ITEM);}@Overridepublic boolean onCreate() {return false;}@Overridepublic Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {switch (uriMatcher.match(uri)) {case TABLE1_DIR://查詢table1表中的所有數(shù)據(jù)break;case TABLE1_ITEM://查詢table1表中的單條數(shù)據(jù)break;case TABLE2_DIR://查詢table2表中的所有數(shù)據(jù)break;case TABLE2_ITEM://查詢table2表中的單條數(shù)據(jù)break;default:break;}return null;}return null;}@Overridepublic String getType(Uri uri) {return null;}@Overridepublic Uri insert(Uri uri, ContentValues values) {return null;}@Overridepublic int delete(Uri uri, String selection, String[] selectionArgs) {return 0;}@Overridepublic int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {return 0;} }這里再講一下getType()方法,它是所有的內(nèi)容提供器都必須提供的一個(gè)方法,用于獲取Uri對(duì)象所對(duì)應(yīng)的MIME類型。一個(gè)內(nèi)容URI所對(duì)應(yīng)的MIME字符串主要由3部分組成,Android對(duì)這3部分做了如下格式規(guī)定:
1.必須以vnd開頭
2.如果內(nèi)容URI以路徑結(jié)尾,則在vnd后面加上android.cursor.dir/,如果以id結(jié)尾,則在vnd后面加上android.cursor.item/
3.最后接上vnd.<authority>.<path>
所以,對(duì)于content://com.example.app.provider/table1這個(gè)內(nèi)容URI,它所對(duì)應(yīng)的MIME類型就可以寫成:
vnd.android.cursor.dir/vnd.com.example.app.provider.table1
對(duì)于content://com.example.app.provider/table1/1這個(gè)內(nèi)容URI,它所對(duì)應(yīng)的MIME類型就可以寫成:
vnd.android.cursor.item/vnd.com.example.app.provider.table1
ManiActivity.java代碼:
package com.example.administrator.contactstest;import android.content.ContentProvider; import android.content.ContentValues; import android.content.UriMatcher; import android.database.Cursor; import android.net.Uri;public class MyProvider extends ContentProvider {public static final int TABLE1_DIR = 0;//table1表中的所有數(shù)據(jù)public static final int TABLE1_ITEM = 1;//table1表中的單條數(shù)據(jù)public static final int TABLE2_DIR = 2;//table2表中的所有數(shù)據(jù)public static final int TABLE2_ITEM = 3;//table2表中的單條數(shù)據(jù)public static UriMatcher uriMatcher;//聲明uri匹配類對(duì)象static {uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);//實(shí)例化uri匹配類對(duì)象//向UriMatcher中添加內(nèi)容URIuriMatcher.addURI("com.example.app.provider", "table1", TABLE1_DIR);uriMatcher.addURI("com.example.app.provider", "table1/#", TABLE1_ITEM);uriMatcher.addURI("com.example.app.provider", "table2", TABLE2_DIR);uriMatcher.addURI("com.example.app.provider", "table2/#", TABLE2_ITEM);}@Overridepublic boolean onCreate() {return false;}@Overridepublic Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {switch (uriMatcher.match(uri)) {case TABLE1_DIR://查詢table1表中的所有數(shù)據(jù)break;case TABLE1_ITEM://查詢table1表中的單條數(shù)據(jù)break;case TABLE2_DIR://查詢table2表中的所有數(shù)據(jù)break;case TABLE2_ITEM://查詢table2表中的單條數(shù)據(jù)break;default:break;}return null;}@Overridepublic String getType(Uri uri) {switch (uriMatcher.match(uri)) {case TABLE1_DIR:return "vnd.android.cursor.dir/vnd.com.example.app.provider.table1";case TABLE1_ITEM:return "vnd.android.cursor.item/vnd.com.example.app.provider.table1";case TABLE2_DIR:return "vnd.android.cursor.dir/vnd.com.example.app.provider.table2";case TABLE2_ITEM:return "vnd.android.cursor.item/vnd.com.example.app.provider.table2";default:break;}return null;}@Overridepublic Uri insert(Uri uri, ContentValues values) {return null;}@Overridepublic int delete(Uri uri, String selection, String[] selectionArgs) {return 0;}@Overridepublic int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {return 0;} }到這里,一個(gè)完整的內(nèi)容提供器就創(chuàng)建成功了,現(xiàn)在任何一個(gè)應(yīng)用程序都可以使用ContentResolver來訪問我們程序中的數(shù)據(jù)。那么前面所提到的,如何才能保證隱私數(shù)據(jù)不會(huì)泄露出去呢?其實(shí)多虧了內(nèi)容提供器的良好機(jī)制,這個(gè)問題在不知不覺中被解決了。因?yàn)樗械腃RUD操作都需要匹配到相應(yīng)的內(nèi)容URI,而這些內(nèi)容URI都是需要我們自主的往UriMatcher中添加的,我們當(dāng)然不會(huì)主動(dòng)將一些隱私數(shù)據(jù)的URI添加到UriMatcher中,所以隱私的數(shù)據(jù)外界是無法訪問到的。
?
總結(jié)
以上是生活随笔為你收集整理的创建自己的内容提供器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 运行时权限+读取系统联系人
- 下一篇: 假山可以做石敢当吗?