1,介绍:
内容提供者(Content Provider) 主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序的数据,同时还能保证被访数据的安全性。
2,简单原理图
3,进程间访问对方数据库:
【1】在A进程中创建数据库
public class MyOpenHelper extends SQLiteOpenHelper {
/**
* @param context
* name :数据库名字
* factory: 游标工厂
* version: 数据库的版本
*/
public MyOpenHelper(Context context) {
super(context, "account.db", null, 1);
}
//Called when the database is created for the first time. 当数据库第一次创建的时候调用 那么这个方法适合做表结构的初始化
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table info (_id integer primary key autoincrement,name varchar(20),phone varchar(20),money varchar(20))");
db.execSQL("insert into info ('name','phone','money') values ('张三','138888','2000')");
db.execSQL("insert into info ('name','phone','money') values ('李四','139999','5000')");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
【2】Mian 方法中获取数据库实例,然后查询当前数据库访问自己
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//[1]获取MyOpenHelper实例
MyOpenHelper myOpenHelper = new MyOpenHelper(getApplicationContext());
//[2]创建数据库 代表当前数据库的对象
SQLiteDatabase db = myOpenHelper.getReadableDatabase();
//[3]把张三和李四的信息读取出来
Cursor cursor = db.query("info", null, null, null, null, null, null);
if (cursor!=null && cursor.getCount()>0) {
//[4]★ 想取出数据必须移动游标
while(cursor.moveToNext()){
String name = cursor.getString(1);
String money = cursor.getString(3);
System.out.println("name:"+name+"----"+money);
}
}
}
}
【3】 在A进程中内容提供者暴露出来数据。
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
public class AccountProvider extends ContentProvider {
// [1]定义一个urimatcher路径匹配器
private static final UriMatcher sURIMatcher = new UriMatcher(
UriMatcher.NO_MATCH);
private static final int QUERYSUCESS = 0;
private static final int INSERTSUCESS = 1;
private static final int UPDATESUCESS = 2;
private static final int DELETESUCESS = 3;
private MyOpenHelper myOpenHelper;
// [2]在静态代码块中添加路径
static {
/**
* authority:要和你在清单文件里面声明authority一样
*
* URL:统一资源定位符 https://www.baidu.com/tieba Uri:统一资源标识符
* com.xiaoshuai.db/query uri就是自己定义的一个路径 代表一个含义
*
*/
sURIMatcher.addURI("com.xiaoshuai.db", "query", QUERYSUCESS);
sURIMatcher.addURI("com.xiaoshuai.db", "insert", INSERTSUCESS);
sURIMatcher.addURI("com.xiaoshuai.db", "update", UPDATESUCESS);
sURIMatcher.addURI("com.xiaoshuai.db", "delete", DELETESUCESS);
}
@Override
public boolean onCreate() {
myOpenHelper = new MyOpenHelper(getContext());
return false;
}
// 把这个方法对外暴露出去
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// [1]获取一个匹配码
int code = sURIMatcher.match(uri);
if (code == QUERYSUCESS) {
// 说明路径匹配成功 把这个方法实现 实际上就是在这个方法对数据库进行查询的操作
SQLiteDatabase db = myOpenHelper.getReadableDatabase();
Cursor cursor = db.query("info", projection, selection,
selectionArgs, null, null, sortOrder);
return cursor;
} else {
// 代表路径匹配失败
return null;
// throw new IllegalArgumentException("哥们路径不正确 ,请检查路径");
}
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
int code = sURIMatcher.match(uri);
if (code == INSERTSUCESS) {
// 代表路径匹配成功 把insert方法实现
SQLiteDatabase db = myOpenHelper.getReadableDatabase();
// 代表新插入行的id
long insert = db.insert("info", null, values);
Uri uri2 = Uri.parse("com.xiaoshuai.insert/" + insert);
return uri2;
} else {
return null;
}
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int code = sURIMatcher.match(uri);
if (code == DELETESUCESS) {
// 代表路径匹配成功 把insert方法实现
SQLiteDatabase db = myOpenHelper.getReadableDatabase();
// 代表删除的行数
int delete = db.delete("info", selection, selectionArgs);
return delete;
} else {
return 0;
}
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int code = sURIMatcher.match(uri);
if (code == UPDATESUCESS) {
// 代表路径匹配成功 把insert方法实现
SQLiteDatabase db = myOpenHelper.getReadableDatabase();
// 代表更新的行数
int update = db.update("info", values, selection, selectionArgs);
return update;
} else {
return 0;
}
}
}
【4】在Android Manifest里面注册
<provider
android:authorities="com.xiaoshuai.db"
android:exported="true"
android:name=".AccountProvider" />
【5】在另一个进程中访问A进程的数据库
// 点击按钮往数据库里面插入一条数据
public void click1(View v) {
// [1]由于第一个应用的数据库系统已经通过内容提供者暴露出来 所以可以直接通过内容解析者操作数据库
Uri uri = Uri.parse("content://com.xiaoshuai.db/insert");
// [2]创建contentValues
ContentValues values = new ContentValues();
// 参数1 是表的列名:
values.put("name", "王五");
values.put("money", "100");
// [3]往数据库里面插入了一条数据
Uri insert = getContentResolver().insert(uri, values);
System.out.println("inset:::" + insert);
}
// 点击按钮删除数据库的数据
public void click2(View v) {
// [1]由于第一个应用的数据库系统已经通过内容提供者暴露出来 所以可以直接通过内容解析者操作数据库
Uri uri = Uri.parse("content://com.xiaoshuai.db/delete");
int delete = getContentResolver().delete(uri, "name=?",
new String[] { "王五" });
Toast.makeText(getApplicationContext(), "删除了" + delete + "行", 1).show();
}
// 点击修改一条记录
public void click3(View v) {
Uri uri = Uri.parse("content://com.xiaoshuai.db/update");
ContentValues values = new ContentValues();
values.put("money", "10000");
int update = getContentResolver().update(uri, values, "name=?",
new String[] { "王五" });
Toast.makeText(getApplicationContext(), "修改了了" + update + "行", 1)
.show();
}
// 点击按钮查询数据库
public void click4(View v) {
// 二由于第一个应用程序的数据库已经通过内容提供者暴露出来 所以我使用内容解析者来获取数据
Uri uri = Uri.parse("content://com.xiaoshuai.db/query");
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
if (cursor != null && cursor.getCount() > 0) {
// ★★★ 想取出数据必须移动游标
while (cursor.moveToNext()) {
String name = cursor.getString(1);
String money = cursor.getString(3);
System.out.println("第二个应用~~name:" + name + "----" + money);
}
}
}