国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android編程之創建自己的內容提供器實現方法

2019-10-22 18:31:13
字體:
來源:轉載
供稿:網友

本文實例講述了Android編程之創建自己的內容提供器實現方法。分享給大家供大家參考,具體如下:

我們學習了如何在自己的程序中訪問其他應用程序的數據。總體來說思 路還是非常簡單的,只需要獲取到該應用程序的內容 URI,然后借助 ContentResolver 進行CRUD 操作就可以了。可是你有沒有想過,那些提供外部訪問接口的應用程序都是如何實現這種功能的呢?它們又是怎樣保證數據的安全性,使得隱私數據不會泄漏出去?

創建內容提供器的步驟

前面已經提到過,如果想要實現跨程序共享數據的功能,官方推薦的方式就是使用內容提供器,可以通過新建一個類去繼承 ContentProvider 的方式來創建一個自己的內容提供器。 ContentProvider 類中有六個抽象方法,我們在使用子類繼承它的時候,需要將這六個方法全 部重寫。新建 MyProvider 繼承自 ContentProvider,代碼如下所示:

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 Uri insert(Uri uri, ContentValues values) {return null;}@Overridepublic int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {return 0;}@Overridepublic int delete(Uri uri, String selection, String[] selectionArgs) {return 0;}@Overridepublic String getType(Uri uri) {return null;}}

在這六個方法中,相信大多數你都已經非常熟悉了,我再來簡單介紹一下吧。

1.    onCreate()

初始化內容提供器的時候調用。通常會在這里完成對數據庫的創建和升級等操作, 返回 true 表示內容提供器初始化成功,返回 false 則表示失敗。注意,只有當存在 ContentResolver 嘗試訪問我們程序中的數據時,內容提供器才會被初始化。

2.    query()

從內容提供器中查詢數據。使用 uri 參數來確定查詢哪張表,projection 參數用于確 定查詢哪些列,selection 和 selectionArgs 參數用于約束查詢哪些行,sortOrder 參數用于 對結果進行排序,查詢的結果存放在 Cursor 對象中返回。

3.    insert()

向內容提供器中添加一條數據。使用 uri 參數來確定要添加到的表,待添加的數據 保存在 values 參數中。添加完成后,返回一個用于表示這條新記錄的 URI。

4.    update()

更新內容提供器中已有的數據。使用 uri 參數來確定更新哪一張表中的數據,新數 據保存在 values 參數中,selection 和 selectionArgs 參數用于約束更新哪些行,受影響的 行數將作為返回值返回。

5.    delete()

從內容提供器中刪除數據。使用 uri 參數來確定刪除哪一張表中的數據,selection和 selectionArgs 參數用于約束刪除哪些行,被刪除的行數將作為返回值返回。

6.    getType()

根據傳入的內容 URI 來返回相應的 MIME 類型。 可以看到,幾乎每一個方法都會帶有 Uri 這個參數,這個參數也正是調用 ContentResolver的增刪改查方法時傳遞過來的。而現在,我們需要對傳入的 Uri 參數進行解析,從中分析出 調用方期望訪問的表和數據。

回顧一下,一個標準的內容 URI 寫法是這樣的:

content://com.example.app.provider/table1

這就表示調用方期望訪問的是 com.example.app 這個應用的 table1 表中的數據。除此之 外,我們還可以在這個內容 URI 的后面加上一個 id,如下所示:

content://com.example.app.provider/table1/1

這就表示調用方期望訪問的是 com.example.app 這個應用的 table1 表中 id 為 1 的數據。 內容 URI 的格式主要就只有以上兩種,以路徑結尾就表示期望訪問該表中所有的數據,以 id 結尾就表示期望訪問該表中擁有相應 id 的數據。我們可以使用通配符的方式來分別匹 配這兩種格式的內容 URI,規則如下。

1.    *:表示匹配任意長度的任意字符

2.    #:表示匹配任意長度的數字 所以,一個能夠匹配任意表的內容 URI 格式就可以寫成:

content://com.example.app.provider/*

而一個能夠匹配 table1 表中任意一行數據的內容 URI 格式就可以寫成:

content://com.example.app.provider/table1/#

