目录:
- 一、什么是ContentProvider:
- 二、如何使用ContentProvider:
- 第一步.创建类继承ContentProvider:
- 第二步.注册ContentProvider:
- 三、URI:
- 1.常用方法:
- 2.解析URI:
- (1)UriMatcher解析URI:
- (2)ContentUris解析URI:
- 四、什么是ContentResolver:
- 五、如何使用ContentResolver:
- 第一步:获取ContentResolver对象
- 第二步:使用ContentResolver对象进行增删查改
- 六、ContentObserve监听器:
- 第一步:设置ContentProvider发送通知
- 第二步:创建类并继承ContentObserver类
- 第三步:ContentResolver中开启监听:
一、什么是ContentProvider:
当我们想允许自己的应用数据被别的应用进行读取操作,可以让自己的APP实现ContentProvider类,同时注册一个URI,然后其他应用只要使用ContentResolver访问指定URI就可以操作我们APP里的数据了。
二、如何使用ContentProvider:
ContentProvider为数据定义一个URI,其他程序想要操作本数据时,只需要获得一个ContentResolver对象并传入相应的URI,即可操作本URI下的数据。
第一步.创建类继承ContentProvider:
需要重写onCreate( )、delete( )、getType( )、insert( )、query( )、update( )方法。
其中增删查改方法可以用来操作本应用的SQLite数据库。
package com.example.myapplication2;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class MyContentProvider extends ContentProvider{
/*创建ContentProvider时调用,其他应用程序第一次访问ContentProvider时,该ContentProvider会被创建出来,立即回调该方法
*/
@Override
public boolean onCreate() {
return false;
}
/*根据传入的URI查询指定条件下的数据
projection:要查询的列名
selection:where子句的内容
selectionArgs:selection中对应的参数
sortOrder:排序规则
*/
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
return null;
}
/*用于返回指定URI代表的数据的MIME类型
*/
@Nullable
@Override
public String getType(@NonNull Uri uri) {
return null;
}
/*根据传入的URI插入contentValues对应的数据
*/
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {
return null;
}
/*根据传入的URI删除where条件匹配的所有数据
*/
@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
/*根据传入的URI更新更新where条件匹配的数据为contentValues
*/
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues contentValues, @Nullable String s, @Nullable String[] strings) {
return 0;
}
}
第二步.注册ContentProvider:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyApplication"
tools:targetApi="31">
<!--属性依次为:全限定类名,用于匹配的URI,是否允许其他应用通过ContentResolver修改本应用的数据-->
<provider
android:name="com.example.myapplication.MyContentProvider"
android:authorities="uri.mycontentprovider"
android:exported="true"/>
</application>
</manifest>
三、URI:
1.常用方法:
//字符串转URI
Uri uri = Uri.parse("uri.mycontentprovider");
//获取uri中数据部分存入一个List中
List<String> segments = uri.getPathSegments();
2.解析URI:
不同URI代表着不同的操作,所以当ContentProvider接收到URI时,我们需要解析URI才能知道该条URI想进行什么操作。
(1)UriMatcher解析URI:
UriMatcher类用于匹配Uri。当应用程序通过URI访问ContentProvider时,UriMatcher用于检查URI是否符合我们预先定义好的若干条规则,如果符合某条规则,则可使用该URI,返回该条规则的匹配码。
//第一步:创建URI
UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);//常量UriMatcher.NO_MATCH表示Uri不匹配时的返回码
//第二步:设置URI匹配规则
matcher.addURI("uri.mycontentprovider", "studentall", 1);//查询所有学生记录,如果URI为:uri.mycontentprovider/studentall时会返回1
matcher.addURI("uri.mycontentprovider", "students/*", 2);//根据学号和姓名模糊查询获得多个记录。*是字符通配符,可以匹配任何字符
matcher.addURI("uri.mycontentprovider", "student/#", 3);//单个学生,需要根据studentid来判断,#是数字通配符,可以匹配任何数字,例如:将来可以匹配student/001,student/002等
matcher.addURI("uri.mycontentprovider", "insertstudent", 4);//插入学生
matcher.addURI("uri.mycontentprovider", "deletestudent/#", 5);//删除单个学生,需要根据studentid来判断,#将来调用时实参使用学号来代替
matcher.addURI("uri.mycontentprovider", "deleteallstudent", 6;//删除所有学生
matcher.addURI("uri.mycontentprovider", "updatestudent", 7);//修改学生信息
//第三步:在需要匹配的地方调用match()方法检查是否匹配
//点击”查询全部学生“按钮时,ContentResolver会执行query方法,发送URI,ContentProvider捕获到该URI后需要判断匹配规则是否符合,符合才执行查询操作
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
switch (matcher.match(Uri.parse("uri.mycontentprovider/studentall"))){
//URI符合我们设置的匹配规则
case 1:{
//查询操作
}
//URI不匹配
default:{
break;
}
}
}
});
(2)ContentUris解析URI:
ContentUris类用于操作Uri路径后面的ID(唯一标识符)部分。
/*
public static Uri withAppendedId (Uri contentUri, long id):用于为路径加上ID部分。
*/
Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person");
Uri resultUri = ContentUris.withAppendedId(uri, 10);
//生成后的Uri为:content://cn.itcast.provider.personprovider/person/10
/*
public static long parseId (Uri contentUri)该方法用于从路径中获取ID部分。
*/
Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person/10")
long personid = ContentUris.parseId(uri);//获取的结果为:10
四、什么是ContentResolver:
当外部应用需要对ContentProvider中的数据进行增删改查操作时,可以使用ContentResolver类完成。
五、如何使用ContentResolver:
第一步:获取ContentResolver对象
通过Activity的静态方法获取ContentResolver对象。
ContentResolver resolver = this.getContentResolver();
第二步:使用ContentResolver对象进行增删查改
ContentResolver 类提供了与ContentProvider 类相同签名的四个方法,通过给这些方法提供ContentProvider的URI使得这些方法能够调用ContenProvider中与之对应的方法,并得到返回的结果。
ContentResolver resolver = this.getContentResolver();
/*根据传入的URI查询指定条件下的数据
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
*/
resolver.query(ContentProvider的URI,SQL参数...);
/*根据传入的URI插入contentValues对应的数据
public Uri insert(Uri uri, ContentValues values)
*/
resolver.insert(ContentProvider的URI,SQL参数...);
/*根据传入的URI删除where条件匹配的所有数据
public int delete(Uri uri, String selection, String[] selectionArgs)
*/
resolver.delete(ContentProvider的URI,SQL参数...);
/*根据传入的URI更新更新where条件匹配的数据为contentValues
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
*/
resolver.update(ContentProvider的URI,SQL参数...);
六、ContentObserve监听器:
用于监听ContentProvider中单个URI的数据的变化。
第一步:设置ContentProvider发送通知
在ContentProvide能使数据发生变化的方法中调用以下方法:
//该方法的作用是:通知注册在该URI:content://org.myapplication.studenttest/studentall上的监听器:该URI上的数据发生变化
this.getContext().getContentResolver().notifyChange(Uri.parse("content://org.myapplication.studenttest/studentall"), null);
第二步:创建类并继承ContentObserver类
需要重写构造方法和onChange方法。
class MyContentObserve extends ContentObserver{
/*
当观察到Uri代表的数据发生变化时,会触发该方法
*/
@Override
public void onChange(boolean selfChange, @Nullable Uri uri) {
}
public MyContentObserve(Handler handler) {
super(handler);
}
}
第三步:ContentResolver中开启监听:
在需要进行监听的位置加入下面的代码,当该URI下的数据发生变化时,ContentProvider会发送通知,然后就会被下面的代码接收到通知,接收到通知后会调用MyContentObserve的onChange方法。
//注册ContentObserver的监听器,当uri="content://org.myapplication.student/studentall"的数据有变化时,就触发,回调MyObserver对象的onChange(boolean selfChange, Uri uri)方法
contentResolver.registerContentObserver(Uri.parse("content://org.myapplication.studenttest/studentall"),true,new MyContentObserve(new Handler()));