/** * 自定义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);数据库