ContentProvider提供了标准的接口,供APP跟其他APP共享数据。ContentProvider提供了一种基于使用content://模式的简单URI寻址模型来发布和使用数据的接口。它允许将应用层跟底层数据层分离,通过抽象底层数据源使应用程序不必依赖于某个数据源。
1、示例展示用法
1) MyContentProvider.java
/**
* 抽象类,实现了ComponentCallbacks2接口
* 在清单文件注册,进程启动时自动创建。
*/
public class MyContentProvider extends ContentProvider {
private static final String TAG = MyContentProvider.class.getSimpleName();
public static final Uri CONTENT_URI = Uri.parse("content://com.qinuli.provider.mycontentprovider/elements");
private static final int ALL_ROWS = 1;
private static final int SINGLE_ROW = 2;
private static final UriMatcher URI_MATCHER;
static{
URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
URI_MATCHER.addURI("com.qinuli.provider.mycontentprovider", "elements", ALL_ROWS);
URI_MATCHER.addURI("com.qinuli.provider.mycontentprovider", "elements/#", SINGLE_ROW);
}
private MyDB myDB;
@Override
public boolean onCreate() {
Log.d(TAG, "onCreate");
myDB = new MyDB(getContext(), MyDB.DATABASE_NAME, null, MyDB.DATABASE_VERSION);
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = myDB.getWritableDatabase();
SQLiteQueryBuilder sqLiteQueryBuilder = new SQLiteQueryBuilder();
sqLiteQueryBuilder.setTables(MyDB.DATABASE_TABLE);
switch(URI_MATCHER.match(uri)){
case SINGLE_ROW:
String rowID = uri.getPathSegments().get(1);
sqLiteQueryBuilder.appendWhere(MyDB.KEY_ID+"="+rowID);
break;
default:break;
}
Cursor cursor = sqLiteQueryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder);
return cursor;
}
@Override
public String getType(Uri uri) {
switch(URI_MATCHER.match(uri)){
case ALL_ROWS:
return "vnd.android.cursor.dir/vnd.qinuli.elemental";
case SINGLE_ROW:
return "vnd.android.cursor.item/vnd.qinuli.elemental";
default:
throw new IllegalArgumentException("Unsupported URI:"+uri);
}
}
@Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db = myDB.getWritableDatabase();
long id = db.insert(MyDB.DATABASE_TABLE, null, values);
if(id>-1){
Uri insertedId = ContentUris.withAppendedId(CONTENT_URI, id);
getContext().getContentResolver().notifyChange(insertedId, null);
return insertedId;
}
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = myDB.getWritableDatabase();
switch(URI_MATCHER.match(uri)){
case SINGLE_ROW:
String rowId = uri.getPathSegments().get(1);
selection = MyDB.KEY_ID+"="+rowId+(TextUtils.isEmpty(selection)?"":" AND ("+selection+')');
break;
default:break;
}
if(selection==null){
selection = "1";
}
int deleteCount = db.delete(MyDB.DATABASE_TABLE, selection, selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
return deleteCount;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
SQLiteDatabase db = myDB.getWritableDatabase();
switch(URI_MATCHER.match(uri)){
case SINGLE_ROW:
String rowId = uri.getPathSegments().get(1);
selection = MyDB.KEY_ID+"="+rowId+(TextUtils.isEmpty(selection)?"":" AND ("+selection+')');
break;
default:break;
}
int updateCount = db.update(MyDB.DATABASE_TABLE, values, selection, selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
return updateCount;
}
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode)
throws FileNotFoundException {
String rowId = uri.getPathSegments().get(1);
File file = new File(getContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES), rowId);
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
int fileMode = 0;
if(mode.contains("w")){
fileMode |= ParcelFileDescriptor.MODE_WRITE_ONLY;
}
if(mode.contains("r")){
fileMode |= ParcelFileDescriptor.MODE_READ_ONLY;
}
if(mode.contains("+")){
fileMode |= ParcelFileDescriptor.MODE_APPEND;
}
return ParcelFileDescriptor.open(file, fileMode);
}
}
2) MyDB.java
public class MyDB extends SQLiteOpenHelper {
private static final String TAG = MyDB.class.getSimpleName();
public static final String KEY_ID = "_id";
public static final String KEY_GOLD_HOARD_NAME_COLUMN = "GOLD_HOARD_NAME_COLUMN";
public static final String KEY_GOLD_HOARD_ACCESSIBLE_COLUMN = "GOLD_HOARD_ACCESSIBLE_COLUMN";
public static final String KEY_GOLD_HOARDED_COLUMN = "GOLD_HOARDED_COLUMN";
public static final String DATABASE_NAME = "me.db";
public static final String DATABASE_TABLE = "GoldHoards";
public static final int DATABASE_VERSION = 1;
private static final String DATABASE_CREATE = "create table " + DATABASE_TABLE + " ("
+ KEY_ID + " integer primary key autoincrement, "
+ KEY_GOLD_HOARD_NAME_COLUMN + " text not null, "
+ KEY_GOLD_HOARDED_COLUMN + " float, "
+ KEY_GOLD_HOARD_ACCESSIBLE_COLUMN + " integer);";
public MyDB(Context context, String name, CursorFactory factory, int version){
super(context, name, factory, version);
}
@Override
public void onConfigure(SQLiteDatabase db) {
Log.d(TAG, "onConfigure");
//API Level 16
// super.onConfigure(db);
}
@Override
public void onCreate(SQLiteDatabase db) {
Log.d(TAG, "onCreate");
//建表
db.execSQL(DATABASE_CREATE);
}
@Override
public void onOpen(SQLiteDatabase db) {
Log.d(TAG, "onOpen");
super.onOpen(db);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.d(TAG, "onUpgrade");
//删除旧表重建新表
db.execSQL("DROP TABLE IF EXISTS "+DATABASE_TABLE);
onCreate(db);
}
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.d(TAG, "onDowngrade");
//API Level 11
// super.onDowngrade(db, oldVersion, newVersion);
db.execSQL("DROP TABLE IF EXISTS "+DATABASE_TABLE);
onCreate(db);
}
}
3) MainActivity.java
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
MyDB myDB;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myDB = new MyDB(getApplication(), MyDB.DATABASE_NAME, null, MyDB.DATABASE_VERSION);
}
public void onClick(View v){
SQLiteDatabase database;
switch(v.getId()){
case R.id.btn_insert:
ContentValues contentValues = new ContentValues();
contentValues.put(MyDB.KEY_GOLD_HOARD_NAME_COLUMN, "gold mountain");
contentValues.put(MyDB.KEY_GOLD_HOARDED_COLUMN, 5.2f);
contentValues.put(MyDB.KEY_GOLD_HOARD_ACCESSIBLE_COLUMN, 1);
database = myDB.getWritableDatabase();
database.insert(MyDB.DATABASE_TABLE, null, contentValues);
database.releaseReference();//equivalent to Closable.close()
break;
case R.id.btn_query:
String[] result_columns = {MyDB.KEY_ID,MyDB.KEY_GOLD_HOARD_NAME_COLUMN,MyDB.KEY_GOLD_HOARDED_COLUMN,
MyDB.KEY_GOLD_HOARD_ACCESSIBLE_COLUMN};
String where = MyDB.KEY_GOLD_HOARD_ACCESSIBLE_COLUMN + "=" +1;
database = myDB.getWritableDatabase();
Cursor cursor = database.query(MyDB.DATABASE_TABLE, result_columns, where, null, null, null, null, null);
StringBuilder sb = new StringBuilder();
while(cursor.moveToNext()){
sb.append(cursor.getInt(cursor.getColumnIndexOrThrow(MyDB.KEY_ID))).append(',')
.append(cursor.getString(cursor.getColumnIndexOrThrow(MyDB.KEY_GOLD_HOARD_NAME_COLUMN))).append(',')
.append(cursor.getFloat(cursor.getColumnIndexOrThrow(MyDB.KEY_GOLD_HOARDED_COLUMN))).append(',')
.append(cursor.getInt(cursor.getColumnIndexOrThrow(MyDB.KEY_GOLD_HOARD_ACCESSIBLE_COLUMN))).append('\n');
}
cursor.close();
database.releaseReference();
if(sb.length()>0){
sb.deleteCharAt(sb.length()-1);
Toast.makeText(this, sb, Toast.LENGTH_SHORT).show();
}
break;
case R.id.btn_update:
ContentValues newValues = new ContentValues();
newValues.put(MyDB.KEY_GOLD_HOARD_NAME_COLUMN, "silver");
newValues.put(MyDB.KEY_GOLD_HOARDED_COLUMN, 3.1f);
String whereU = MyDB.KEY_ID + "=" +1;
database = myDB.getWritableDatabase();
//更新指定行指定列数据
database.update(MyDB.DATABASE_TABLE, newValues, whereU, null);
database.close();
break;
case R.id.btn_delete:
String whereR = MyDB.KEY_ID + "=" + 1;
database = myDB.getWritableDatabase();
//删除指定行数据
database.delete(MyDB.DATABASE_TABLE, whereR, null);
database.close();
break;
case R.id.btn_drop:
database = myDB.getWritableDatabase();
//清空表中数据
database.delete(MyDB.DATABASE_TABLE, null, null);
database.close();
break;
case R.id.btn_queryItem:
queryItem();
break;
case R.id.btn_queryItems:
queryContent();
}
}
//查询指定范围的数据
private void queryContent(){
ContentResolver contentResolver = getContentResolver();
String[] resultColumns = {MyDB.KEY_ID, MyDB.KEY_GOLD_HOARD_NAME_COLUMN,
MyDB.KEY_GOLD_HOARDED_COLUMN, MyDB.KEY_GOLD_HOARD_ACCESSIBLE_COLUMN};
String where = MyDB.KEY_GOLD_HOARD_ACCESSIBLE_COLUMN +"="+1;
Cursor cursor = contentResolver.query(MyContentProvider.CONTENT_URI, resultColumns, where, null, null);
StringBuilder sb = new StringBuilder();
while(cursor.moveToNext()){
sb.append(cursor.getString(cursor.getColumnIndexOrThrow(MyDB.KEY_GOLD_HOARD_NAME_COLUMN))).append(',')
.append(cursor.getFloat(cursor.getColumnIndexOrThrow(MyDB.KEY_GOLD_HOARDED_COLUMN))).append('\n');
}
if(sb.length()>0){
sb.deleteCharAt(sb.length()-1);
Toast.makeText(this, sb, Toast.LENGTH_SHORT).show();
}
}
//查询单行数据
private void queryItem(){
ContentResolver contentResolver = getContentResolver();
String[] resultColumns = {MyDB.KEY_ID, MyDB.KEY_GOLD_HOARD_NAME_COLUMN,
MyDB.KEY_GOLD_HOARDED_COLUMN, MyDB.KEY_GOLD_HOARD_ACCESSIBLE_COLUMN};
//指定行,不再需要where
Uri rowAddress = ContentUris.withAppendedId(MyContentProvider.CONTENT_URI, 2);
Cursor cursor = contentResolver.query(rowAddress, resultColumns, null, null, null);
StringBuilder sb = new StringBuilder();
while(cursor.moveToNext()){
sb.append(cursor.getString(cursor.getColumnIndexOrThrow(MyDB.KEY_GOLD_HOARD_NAME_COLUMN))).append(',')
.append(cursor.getFloat(cursor.getColumnIndexOrThrow(MyDB.KEY_GOLD_HOARDED_COLUMN))).append('\n');
}
if(sb.length()>0){
sb.deleteCharAt(sb.length()-1);
Toast.makeText(this, sb, Toast.LENGTH_SHORT).show();
}
}
}
4) activity_main.xml
5) AndroidManifest.xml