理论知识
ContentProvider 是 Android中用于数据共享的机制,主要是用于进程间(App之间)。
如何进行数据共享?
内容提供者 ContentProvider
提供数据,需要继承这个类,,并重写其中的增删改查方法。
继承 ContentProvider 类并重写增删改查、getType和 onCtreate方法,在新版的Android studio中新建一个ContentProvider会自动在 Mainifest中进行注册。
- URI Authorities:相当于标识,通常由包名+provider组成
- Exported:是否对外暴露
- Enabled:是否生效
ContentProvider 中的方法
- onCreate():该方法在ContentProvider创建后会被调用,当其他应用程序第一次访问ContentProvide时,该ContentProvider会被创建出来,并立即回调该onCreate方法
- getType(Uri uri), 返回 当前Uri所代表的数据的MIME类型。如果该Uri对应数据可能包括多条记录,那么MIME类型字符串应该以 vnd.android.cursor.dir/开头;如果该Uri对应的数据只包含一条记录,那么返回MIME类型字符串应该以vnd.android.cursor.item/开头。
内容观察者 ContentObserver
观察ContentProvider提供的数据,并通知 ContentResolver
内容接收者 ContentResolver
- 处理数据,可以调用其类似数据库操作的增删改查方法,实现数据获取。
- 它提供的方法与ContentProvider一一对应。
- 但不同于sqlite数据库,它接收的不是表名而是一个url,这样可以保证数据的安全性。
什么是URI?
UriMatcher
UriMatcher本质是一个文本过滤器,可以直接得到Uri的path,可以通过调用uriMatcher.addURI()方法添加相对应的返回码
private UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
@Override
public boolean onCreate() {
dataBaseHelper = new DataBaseHelper(getContext());
sqLiteDatabase = dataBaseHelper.getWritableDatabase();
uriMatcher.addURI(AUTHORITIES, DataBaseHelper.STUTDY_SQLITE_TABLE, 0);
return true;
}
@Override
public String getType(Uri uri) {
int code = uriMatcher.match(uri);
if (code == 0) {
return DataBaseHelper.STUTDY_SQLITE_TABLE;
} else {
return null;
}
}
实战演练
App-A ContentProvider
package com.example.androidstudiostudy.contentprovider;
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;
import com.example.androidstudiostudy.database.DataBaseHelper;
public class MyContentProvider extends ContentProvider {
private UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
private String AUTHORITIES = "com.example.androidstudiostydy.provider";
private DataBaseHelper dataBaseHelper;
private SQLiteDatabase sqLiteDatabase;
public MyContentProvider() {
}
@Override
public boolean onCreate() {
dataBaseHelper = new DataBaseHelper(getContext());
sqLiteDatabase = dataBaseHelper.getWritableDatabase();
uriMatcher.addURI(AUTHORITIES, DataBaseHelper.STUTDY_SQLITE_TABLE, 0);
return true;
}
@Override
public String getType(Uri uri) {
int code = uriMatcher.match(uri);
if (code == 0) {
return DataBaseHelper.STUTDY_SQLITE_TABLE;
} else {
return null;
}
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
String tableName = getType(uri);
if (tableName == null) {
return null;
}
return sqLiteDatabase.query(tableName, projection, selection, selectionArgs, null, null, sortOrder);
}
/// 删除
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
String tableName = getType(uri);
// 查询的表不存在
if (tableName == null) {
return -1;
}
return sqLiteDatabase.delete(tableName, selection, selectionArgs);
}
/// 更新
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
String tableName = getType(uri);
// 查询的表不存在
if (tableName == null) {
return -1;
}
return sqLiteDatabase.update(tableName, values, selection, selectionArgs);
}
@Override
public Uri insert(Uri uri, ContentValues values) {
String tableName = getType(uri);
// 查询的表不存在
if (tableName == null) {
return null;
}
long index = sqLiteDatabase.insert(tableName, null, values);
if (index > 0) {
return uri;
} else {
return null;
}
}
}
App-B ContentResolver
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getContentProviderData();
}
// 接收来自其他app的数据
public void getContentProviderData() {
ContentResolver contentResolver = getContentResolver();
Uri uri = Uri.parse("content://com.example.androidstudiostydy.provider/STUTDY_SQLITE_TABLE");
@SuppressLint("Recycle")
// 检查 Cursor 是否为空
Cursor cursor = contentResolver.query(uri, null, null, null, null);
if (cursor != null) {
while(cursor.moveToNext()){
int id = cursor.getInt(0);
String name = cursor.getString(1);
String phone = cursor.getString(2);
String pwd = cursor.getString(3);
Log.d("contentprovider", id + "\t" + name + "\t" + phone + "\t" + pwd);
}
cursor.close();
} else {
Toast.makeText(this, "无法获取内容提供者数据", Toast.LENGTH_LONG).show();
}
}