接著,我們再借助 UriMatcher 這個類就可以輕松地實現匹配內容 URI 的功能。UriMatcher 中提供了一個 addURI()方法,這個方法接收三個參數,可以分別把權限、路徑和一個自定義 代碼傳進去。這樣,當調用 UriMatcher 的 match()方法時,就可以將一個 Uri 對象傳入,返 回值是某個能夠匹配這個 Uri 對象所對應的自定義代碼,利用這個代碼,我們就可以判斷出 調用方期望訪問的是哪張表中的數據了。修改 MyProvider 中的代碼,如下所示:

public class MyProvider extends ContentProvider {public static final int TABLE1_DIR = 0;public static final int TABLE1_ITEM = 1;public static final int TABLE2_DIR = 2;public static final int TABLE2_ITEM = 3;private static UriMatcher uriMatcher; static {uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);uriMatcher.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_ITEM);uriMatcher.addURI("com.example.app.provider ", "table2/#", TABLE2_ITEM);}……@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;}……}……}

可以看到,MyProvider 中新增了四個整型常量,其中 TABLE1_DIR 表示訪問 table1 表 中的所有數據,TABLE1_ITEM 表示訪問 table1 表中的單條數據,TABLE2_DIR 表示訪問 table2 表中的所有數據,TABLE2_ITEM 表示訪問 table2 表中的單條數據。接著在靜態代碼 塊里我們創建了 UriMatcher 的實例,并調用 addURI()方法,將期望匹配的內容 URI 格式傳 遞進去,注意這里傳入的路徑參數是可以使用通配符的。然后當 query()方法被調用的時候, 就會通過 UriMatcher 的 match()方法對傳入的 Uri 對象進行匹配,如果發現 UriMatcher 中某 個內容 URI 格式成功匹配了該 Uri 對象,則會返回相應的自定義代碼,然后我們就可以判斷 出調用方期望訪問的到底是什么數據了。

上述代碼只是以 query()方法為例做了個示范,其實 insert()、update()、delete()這幾個方 法的實現也是差不多的,它們都會攜帶 Uri 這個參數,然后同樣利用 UriMatcher 的 match() 方法判斷出調用方期望訪問的是哪張表,再對該表中的數據進行相應的操作就可以了。

除此之外,還有一個方法你會比較陌生,即 getType()方法。它是所有的內容提供器都必 須提供的一個方法,用于獲取 Uri 對象所對應的 MIME 類型。一個內容 URI 所對應的 MIME 字符串主要由三部分組分,Android 對這三個部分做了如下格式規定。

1.    必須以 vnd 開頭。
2.    如果內容 URI 以路徑結尾,則后接 android.cursor.dir/,如果內容 URI 以 id 結尾, 則后接 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

現在我們可以繼續完善 MyProvider 中的內容了,這次來實現 getType()方法中的邏輯, 代碼如下所示:

public class MyProvider extends ContentProvider {……@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;}}

到這里,一個完整的內容提供器就創建完成了,現在任何一個應用程序都可以使用ContentResolver 來訪問我們程序中的數據。那么前面所提到的,如何才能保證隱私數據不會 泄漏出去呢?其實多虧了內容提供器的良好機制,這個問題在不知不覺中已經被解決了。因 為所有的 CRUD 操作都一定要匹配到相應的內容 URI 格式才能進行的,而我們當然不可能 向 UriMatcher 中添加隱私數據的 URI,所以這部分數據根本無法被外部程序訪問到,安全問題也就不存在了。

希望本文所述對大家Android程序設計有所幫助。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 图木舒克市| 溧阳市| 漳浦县| 临泉县| 龙口市| 墨竹工卡县| 罗江县| 犍为县| 保德县| 法库县| 新沂市| 泽库县| 东港市| 平潭县| 遂昌县| 江口县| 芮城县| 犍为县| 丘北县| 丹巴县| 扶余县| 巴林右旗| 临海市| 邻水| 恩平市| 宜川县| 岳普湖县| 白沙| 南京市| 汪清县| 辽中县| 特克斯县| 乌苏市| 共和县| 长治市| 长武县| 云和县| 横峰县| 大港区| 宜城市| 宜君县|