目录
一,ContentProvider
二,Uri和UriMatcher工具类
1,Uri
2,UriMatcher
三,自定义ContentProvider
1,准备数据源
2,创建ContentProvider子类
3,在Manifest文件中注册ContentProvider
四,使用ContentResolver访问数据
五,获取系统中CP的数据
1,获取通话记录
2,管理多媒体内容
一,ContentProvider
ContentProvider内容提供者,是一种实现不同应用间共享数据的标准api,当应用想要提供数据时,就提供ContentProvider,其他应用通过ContentResolver来接收数据;
ContentProvider以Uri的形式对外提供数据,其他应用使用ContentResolver通过Uri来访问数据;
ContentProvider是单例模式的,多个ContentResolver请求数据时,是委托给同一个CP对象来操作的;
二,Uri和UriMatcher工具类
1,Uri
Uri的结构和网站URL命名规则类似:
Uri举例:content://org.edu.provider/words
- content://:这部分是Android固定的
- org.edu.provider:这部分是ContentProvider中的authority,结构一般为包名.provider
- words:资源部分,根据资源不同这部分不同
通过Uri提供的静态方法parse()来实现将字符串转换为Uri:
- Uri uri = Uri.parse("content://org.edu.p../words")
2,UriMatcher
帮助ContentProvider操作Uri,进行Uri判断和注册等功能;
(1)UriMatcher通过构造器构造:
UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
//UriMatcher.NO_MATCH 表示不匹配任何路径的返回码(返回-1)
(2)注册Uri,只有注册过的Uri才能被访问:
//Uri的authorities
private static String AUTHORITIES = "com.example.contentprovider.ContentProvider.provider";
//Uri的标识码,用于标识唯一的资源
private static Integer BOOK_CODE = 0;
//注册Uri authorities + 资源名(表名)+ 标识码
matcher.addURI(AUTHORITIES, "tb_books", BOOK_CODE);
//最终Uri格式为"content://com.example.contentprovider.ContentProvider.provider/tb_books/0"
(3)通过int match(Uri uri)方法来判断Uri的对应的标识符,找不到返回-1:
private String getTable(Uri uri) {
String tableName = "";
if(matcher.match(uri) == BOOK_CODE)tableName = "tb_books";
return tableName;
}
三,自定义ContentProvider
- 准备数据源:可以是文件存储,Sqlite数据库等数据源;
- 创建ContentProvider:自定义一个类继承ContentProvider,并重写增删改查等方法;
- Manifest文件中注册ContentProvider;
1,准备数据源
(1)以Sqlite数据库为数据源,创建SqliteOpenHelper类:
public class SqliteHelper extends SQLiteOpenHelper {
public SqliteHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table if not exists tb_books(" +
"id Integer primary key autoincrement, " +
"name varchar(20) not null" +
");"
);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
2,创建ContentProvider子类
(2)创建ContentProvider,重写增删改查等方法,使用UriMatcher注册Uri:
public class MyContentProvider extends ContentProvider {
private SQLiteDatabase bookDB;
private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
private static String AUTHORITIES = "com.example.contentprovider.ContentProvider.provider";
private static Integer BOOK_CODE = 0;
//注册Uri
public MyContentProvider() {
matcher.addURI(AUTHORITIES, "tb_books", BOOK_CODE);
}
@Override
public String getType(Uri uri) {
return null;
}
private String getTable(Uri uri) {
String tableName = "";
if(matcher.match(uri) == BOOK_CODE)tableName = "tb_books";
return tableName;
}
@Override
public boolean onCreate() {
//获取Sqlite数据库
SqliteHelper sqliteHelper = new SqliteHelper(
getContext(),
"bookDB.db",
null,
1
);
bookDB = sqliteHelper.getWritableDatabase();
//插入数据
ContentValues contentValuesBooks = new ContentValues();
contentValuesBooks.put("name", "book1");
bookDB.insert("tb_books", null, contentValuesBooks);
return true;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
String table = getTable(uri);
if(table.isEmpty()){
return null;
}else {
long insert = bookDB.insert(table, null, values);
if(insert > 0)return uri;
else return null;
}
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
String table = getTable(uri);
if(table.isEmpty()){
return -1;
}else {
int delete = bookDB.delete(table, selection, selectionArgs);
return delete;
}
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
String table = getTable(uri);
if(table.isEmpty()){
return null;
}else {
Cursor cursor = bookDB.query(table, projection, selection, selectionArgs, null, null,sortOrder);
return cursor;
}
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
String table = getTable(uri);
if(table.isEmpty()){
return -1;
}else {
int update = bookDB.update(table, values, selection, selectionArgs);
return update;
}
}
}
3,在Manifest文件中注册ContentProvider
四,使用ContentResolver访问数据
(1)通过getContentResolver()方法获取ContentResolver对象:
ContentResolver contentResolver = getContentResolver();
(2)获取Uri:
Uri uri = Uri.parse("content://com.example.contentprovider.ContentProvider.provider/tb_books");
(3)通过ContentResolver调用增删改查等方法:
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding = null;
private ContentResolver contentResolver;
private Uri uri;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
contentResolver = getContentResolver();
uri = Uri.parse("content://com.example.contentprovider.ContentProvider.provider/tb_books");
binding.btnAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialogUtil.showDialog(
MainActivity.this,
"添加",
"id",
"书名",
new AlertDialogUtil.DialogClickCallback() {
@Override
public void onClick(DialogInterface dialog, int which, String input1, String input2) {
ContentValues contentValues = new ContentValues();
contentValues.put("id", Integer.valueOf(input1));
contentValues.put("name", input2);
Uri insert = contentResolver.insert(uri, contentValues);
if (insert != null) {
Toast.makeText(MainActivity.this, "插入成功", Toast.LENGTH_SHORT).show();
} else
Toast.makeText(MainActivity.this, "插入失败", Toast.LENGTH_SHORT).show();
}
}
);
}
});
binding.btnDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialogUtil.showDialog(
MainActivity.this,
"删除",
"id",
"书名",
new AlertDialogUtil.DialogClickCallback() {
@Override
public void onClick(DialogInterface dialog, int which, String input1, String input2) {
String selection = "id = ?";
String[] selectionArgs = {input1};
int delete = contentResolver.delete(uri, selection, selectionArgs);
if(delete > 0){
Toast.makeText(MainActivity.this, "删除成功", Toast.LENGTH_SHORT).show();
}else
Toast.makeText(MainActivity.this, "删除失败", Toast.LENGTH_SHORT).show();
}
}
);
}
});
binding.btnUpdate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialogUtil.showDialog(
MainActivity.this,
"修改",
"id",
"书名",
new AlertDialogUtil.DialogClickCallback() {
@Override
public void onClick(DialogInterface dialog, int which, String input1, String input2) {
ContentValues contentValues = new ContentValues();
contentValues.put("name", input2);
String selection = "id = ?";
String[] selectionArgs = {input1};
int update = contentResolver.update(uri, contentValues, selection, selectionArgs);
if(update > 0){
Toast.makeText(MainActivity.this, "修改成功", Toast.LENGTH_SHORT).show();
}else
Toast.makeText(MainActivity.this, "修改失败", Toast.LENGTH_SHORT).show();
}
}
);
}
});
binding.btnQuery.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Cursor cursor = contentResolver.query(uri, null, null, null, null);
StringBuffer result = new StringBuffer();
if(cursor == null){
Toast.makeText(MainActivity.this, "查询失败", Toast.LENGTH_SHORT).show();
}else{
while(cursor.moveToNext()){
int indexOfName = cursor.getColumnIndex("name");
int indexOfId = cursor.getColumnIndex("id");
int id = cursor.getInt(indexOfId);
String name = cursor.getString(indexOfName);
result.append("id: " + id + ", name: " + name + "\n");
}
}
binding.tvResult.setText(result);
}
});
}
}
五,获取系统中CP的数据
Android系统应用会采用CP(ContentProvider)的形式提供一些开放数据,只要知道相关的Uri。我们就可以直接通过ContentResolver来访问这些数据;
1,获取通话记录
通话记录的Uri为:CallLog.Calls.CONTENT_URI
获取通话记录用到的常量:
- CallLog.Calls._ID: "_id"
- CallLog.Calls.CACHED_NAME:”name”
- CallLog.Calls.NUMBER:”number”
- CallLog.Calls.TYPE:”type” CallLog.Calls.DATE:”date”
- CallLog.Calls.DURATION:”duration”
2,管理多媒体内容
此CP支持的Uri如下:
- MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
- MediaStore.Audio.Media.INTERNAL_CONTENT_URI
- MediaStore.Images.Media.EXTERNAL_CONTENT_URI
- MediaStore.Images.Media.INTERNAL_CONTENT_URI
- MediaStore.Video.Media.EXTERNAL_CONTENT_URI
- MediaStore.Video.Media.INTERNAL_CONTENT_URI
- Content://sms/outbox 发送箱短信URI
- Content://sms/sent 收信箱短信URI
- Content://sms/draft 草稿箱短信URI