使用android中ContentProvider組件對外共享以及監聽ContentProvider中數據的變化

1.Contentprovider(組件)內容提供者:
    對外共享數據使用,可以把任意類型的數據進行對外共享;如:xml、數據庫、txt等;好處是統一了數據對外的訪問方式
    ContentProvider(內容提供者)的scheme已經由Android規定,scheme爲:content://主機名(或Authority)用於唯一標識這個
    ContentProvider,外部調用這個可以根據這個標識來找到它。
    路徑(Path)可以用來表示我們要操作的數據,路徑的應用根據業務而定
    要操作user表中的id爲1的記錄,可以構建路徑:/user/1
    要操作user表中的id爲1的記錄的age字段,可以構建路徑:/user/1/age
    要操作user表中的所有記錄,可以構建路徑:/user

    如果要操作文件、xml或其它數據,可以這樣命名路徑:要操作xml文件中user節點下的age字段,可以構建路徑:/user/age

使用方法,在使用ContentProvider時首先需要繼承ContentProvider,因爲ContentProvider是組件需要在應用清單文件中進行配置

示例:

import cn.kafei.service.DBOpenHelper;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;

public class UserProvider extends ContentProvider {
	private DBOpenHelper dbOpenHelper;//打開數據庫
	private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH);//添加供匹配的URI
	private static final int USERS = 1;
	private static final int USER = 2;
	static {
		// 第一個參數:主機名,也就是在清單文件配置的provider的android:authorities
		// 第二參數:表示要匹配那個路徑
		// 第三個參數:表示匹配碼的標識,如果匹配成功就返回
		MATCHER.addURI("cn.kafei.provides.userprovider", "user", USERS);//匹配user表中的所有記錄
		// #:表示數字,*號表示所有字符
		MATCHER.addURI("cn.kafei.provides.userprovider", "user/#", USER);//根據ID進行匹配
	}

	/**
	 * 當內容提供者的實例被創建出來之後被調用,只執行一次
	 */
	@Override
	public boolean onCreate() {
		dbOpenHelper = new DBOpenHelper(this.getContext());
		return true;
	}

	/**
	 * 返回你目前要操作的數據的內容類型 如:txt:plain/text html:html/text
	 */
	@Override
	public String getType(Uri uri) {
		switch (MATCHER.match(uri)) {
		case 1:
			return "vnd.android.cursor.dir/user";
		case 2:
			return "vnd.android.cursor.item/user";
		default:
			throw new IllegalArgumentException("this is Unknown Uri:" + uri);
		}
	}

	/**
	 * 可以供外部的應用往內容提供者插入數據 values:用來存放各個字段的值
	 */
	@Override
	public Uri insert(Uri uri, ContentValues values) {
		SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
		switch (MATCHER.match(uri)) {
		case 1:
			// 如果主鍵是整型,那麼這個行號就等於你的主鍵值
			long rowid = db.insert("user", "name", values);
			// content://cn.kafei.provides.userprovider/user/1
			// Uri
			// insertUri=Uri.parse("content://cn.kafei.provides.userprovider/user/"+rowid);
			Uri insertUri = ContentUris.withAppendedId(uri, rowid);
			return insertUri;
		default:
			throw new IllegalArgumentException("this is Unknown Uri:" + uri);
		}
	}

	/**
	 * 允許外部的應用刪除內容提供者中的數據
	 */
	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
		int num = 0;
		switch (MATCHER.match(uri)) {
		case 1:
			num = db.delete("user", selection, selectionArgs);
			break;
		case 2:
			long rowid = ContentUris.parseId(uri);// 從URI中獲取傳入的ID
			String where = "id=" + rowid;
			if (selection != null && !"".equals(selection.trim())) {
				where += " and " + selection;
			}
			num = db.delete("user", where, selectionArgs);
			break;
		default:
			throw new IllegalArgumentException("this is Unknown Uri:" + uri);
		}
		return num;
	}

	/**
	 * 允許外部的應用對內容提供者中的數據進行更新
	 */
	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
		int num = 0;
		switch (MATCHER.match(uri)) {
		case 1:
			num = db.update("user", values, selection, selectionArgs);
			break;
		case 2:
			long rowid = ContentUris.parseId(uri);// 從URI中提取傳入的ID
			String where = "id=" + rowid;
			if (selection != null && !"".equals(selection.trim())) {
				where += " and " + selection;
			}
			num = db.update("user", values, where, selectionArgs);
			break;
		default:
			throw new IllegalArgumentException("this is Unknown Uri:" + uri);
		}
		return num;
	}

	/**
	 * 可以供外部的應用查詢內容提供者的數據
	 */
	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
		switch (MATCHER.match(uri)) {
		case 1:
			return db.query("user", projection, selection, selectionArgs, null,
					null, sortOrder);
		case 2:
			long rowid = ContentUris.parseId(uri);// 從URI中提取傳入的ID
			String where = "id=" + rowid;
			if (selection != null && !"".equals(selection.trim())) {
				where += " and " + selection;
			}
			return db.query("user", projection, where, selectionArgs, null,
					null, sortOrder);
		default:
			throw new IllegalArgumentException("this is Unknown Uri:" + uri);
		}
	}
}
在應用清單文件中(application)標籤內進行配置ContentProvider組件:

