/** * 自定義MyContentProvider提供了對外共享本地數據一種機制 * 在AndroidManifest.xml中註冊MyContentProvider: * <provider android:name="com.test.provider.MyContentProvider" * android:authorities="com.test.provider.MyContentProvider" * android:exported="true" /> * name,爲自定義Provider類的路徑名 * authorities,爲類中定義的常量AUTHORITY,是Provider的惟一標示,通常定義爲Provider類的路徑名 * exported="true",表示容許其餘應用訪問 * */ public class MyContentProvider extends ContentProvider{ // 定義AndroidManifest.xml中<provider>標籤的android:authorities的屬性值 public static final String AUTHORITY="com.test.provider.MyContentProvider"; private static final String DATABASE_DIR = "database_dir"; //數據庫的目錄名 private static final String DATABASE_NAME = "database.db"; //數據庫的文件名,一個數據庫文件能夠關聯多張表 public static final String SIMPLE_TABLE_NAME = "simple_list_data";//數據庫的表名 // 定義數據庫中simple_list_data表的基本字段 public static final class SimpleListData implements BaseColumns{ // Data數據只有兩個字段:_id,content public static final String ID = "_id";//_id字段 public static final String CONTENT = "content";//content字段 // 定義Uri:scheme + authority + path // 1. scheme必須以content://開頭,這是Android規定的。 // 2. authority用於來惟一標示一個ContentProvider,通常定義爲ContentProvider的包路徑。 // 3. path也是字符串,表示要操做的數據。可根據本身的實現邏輯來指定: // content://com.test.provider.MyContentProvider/simple_list_data // 表示要操做simple_list_data表 // // content://com.test.provider.MyContentProvider/simple_list_data/# // 表示要操做simple_list_data表中特定id的行(記錄).注意#匹配一個數字字符串 // // content://com.test.provider.MyContentProvider/simple_list_data/10/content // 表示要操做simple_list_data表中id爲10的行的content字段。 // // content://com.test.provider.MyContentProvider/simple_list_data/* // 表示操做simple_list_data表中的全部字段。注意*匹配一個文本字符串。 public static final Uri DATA_URI = Uri.parse("content://" + AUTHORITY + "/" + SIMPLE_TABLE_NAME); // 若是要處理的對象是一個新的數據類型,須要定義MIME類型,在getType(Uri)中返回定義類型值 // 定義遵循3條原則: // 1. 必須以"vnd"開頭 // 2. 若是Uri對應的數據有多條,必須是"vnd.android.cursor.dir/開頭" // 3. 若是Uri對應的數據只有一條,必須是"vnd.android.cursor.item/開頭" public static final String TYPE = "vnd.android.cursor.dir/vnd.dir"; public static final String ITEM_TYPE = "vnd.android.cursor.item/vnd.item"; } // 使用靜態代碼塊初始化UriMatch // 能夠註冊多個Uri,每一個Uri表明一種操做 // 在使用UriMatch。match(uri)方法匹配相應的URI,就能夠返回相應的code,好比: // "content://com.test.provider.MyContentProvider/simple_list_data"匹配返回1 // "content://com.test.provider.MyContentProvider/simple_list_data/#"匹配返回2 public static final UriMatcher mUriMatcher; static { mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); mUriMatcher.addURI(AUTHORITY, SIMPLE_TABLE_NAME, 1); //URI表示返回全部數據 mUriMatcher.addURI(AUTHORITY, SIMPLE_TABLE_NAME+"/#", 2); //URI表示返回某一條數據 } // 定義SQLite數據庫接口 private class SQLiteHelper extends SQLiteOpenHelper { public SQLiteHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); } public void onCreate(SQLiteDatabase db) { } public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } } private static SQLiteHelper mDb; @Override public boolean onCreate() { if( mDb == null ){ StringBuffer path = new StringBuffer(); if ( Environment.getExternalStorageState().equalsIgnoreCase(Environment.MEDIA_MOUNTED) ) { File file = Environment.getExternalStorageDirectory(); path.append(file.getPath()); } else { path.append(getContext().getFilesDir()); } path.append(File.separator); path.append(DATABASE_DIR); String databaseDirPath = path.toString(); File dir = new File(databaseDirPath); if(!dir.exists()){ dir.mkdir(); } path.append(File.separator); path.append(DATABASE_NAME); String databaseFullPath = path.toString(); File file = new File(databaseFullPath); if(!file.exists()){ try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } mDb = new SQLiteHelper(getContext(),databaseFullPath,null,1); SQLiteDatabase db = mDb.getWritableDatabase(); StringBuffer str = new StringBuffer(); str.append("CREATE TABLE IF NOT EXISTS "); str.append(SIMPLE_TABLE_NAME); str.append(" (_id INTERGER PRIMARY KEY, content TEXT)"); db.execSQL(str.toString()); db.close(); } return (mDb==null)?false:true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase db = mDb.getReadableDatabase(); Cursor c = null; switch(mUriMatcher.match(uri)){ case 1: c = db.query(SIMPLE_TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder); break; case 2: long id = ContentUris.parseId(uri); StringBuffer where = new StringBuffer(); where.append("_id="); where.append(id); if(selection!=null && !where.toString().equalsIgnoreCase(selection.trim())){ where.append(" and "); where.append(selection); } c = db.query(SIMPLE_TABLE_NAME, projection, where.toString(), selectionArgs, null, null, sortOrder); break; default: break; } return c; } @Override public String getType(Uri uri) { String mimeType = null; switch(mUriMatcher.match(uri)){ case 1://URI表示返回全部數據 mimeType = SimpleListData.TYPE; break; case 2://URI表示返回某一條數據 mimeType = SimpleListData.ITEM_TYPE; break; default: break; } return mimeType; } @Override public Uri insert(Uri uri, ContentValues values) { Uri insertedUri = null; SQLiteDatabase db = mDb.getWritableDatabase(); if(mUriMatcher.match(uri)==1){ //插入只能是向表插入 long newid = db.insert(SIMPLE_TABLE_NAME, null, values); getContext().getContentResolver().notifyChange(uri, null); insertedUri = ContentUris.withAppendedId(uri, newid); } db.close(); return insertedUri; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { int count = 0; SQLiteDatabase db = mDb.getWritableDatabase(); switch(mUriMatcher.match(uri)){ case 1://刪除表 count = db.delete(SIMPLE_TABLE_NAME, selection, selectionArgs); //向外界通知數據變化,以便ContentResolver做出相應 getContext().getContentResolver().notifyChange(uri, null); break; case 2://刪除表中的某一條數據 long id = ContentUris.parseId(uri); StringBuffer where = new StringBuffer(); where.append("_id="); where.append(id); if(selection!=null && !where.toString().equalsIgnoreCase(selection.trim())){ where.append(" and "); where.append(selection); } count = db.delete(SIMPLE_TABLE_NAME, where.toString(), selectionArgs); //向外界通知數據變化,以便ContentResolver做出相應 getContext().getContentResolver().notifyChange(uri, null); break; default: break; } db.close(); return count; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { int count = 0; SQLiteDatabase db = mDb.getWritableDatabase(); switch(mUriMatcher.match(uri)){ case 1: count = db.update(SIMPLE_TABLE_NAME, values, selection, selectionArgs); getContext().getContentResolver().notifyChange(uri, null); break; case 2: long id = ContentUris.parseId(uri); StringBuffer where = new StringBuffer(); where.append("_id="); where.append(id); if(selection!=null && !where.toString().equalsIgnoreCase(selection.trim())){ where.append(" and "); where.append(selection); } count = db.update(SIMPLE_TABLE_NAME, values, where.toString(), selectionArgs); getContext().getContentResolver().notifyChange(uri, null); break; default: break; } db.close(); return count; } }
自定義ContentObserver來監聽註冊Uri數據的變化:java
public class MyContentObserver extends ContentObserver{ private Handler mHandler; public static final int DATA_CHANGED = 100; public MyContentObserver(Handler handler) { super(handler); mHandler = handler; } public void onChange(boolean selfChange) { mHandler.sendEmptyMessage(DATA_CHANGED); } }
使用ContentResolver來獲取ContentProvider提供的數據,同時註冊ContentObserver監聽Uri數據的變化:android
//註冊觀察者
mContentObserver = new MyContentObserver(new Handler(){
public void handleMessage(Message msg) {
if(msg.what == MyContentObserver.DATA_CHANGED){
}
}
});
mContentResolver = getContentResolver();
mContentResolver.registerContentObserver(MyContentProvider.SimpleListData.DATA_URI, true, mContentObserver);
//解除觀察者
mContentResolver.unregisterContentObserver(mContentObserver);數據庫