Android四大組件之一 content provider,它主要的作用是:實(shí)現(xiàn)各個(gè)應(yīng)用程序之間的(跨應(yīng)用)數(shù)據(jù)共享。
在這里涉及到進(jìn)程通信問(wèn)題,自然在Android中使用的是binder來(lái)進(jìn)行,但是由于content provider提供的數(shù)據(jù)量一般都比較大不能夠直接進(jìn)行傳遞。
所以這里采用的是一種叫做 匿名共享內(nèi)存的方式進(jìn)行數(shù)據(jù)傳遞,在不同的進(jìn)程中只需要傳遞一個(gè)文件描述符就可以。
通過(guò)下圖對(duì)content provider有個(gè)比較直觀的了解:
ContentProvider提供了在應(yīng)用程序之前共享數(shù)據(jù)的一種機(jī)制。
1)存儲(chǔ)和獲取數(shù)據(jù)提供了統(tǒng)一的接口。
2)對(duì)數(shù)據(jù)進(jìn)行封裝,不用關(guān)心數(shù)據(jù)存儲(chǔ)的細(xì)節(jié)。
3)Android為常見(jiàn)的一些數(shù)據(jù)提供了默認(rèn)的ContentProvider(包括音頻、視頻、圖片和通訊錄等)。
二、content provider的定義
如果需要使用content provider首先需要在AndroidManifest中進(jìn)行申明
<provider android:authorities="list" //該provider的唯一ID android:directBootAware=["true" | "false"] android:enabled=["true" | "false"] // 能否被系統(tǒng)實(shí)例化 android:exported=["true" | "false"] //該provider能否被其他應(yīng)用使用 android:grantUriPermissions=["true" | "false"] android:icon="drawable resource" android:initOrder="integer" android:label="string resource" android:multiprocess=["true" | "false"] android:name="string" android:permission="string" android:process="string" android:readPermission="string" //讀權(quán)限 android:syncable=["true" | "false"] android:writePermission="string" > //寫(xiě)權(quán)限 . . . </provider>
注意在provider的屬性中最重要的是 authorities,它是唯一能夠標(biāo)識(shí)一個(gè)provider,contentprovider通過(guò)URI中的地址來(lái)查找到對(duì)應(yīng)的provider,其中該URI就包含了需要尋找的provider中的authorities屬性值。
定義好的provider最后被打包編譯進(jìn)入到PackageManagerService中。
在Java代碼中定義一個(gè)provider時(shí)需要繼承其父類(lèi)ContentProvider,并實(shí)現(xiàn)增刪查改方法。
public class XXXXProvider extends ContentProvider { @Override public boolean onCreate() { // TODO Auto-generated method stub return false; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // TODO Auto-generated method stub return null; } @Override public String getType(Uri uri) { // TODO Auto-generated method stub return null; } @Override public Uri insert(Uri uri, ContentValues values) { // TODO Auto-generated method stub return null; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // TODO Auto-generated method stub return 0; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { // TODO Auto-generated method stub return 0; } }
三、contentprovider的使用
在activity中如果想通過(guò)provider來(lái)實(shí)現(xiàn)增刪查改,首先需要獲取contentprovider,大致過(guò)程為在context中獲取contentResolver,然后通過(guò)contentResolver去ActivityManagerService中查詢(xún)對(duì)應(yīng)的provider,如果沒(méi)有則進(jìn)入PackageManagerService中查找:
1)首先每個(gè)context類(lèi)都會(huì)內(nèi)部包含了一個(gè)ContentResolver的子對(duì)象ApplicationContentResolver。
2)通過(guò)調(diào)用ApplicationContentResolver的主要方法query來(lái)獲取CP的數(shù)據(jù)庫(kù)數(shù)據(jù)。
3)調(diào)用的過(guò)程首先會(huì)調(diào)用ContentResolver的核心方法acquireProvider()。而acquireProvider()方法是一個(gè)抽象方法,其實(shí)現(xiàn)是交由子類(lèi)實(shí)現(xiàn)。
4)通過(guò)子類(lèi)的acquireProvider()方法實(shí)現(xiàn)了解到主要的實(shí)現(xiàn)是交由ActivityThread類(lèi)來(lái)完成。
5)ActivityThread類(lèi)會(huì)做出一個(gè)判斷,如果本地保存一個(gè)需要獲取的CP對(duì)象實(shí)例,就會(huì)直接返回這個(gè)對(duì)象實(shí)例,如果沒(méi)有保存,則會(huì)訪問(wèn)AMS對(duì)象去查找獲取一個(gè)對(duì)象的CP對(duì)象實(shí)例,當(dāng)找到這個(gè)對(duì)象實(shí)例后會(huì)保存到本地以便日后快速獲取。
6)如果在AMS里面沒(méi)有找到,就會(huì)繼續(xù)深入到PMS里去從全部的provider中查找。
7)獲取到CP對(duì)象實(shí)例后會(huì)通過(guò)層層返回,最后再調(diào)用該CP對(duì)象的query方法獲取相應(yīng)的數(shù)據(jù)。
首先在應(yīng)用的的manifest中需要進(jìn)行讀寫(xiě)權(quán)限申明,這個(gè)申明的定義跟之前provider定義中讀寫(xiě)所需權(quán)限屬性值是一樣的:
<use-permission android:name="android.permission.READ_SMS"/> <use-permission android:name="android.permission.WRITE_SMS"/>
在activity中獲取ContentResolver調(diào)用其中的操作方法時(shí),需要傳入相對(duì)應(yīng)的參數(shù):
contentResolver.query(Uri uri, String[] projection,String selection, String[] selectionArgs,String orderBy);
uri:傳入對(duì)應(yīng)uri是為了查找到對(duì)應(yīng)的provider,跟provider在manifest中定義的authorities值是一樣
projection:選擇需要返回的對(duì)象屬性值,有時(shí)候不需要將對(duì)象的值全部返回。
selection/selectionArgs: 查詢(xún)條件
orderBy: 返回的對(duì)象排序方式
類(lèi)似其他的delete、insert和update操作。最主要的是傳入正確的Uri才能找到對(duì)應(yīng)的provider。