<!--android:name:表示ContentProvider的類名;android:authorities:表示主機名 ,主機名可以自定義,但是建議按照所提供的格式,以免引起重複-->
        <provider
            android:name=".UserProvider"
            android:authorities="cn.kafei.provides.userprovider" >
        </provider>
以上完成後就算ContentProvider配置完成
測試:

import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.test.AndroidTestCase;
import android.util.Log;

public class AccessContentProviderTest extends AndroidTestCase {
	private final String TAG="AccessContentProviderTest";
	/**
	 * 測試插入
	 */
	public void testInsert()throws Exception{
		Uri uri=Uri.parse("content://cn.kafei.provides.userprovider/user");//要操作的路徑
		ContentResolver resolver=this.getContext().getContentResolver();
		ContentValues values=new ContentValues();
		values.put("name", "ht896632");
		values.put("age", "99");
		values.put("amount", "1234000000");
		resolver.insert(uri, values);
	}
	/**
	 * 測試刪除
	 */
	public void testDelete()throws Exception{
		Uri uri=Uri.parse("content://cn.kafei.provides.userprovider/user/23");
		ContentResolver resolver=this.getContext().getContentResolver();
		resolver.delete(uri, null, null);
	}
	/**
	 * 測試更新
	 */
	public void testUpdate()throws Exception{
		Uri uri=Uri.parse("content://cn.kafei.provides.userprovider/user/22");
		ContentResolver resolver=this.getContext().getContentResolver();
		ContentValues values=new ContentValues();
		values.put("name", "李宏濤");
		
		resolver.update(uri, values, null, null);
	}
	/**
	 * 測試查詢
	 */
	public void testQuery()throws Exception{
		Uri uri=Uri.parse("content://cn.kafei.provides.userprovider/user");
		ContentResolver resolver=this.getContext().getContentResolver();
		Cursor cursor=resolver.query(uri, null, null, null, "id desc");
		while(cursor.moveToNext()){
			String name=cursor.getString(cursor.getColumnIndex("name"));
			int id=cursor.getInt(cursor.getColumnIndex("id"));
			Log.i(TAG, "ID:"+id+" name:"+name);
		}
		cursor.close();
	}
}
注意:ContentProvider的注作用是對外共享數據。

2.監聽ContentProvider數據中的變化

思路:首先往ContentProvider中添加數據,然後通過其它應用監聽ContentProvider中的數據變化。

添加數據方法(使用一個應用往ContentProvider中添加數據):

public void add(View view){
    	Uri uri=Uri.parse("content://cn.kafei.provides.userprovider/user");//要操作的路徑
		ContentResolver resolver=this.getContentResolver();
		ContentValues values=new ContentValues();
		values.put("name", "One");
		values.put("age", "101");
		values.put("amount", "9000");
		resolver.insert(uri, values);
    }
監聽數據方法(放在一個應用的onCreate方法中,並且讓這個應用保持在運行狀態,否則監聽不到):

        Uri uri=Uri.parse("content://cn.kafei.provides.userprovider/user");//要操作的路徑
        //第一個參數:要監聽的URI
        //第二個參數:是否依賴
        //第三參數:表示監聽對象
        this.getContentResolver().registerContentObserver(uri, true, new UserContentOberver(new Handler()));
       //以上代碼放在onCreate方法中,監聽時,作爲監聽的應該必須啓動 
   /**
     * 監聽數據方法
     */
    private class UserContentOberver extends ContentObserver{
		public UserContentOberver(Handler handler) {
			super(handler);
		}
		//只能粗略的監聽到數據是否發生變化
    	@Override
    	public void onChange(boolean selfChange) {
    		//select * from user order by id desc limit 1
    		Uri uri=Uri.parse("content://cn.kafei.provides.userprovider/user");//要操作的路徑
    		Cursor cursor=getContentResolver().query(uri, null, null, null, "id desc");
    		if(cursor.moveToFirst()){
    			String name=cursor.getString(cursor.getColumnIndex("name"));
    			Log.i(TAG, name);
    		}
    		
    	}
    }
注:ContentProvider、添加數據方法、監聽數據方法在三個不同的應用中,連接他們之前的就是一個URI:
content://cn.kafei.provides.userprovider/user

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章