Content Provider是Android系統四大組件之一:android
官方的定義是:A Content Provider manages access to a central repository of data.數據庫
那麼Android系統爲何要提供這樣一個組件呢?安全
我的以爲至少有以下兩點:網絡
首先,Android是一個很重視安全性的系統(貌似Android系統的漏洞最多~~~),一個應用的數據對於其餘應用來講私有的,除非你把數據存儲在SD卡上。但不少時候咱們須要在程序之間共享數據,好比咱們想獲取聯繫人的信息之類的。這時Content Provider就提供了一個很好的解決方案,將數據的存儲、讀取細節隱藏,提供一個統一的接口供其它應用訪問,而且還能夠作到權限控制,在必定程度上保證數據的安全性。ide
其次就是進程間通訊(inter-process communication IPC)的問題,若是讓開發者本身來處理這些細節無疑會加大開發的難度。而Content Provider提供了相似於b/s結構的模式,b與c之間是以一種什麼方式去實現咱們並不關心,就像咱們大部分時候不用去關心網絡究竟是怎麼鏈接的。開發者應該關心的是怎麼去實現一個Content Provider或去調用一個Content Provider。ui
URI(Uniform Resource Identifier)統一資源標識符spa
URI和URL(Unifrom Resource Locator)很像,但二者並非同一個東西,不過能夠拿來作類推。翻譯
對於一個content URI的通常形式是這樣子的:code
content://user_dictionary/words
其中「content://」稱爲scheme,相似於http://或ftp://,表示這個URI的類型。orm
「user_dictionary」就相似於域名,但在這裏應該叫作authority(這個怎麼翻譯呢?)。它是一個用來標識不一樣content provider的名稱。
「words」這裏用於表示對哪個表進行操做。注意,這裏這麼說是不許確的!
首先content provider的數據源不必定就是關係型數據庫,能夠是xml,數據文件甚至是網絡數據。
其次,就算是SQLite之類的數據庫,這一部分也不必定就真的是一個真實存在的表,它可能就是某個視圖而已,這裏說它是某一個表只是方便理解,切記!
如何建立一個Uri呢?
第一種:能夠用Uri.Builder來建立:
Uri.Builder builder = new Uri.Builder(); builder.scheme("content"); builder.authority("user_dictionary"); builder.path("words"); Uri uri = builder.build();
還有一種更簡單的方法,就是使用Uri.Parse()方法:
Uri uri = Uri.parse("content://user_dictionary/words");
顯然,第二種要簡潔得多了。
有些content provider支持直接查詢到某一條記錄,就是在上面提到Uri的末尾再加上一個id如:
content://user_dictionary/words/2
就表示直接定位到某一個記錄上。構建這種Uri有一個簡單的方法
Uri uri = Uri.parse("content://user_dictionary/words");
Uri singleUri = ContentUris.withAppendedId(uri, 4);
從content provider中檢索數據:
使用一個content provider主要有以下幾個步驟:
在AndroidManifest.xml文件中添加相應的權限。
如,想要查看系統的通話記錄應該添加
<uses-permission android:name="android.permission.READ_CALL_LOG" />
要注意,content provider讀寫權限是分開的,讀就只能讀,寫就只能寫(不像寫外部存儲卡那個權限,它其實還含有讀的權限)。好比同時還要修改通話記錄的話,還應該添加這個權限:
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
使用ContentResolver的query方法。該方法的簽名是這樣的:
public final Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
若是比較熟悉SQLite的應該對這些參數至關熟悉。不就是把一個SQL語句分紅幾個部分嘛。
這個方法將返回一個Cursor,經過這個「遊標」咱們就能夠獲得咱們想要的數據了。
下面給一個獲取通話記錄的例子:
public void getData() { String[] projection = { Calls.NUMBER, Calls.DATE, Calls.DURATION, Calls.TYPE }; Cursor cursor = getContentResolver().query(Calls.CONTENT_URI, projection, null, null, null); while (cursor.moveToNext()) { for (int i = 0; i < cursor.getColumnCount(); i++) { System.out.println(cursor.getColumnName(i) + "--->" + cursor.getString(i)); } System.out.println("~~~~~~~~~~~~~~~~"); } cursor.close(); }
其餘方法其實也都是差很少的,看看文檔能夠掌握了,若是還以爲比較難懂,建議先學一下SQLite的使用。