20170104第一行程式碼第七章Content Provider
一、簡介
Content Provider用法有兩種:
1、使用現有的CP來讀取和操作相應程式中的資料;比如系統電話本。
2、建立自己的CP給我們的程式資料提供外部訪問的介面。
二、訪問已有的CP
當一個APP通過CP對其資料提供了外部的訪問介面,則其他任何程式都可以通過這個介面對資料進行訪問和操作。
1、ContentResolver用法
任何程式如果想訪問其他程式通過CP共享的資料,都要使用ContentResolver,通過Context的getContentResolver()方法獲取。
CR不接受表名,只接收內容URI。
URI:給CP中的資料建立了一個唯一的識別符號,通過URI就可以訪問該資料。
URI包含兩個部分:許可權authority+路徑path。
許可權authority:為了區分不同的程式,一般用該程式的包名做許可權,com.example.app.provider
路徑path:為了區分同一個APP中不同的表名。
URI標準格式為:content://com.example.app.provider/table1
其中,com.example.app為提供CP的程式包名;table1為資料所在表名。
使用方法:
ContentResolver cr=getContentResolver();
//查詢資料
Cursor cursor=cr.query(uri, column1, “column1=? and column2=?”, new String[] {“ ”,” ”});
分別填入URI,查詢的列名,查詢的約束條件,佔位符的值,最後還可以加上排序方式。
//增加資料
ContentValues values=new ContentValues();
values.put(“column1”,”hello”);
values.put(“column2”,”hujun”);
cr.insert(uri, values);
利用ContentValues將資料插入表。
//修改資料
ContentValues values=new ContentValues();
values.put(“column1”,”data_changed”);
cr.update(uri, values, “column1=? and column2=?”, new String[] {“ ”,” ”});
分別填入URI,values,以及約束條件和佔位符的值。
//刪除資料
cr.delete(uri, “column1=?” , new String[] {“data”});
刪除列1中值為data的行。
2、讀取系統聯絡人
手機聯絡人URI為:
ContactsContract.CommonDataKinds.Phone.CONTENT_URI
該資料中包括聯絡人姓名、號碼,所在列名分別為:
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
ContactsContract.CommonDataKinds.Phone.NUMBER
讀取聯絡人資訊,還需要獲取許可權
android.permission.READ_CONTACTS
讀取程式碼為:
public void init()
{
ContentResolver cr=getContentResolver();
Cursor cursor=cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
if(cursor!=null)
{
while(cursor.moveToNext())
{
String name=cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String number=cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contacts.add(name+"\n"+number);
}}
if(cursor!=null)cursor.close();
}
三、建立自己的ContentProvider
1、建立CP步驟5部曲
(1)首先,新建MyContentProvider類去繼承ContentProvider,需要重寫6個方法:
onCreate():當存在ContentResolver嘗試訪問該CP時,自動呼叫onCreate()方法來初始化CP,通常在此完成資料庫建立、升級等操作。
insert()、query()、update()、delete()就是操作CP提供的資料時使用的方法。
getType():根據傳入的URI來返回相應的MIME型別?
(2)然後,如何解析URI?
UIR包括兩種格式:
content://com.example.app.provider/table1
content://com.example.app.provider/table1/1
第一種格式,以路徑table1結尾,訪問表table1中所有資料;
第二種格式,在最後加上了id,即訪問表table1中id為1的資料。
以萬用字元形式表示:
*:代表任意長度任意字元;
#:代表任意長度任意數字。
content://com.example.app.provider/*代表任意一個表
content://com.example.app.provider/table1/#代表表table1中任意一行
採用UriMatcher解析URI,
首先,配置UriMatcher,利用addURI()方法,將許可權,路徑和自定義程式碼傳入;
然後,解析URI,利用match(uri)方法,如果該uri和之前addURI()寫入的許可權和路徑相同時,返回自定義程式碼。
最後,通過這個自定義程式碼,即可採取不同的操作。
(3)重寫query()等
public class MyContentProvider 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.contentprovider", "Book", TABLE1_DIR);
uriMatcher.addURI("com.example.contentprovider", "Book/#", TABLE1_ITEM);
uriMatcher.addURI("com.example.contentprovider", "Category", TABLE2_DIR);
uriMatcher.addURI("com.example.contentprovider", "Category/#", TABLE2_ITEM);
}
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
switch (uriMatcher.match(uri)) {
case TABLE1_DIR:
//查詢Book中所有資料
break;
case TABLE1_ITEM:
//查詢Book中單條資料,根據id
break;
case TABLE2_DIR:
//查詢Category中單條資料
break;
case TABLE2_ITEM:
//查詢Book中單條資料,根據id
break;
default:
break;
}
return null;
}
(4)重寫getType()
獲取URI物件所對應的MIME型別。
一個內容URI對應的MIME字串包含3個部分:
1、必須以vnd開頭;
2、如果內容URI以路徑結尾,則後接android.cursor.dir/
如果內容URI以id結尾,則後接android.cursor.item/
3、最後接vnd..
例如:
URI:content://com.example.app.provider/table1
MIMIE:vnd.android.cursor.dir/vnd.com.example.app.provider.table1
URI: content://com.example.app.provider/table1/1
MIMIE: vnd.android.cursor.item/vnd.com.example.app.provider.table1
(5)在AndroidManifest.xml中註冊
android:name="com.example.contentprovider.MyContentProvider"
android:authorities="com.example.contentprovider.provider"
android:exported="true" >
android:exported="true"表示該provider可以被其他程式訪問。
四、跨程式資料共享實踐
資料傳送方,需要構建ContentProvider,將資料共享;共享的資料在CP類中onCreate()封裝到資料庫中。
資料接收方,利用ContentResolver獲取資料。
附錄:
當URI中包含id,如何獲取呢?
String id=uri.getPathSegments().get(1);
由此可見,路徑獲取方式為:String path=uri.getPathSegments().get(0);
相關文章
- Android中Content ProviderAndroidIDE
- Android Content Provider SecurityAndroidIDE
- Flutter狀態管理Provider(三)基於Provider的程式碼框架FlutterIDE框架
- 第七章——字串(程式碼點檢視)字串
- 奧巴馬的第一行程式碼行程
- 第八章:四大元件之Content Provider元件IDE
- 第一行程式碼——書的理解行程
- 《第一行程式碼Android》摘要行程Android
- 這就是奧巴馬的第一行程式碼行程
- 第七章-----執行緒執行緒
- Android深入四大元件(五)Content Provider的啟動過程Android元件IDE
- 《第一行程式碼》讀書筆記三行程筆記
- Android初探(轉自《第一行程式碼》)Android行程
- 《第一行程式碼——Android》封面誕生記行程Android
- 《第一行程式碼——Android》編輯的話行程Android
- 達芬奇密碼 第七章密碼
- Python安裝與第一行程式碼和儲存程式Python行程
- 青出於紅——《第一行程式碼(第2版)》行程
- Java/Android 編碼規範,從第一行程式碼開始JavaAndroid行程
- Vapor 2.0 - MySQL提供程式(MySQL Provider)VaporMySqlIDE
- [20170104]一條sql優化.txtSQL優化
- 第一個Spring程式(程式碼篇)Spring
- 第一段JavaScript程式碼JavaScript
- content = content==null? content="":content; 三目運算子用法例項Null
- css設定文字第一行的樣式程式碼例項CSS
- 愛不釋手的《第一行程式碼》(第2版)行程
- 人人都能學會的python程式設計教程1:第一行程式碼Python程式設計行程
- 《我的第一本程式設計書》第七章 為儲存區起名,更多的中文程式設計
- HTTP狀態碼和content-typeHTTP
- 偽元素 content 出現中文亂碼
- angular原始碼剖析之Provider系列--QProviderAngular原始碼IDE
- angular原始碼剖析之Provider系列--CacheFactoryProviderAngular原始碼IDE
- 【第七章】XSS 跨站指令碼漏洞指令碼
- Flutter 入門與實戰(四十七):使用 Provider 改造?一樣的程式碼,程式碼量降低了2/3!FlutterIDE
- 第一行程式碼第三版學習筆記(一)行程筆記
- 第1章:開始啟程 - 你的第一行android程式碼Android
- 01《第一行程式碼(第三版)》閱讀筆記行程筆記
- 程式是怎麼跑起來的第七章