Android ContentProvider
一.ContentProvider 使用场景:
1.ContentProvider为存储和读取数据提供了统一的接口
- 使用ContentProvider,应用程序可以实现数据共享
3.android内置的许多数据都是使用ContentProvider形式,供开发者调用的(如视频,音频,图片,通讯录等)
所以ContentProvider很适合跨进程通信,另外ContentProvider的底层是采用 Android中的Binder机制(因此Binder机制很重要)。
发现问题:
此外但是在写ContentProvider的时候,用的它跨进程通信。举个例子:A应用通过ContentProvider暴露有个接口,使B应用可以访问,此时我就考虑到一个问题,如果A应用被系统杀掉,那么B应用还可不可以获取到A应用暴露的数据,那么OK,我们带着问题去写这个ContentProvider。
二.ContentResolver
在ContentProvider的使用过程中,需要借用ContentResolver来控制ContentProvider所暴露处理的接口,作为代理来间接操作ContentProvider以获取数据。
在 Context.java 的源码中如下抽象方法
public abstract ContentResolver getContentResolver();
所以可以在所有继承Context的类中通过 getContentResovler() 方法获取ContentProvider
ContentResolver contentResolver = getContentResovler();
三.写一个A应用MyContentProvider
1.首先在Manifest文件中注册provider,并且定义provider的uri和name
<provider android:name="MyProvider"
android:authorities="cn.test.myprovider"
android:exported="true"
/>
2.自定义一个MyContentProvider需要继承ContentProvider并重写其中的方法。
public class MyProvider extends ContentProvider {
private Context mContext;
DBHelper mDbHelper = null;
SQLiteDatabase db = null;
public static final String AUTOHORITY = "cn.scu.myprovider";
// 设置ContentProvider的唯一标识
public static final int User_Code = 1;
public static final int Job_Code = 2;
// UriMatcher类使用:在ContentProvider 中注册URI
private static final UriMatcher mMatcher;
static{
mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
// 初始化
mMatcher.addURI(AUTOHORITY,"user", User_Code);
mMatcher.addURI(AUTOHORITY, "job", Job_Code);
// 若URI资源路径 = content://cn.scu.myprovider/user ,则返回***User_Code
// 若URI资源路径 = content://cn.scu.myprovider/job ,则返回***Job_Code
}
// 以下是ContentProvider的6个方法
/**
* 初始化ContentProvider
*/
@Override
public boolean onCreate() {
mContext = getContext();
// 在ContentProvider创建时对数据库进行初始化
// 运行在主线程,故不能做耗时操作,此处仅作展示
mDbHelper = new DBHelper(getContext());
db = mDbHelper.getWritableDatabase();
// 初始化两个表的数据(先清空两个表,再各加入一个记录)
//db.execSQL("delete from user");
//db.execSQL("insert into user values('null','Carson');");
//db.execSQL("insert into user values('null','Kobe');");
//db.execSQL("insert into user values(5,'zenmeban');");
db.execSQL("delete from job");
db.execSQL("insert into job values(1,'Android');");
db.execSQL("insert into job values(2,'iOS');");
return true;
}
/**
* 添加数据
*/
@Override
public Uri insert(Uri uri, ContentValues values) {
// 根据URI匹配 URI_CODE,从而匹配ContentProvider中相应的表名
// 该方法在最下面
String table = getTableName(uri);
ContentValues contentValues = new ContentValues();
//contentValues.put("_id","4");
//contentValues.put("name","buzhidao");
// db.execSQL("insert into user values(null,'buzhidao');");
// 向该表添加数据
db.insert(table, null, contentValues);
// 当该URI的ContentProvider数据发生变化时,通知外界(即访问该ContentProvider数据的访问者)
mContext.getContentResolver().notifyChange(uri, null);
// 通过ContentUris类从URL中获取ID
//long personid = ContentUris.parseId(uri);
//System.out.println(personid);
Log.i("wangrui",""+contentValues);
return uri;
}
/**
* 查询数据
*/
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// 根据URI匹配 URI_CODE,从而匹配ContentProvider中相应的表名
// 该方法在最下面
String table = getTableName(uri);
// 通过ContentUris类从URL中获取ID
//long personid = ContentUris.parseId(uri);
//System.out.println(personid);
// 查询数据
return db.query(table,projection,selection,selectionArgs,null,null,sortOrder,null);
}
/**
* 更新数据
*/
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
String table = getTableName(uri);
int count = db.update(table,values,selection,selectionArgs);
if(count>0) {
mContext.getContentResolver().notifyChange(uri, null);
}
return 0;
}
/**
* 删除数据
*/
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// 由于不展示,此处不作展开
String table = getTableName(uri);
return 0;
}
@Override
public String getType(Uri uri) {
// 由于不展示,此处不作展开
return null;
}
/**
* 根据URI匹配 URI_CODE,从而匹配ContentProvider中相应的表名
*/
private String getTableName(Uri uri){
String tableName = null;
switch (mMatcher.match(uri)) {
case User_Code:
tableName = DBHelper.USER_TABLE_NAME;
break;
case Job_Code:
tableName = DBHelper.JOB_TABLE_NAME;
break;
}
return tableName;
}
}
3.创建数据库DBHelper
public class DBHelper extends SQLiteOpenHelper {
// 数据库名
private static final String DATABASE_NAME = "finch.db";
// 表名
public static final String USER_TABLE_NAME = "user";
public static final String JOB_TABLE_NAME = "job";
private static final int DATABASE_VERSION = 1;
//数据库版本号
public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
// 创建两个表格:用户表 和职业表
db.execSQL("CREATE TABLE IF NOT EXISTS " + USER_TABLE_NAME + "(_id INTEGER PRIMARY KEY AUTOINCREMENT," + " name TEXT)");
db.execSQL("CREATE TABLE IF NOT EXISTS " + JOB_TABLE_NAME + "(_id INTEGER PRIMARY KEY AUTOINCREMENT," + " job TEXT)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
四 .写一个查找这个provider的另一个demo,B应用
这个demo中只是用来查找前一个应用提供的 contentProvider,只贴出关键代码
cursor = getContentResolver().query(uri_user, null, null, null, null);
if (cursor != null) {
while (cursor.moveToNext()) {
// int displayName = cursor.getInt(0);
// String number = cursor.getString(1);
// String time = cursor.getString(2);
// 获取联系人姓名
String displayName = cursor.getString(cursor.getColumnIndex(
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
//获取联系人姓名
String number = cursor.getString(cursor.getColumnIndex(
ContactsContract.CommonDataKinds.Phone.NUMBER));
contactsList.add(displayName + "\n" + number + " ..");
}
cursor.close();
}
ok,两个demo到这里就写完了,最后结果说明,从B应用中可以成功获取到A应用的提供的contentProvider,此时如果把A应用从后台杀掉也是可以成功获取到数据。后续会将两个应用的demo上传GitHub。
上一篇: Java中final关键字的深入探究
下一篇: 详解Vue路由钩子及应用场景
推荐阅读
-
android R启动找不到super分区问题
-
Android studio 中找不到 R
-
Android ContentProvider
-
com.android.internal.R 错误: 找不到符号
-
Android LayoutInflater深入分析及应用
-
Android4.4 Uri获取图片及document理解
-
Android编程使用android-support-design实现MD风格对话框功能示例
-
androidpn(安卓信息推送工具) 博客分类: 移动开发 android
-
SQLite外键(Foreign Key)支持 博客分类: android SQLiteSinatraUbuntuDebianSQL
-
Google Map Android API V1中API Key的生成 博客分类: Android androidMapViewapiKeygoogle map