一、ContentProvider介绍
ContentProvider的底层是Binder,主要用于跨进程访问。
通过实现ContentProvider的query、update、insert、delete等方法即可。
二、ContentProvider创建
三、权限设置
创建时,需要在AndroidMainfest中声明权限 authorities为唯一标识。
<provider
android:name=".MyContentProvider"
android:authorities="com.example.fyq.broadtest" //这是唯一标识,一般写包名
android:permission="com.example.PROVIDER" //这是权限,需要有此权限才可以访问
android:process=":provider"//开启另一进程
android:enabled="true"
android:exported="true"></provider>
四、实现应用访问
同一应用的其他进程或者另一应用来访问结果是一样的,实现如下:
public class ProviderActivity extends Activity {
/**
* 外部访问类,用于访问ContentProvider及数据库
* @param savedInstanceState
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_provider);
Uri uri = Uri.parse("com.example.fyq.broadtest");//android:authorities属性的标识
getContentResolver().query(uri, null, null, null, null);
getContentResolver().query(uri, null, null, null, null);
getContentResolver().query(uri, null, null, null, null);
//======================添加内容
/**
* 访问book表
*/
Uri bookUri = Uri.parse("content://com.example.fyq.broadtest/book");
ContentValues values = new ContentValues();
values.put("_id", 6);
values.put("name", "书名");
getContentResolver().insert(bookUri, values);//插入一本书
//查询所有书
Cursor bookCursor = getContentResolver().query(bookUri, new String[]{"_id", "name"}, null, null, null);
while (bookCursor.moveToNext()) {
Book book = new Book();
book.bookId = bookCursor.getInt(0);
book.bookName = bookCursor.getString(1);
}
bookCursor.close();
//======================添加内容
}
}
五、创建数据库及表的类
/**
* Created by fyq on 2018/5/17.
* 这个类是创建数据库的类
*/
public class DbOpenHelper extends SQLiteOpenHelper {
private static final String DB_NAME = "book_provider.db";//数据库名
public static final String BOOK_TABLE_NAME = "book";
public static final String USER_TABLE_NAME = "user";
private static final int DB_VERSION = 1;
//执行语句 ----PRIMARY主键
private String CREATE_BOOK_TABLE = "CREATE TABLE IF NOT EXISTS" + BOOK_TABLE_NAME + "(_id INTEGER PRIMARY KEY," + "name TEXT";
private String CREATE_USER_TABLE = "CREATE TABLE IF NOT EXISTS" + USER_TABLE_NAME + "(_id INTEGER PRIMARY KEY," + "name TEXT," + "sex INT)";
public DbOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
public DbOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version,
DatabaseErrorHandler errorHandler) {
super(context, name, factory, version, errorHandler);
}
public DbOpenHelper(Context mContext) {
super(mContext, DB_NAME, null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK_TABLE);
db.execSQL(CREATE_USER_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
六、数据库操作类
/**
* 这个类是用于访问数据库,对数据库进行操作的
*/
public class BookContentProvider extends ContentProvider {
private static final String TAG = "BookContentProvider";
//==============二、添加内容====================
/**
*用于对应Uri和Uri_Code
*/
public static final String AUTHORITY = "com.example.fyq.broadtest";//这个是根据AndroidMainfest中唯一标识来命名的
//对Book和User两个不同的对象定义URI的标识
public static final Uri BOOK_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/book");
public static final Uri USER_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/user");
public static final int BOOK_URI_CODE = 0;
public static final int USER_URI_CODE = 1;
private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
sUriMatcher.addURI(AUTHORITY, "book", BOOK_URI_CODE);//通过此方式关联Uri和Uri_Code
sUriMatcher.addURI(AUTHORITY, "user", USER_URI_CODE);
}
private SQLiteDatabase mDb;
private Context mContext;
/**
* 通过Uri获取Uri_Code,根据Uri_Code再得到表名
*/
private String getTableName(Uri uri) {
String tableName = null;
switch (sUriMatcher.match(uri)) {
case BOOK_URI_CODE://知道Code后获取表名
tableName = DbOpenHelper.BOOK_TABLE_NAME;
break;
case USER_URI_CODE:
tableName = DbOpenHelper.USER_TABLE_NAME;
break;
default:
break;
}
return tableName;
}
//===============二、添加内容==================
public BookContentProvider() {
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public boolean onCreate() {
mContext = getContext();
initProviderData();//ContentProvider创建时初始化数据库。此过程不应在主线程中进行,因为耗时
return true;
}
private void initProviderData() {
mDb = new DbOpenHelper(mContext).getWritableDatabase();//DBOpen是继承自SQLiteOpenHelper的
/**
* 之后mDb.execSQL执行SQL语句
*/
}
/**
* 除了query外,其他三个方法会引起数据源改变
* @param uri
* @param projection
* @param selection
* @param selectionArgs
* @param sortOrder
* @return
*/
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
Log.d(TAG, "query: current thread:" + Thread.currentThread().getName());
String table = getTableName(uri);
if (table == null) {
// TODO: Implement this to handle query requests from clients.
throw new UnsupportedOperationException("Not yet implemented");
}
return mDb.query(table, projection, selection, selectionArgs, null, null, sortOrder, null);
}
@Override
public Uri insert(Uri uri, ContentValues values) {
String table = getTableName(uri);
if(table == null) {
// TODO: Implement this to handle requests to insert a new row.
throw new UnsupportedOperationException("Not yet implemented");
}
mDb.insert(table, null, values);
//可能通过ContentProvider的registerContentObserver来注册观察者;通过unre...来解绑
mContext.getContentResolver().notifyChange(uri,null);//通知外界数据有变化
return uri;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
/**
* ignore未写
*/
// TODO: Implement this to handle requests to update one or more rows.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
/**
* ignore未写
*/
// Implement this to handle requests to delete one or more rows.
throw new UnsupportedOperationException("Not yet implemented");
}
}