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