//通知所用注册该Uri的监听者,数据发生了变化
getContext().getContentResolver().notifyChange(uri,null);
/** 内容提供者监听类 */
private ContentObserver contentObserver = new ContentObserver(handler) {
@Override
public boolean deliverSelfNotifications() {
Log.i(TAG ,"deliverSelfNotifications");
return super.deliverSelfNotifications();
}
/**
* ContentProvider的内容发生变化时,触发该方法
* @param selfChange
*/
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
Log.i(TAG ,"onChange-------->");
}
/**
* ContentProvider的内容发生变化时,触发该方法 这个与上方法相比多个Uri
* @param selfChange
*/
@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
Log.i(TAG ,"onChange-------->" + uri);
handler.sendEmptyMessage(0x123);
}
};
private Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
if (msg.what == 0x123){
Toast.makeText(MainActivity.this, "数据发生变化", Toast.LENGTH_SHORT).show();
}
return false;
}
});
public class SmsActivity extends AppCompatActivity {
private Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
if (msg.what == 0x123){
Uri uri= Uri.parse("content://sms/sent");
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
StringBuffer buffer = new StringBuffer();
while (cursor.moveToNext()){
buffer.append("地址:").append(cursor.getString(cursor.getColumnIndex("address")));
buffer.append("收件人:").append(cursor.getString(cursor.getColumnIndex("person")));
buffer.append("内容:").append(cursor.getString(cursor.getColumnIndex("body")));
buffer.append("\n");
}
txt_body.setText(buffer.toString());
Toast.makeText(SmsActivity.this, buffer.toString(), Toast.LENGTH_SHORT).show();
}
return false;
}
});
/** 内容提供者监听类 */
private ContentObserver contentObserver = new ContentObserver(handler) {
@Override
public boolean deliverSelfNotifications() {
return super.deliverSelfNotifications();
}
/**
* ContentProvider的内容发生变化时,触发该方法
* @param selfChange
*/
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
handler.sendEmptyMessage(0x123);
}
/**
* ContentProvider的内容发生变化时,触发该方法 这个与上方法相比多个Uri
* @param selfChange
*/
@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
// handler.sendEmptyMessage(0x123);
}
};
private TextView txt_body;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sms);
txt_body = (TextView) findViewById(R.id.txt_body);
Uri uri= Uri.parse("content://sms");
getContentResolver().registerContentObserver(uri,true,contentObserver);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
requestPermissions(new String[]{Manifest.permission.READ_SMS},0x234);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 0x234){
if (grantResults[0] != 0){
finish();
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
getContentResolver().unregisterContentObserver(contentObserver);
}
}
/**信息箱 全*/
public final static String SMS_URI_ALL = "content://sms/";
/**收件箱*/
public final static String SMS_URI_INBOX = "content://sms/inbox";
/**发件箱*/
public final static String SMS_URI_SEND = "content://sms/sent";
/**草稿箱*/
public final static String SMS_URI_DRAFT = "content://sms/draft";
(1)自定义数据库帮助类继承SQLiteOpenHelp,创建自己的数据库;(2)自定义ContentProvider继承ContentProvider,实现其抽象方法;(3)在配置文件中注册与配置该ContentProvider,如果想要外部应用可以访问该ContentProvider的数据实现共享,要把exported属性值设置为true;(4)使用UriMatcher工具类,注册可用的Uri,确保访问者的Uri的正确性;(5)在自定义的ContentProvider的insert、query、update、delete方法中实现数据库的CRUD操作(其实就是ContentProvider绑定自己的数据库),在必要的地方通知注册该Uri的监听者,该ContentProvider的共享数据已经发生了变化;(6)创建Handle对象,把该Handle对象作为参数去创建监听器对象(ContentObserver),并在OnChange方法中实现自己的业务(共享数据发生变化时,会触发该方法);(7)注册监听;(8)应用推出时,反注册该监听;
public class SQLiteOpenHelperUtil extends SQLiteOpenHelper {
/**数据库名*/
private static final String DB_NAME = "DBStudent";
/**表名*/
public static final String TABLE_NAME = "GradeOne";
public static String ID = "_id";
public static String STUDENT_ID = "studentId";
public static String MESSAGE = "message";
public static String SQL = "create table if not exists GradeOne ( _id integer primary key autoincrement, studentId integer , message varchar ) ";
public SQLiteOpenHelperUtil(Context context) {
super(context, DB_NAME, null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(SQL);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
public class MyContentProvide extends ContentProvider{
@Override
public boolean onCreate() {
return false;
}
@Nullable
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
return null;
}
@Nullable
@Override
public String getType(Uri uri) {
return null;
}
@Nullable
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return 0;
}
}
android:name=".MyContentProvide"
android:authorities="com.lzb.provide.myContentProvide"
android:exported="true" />
/**标识码*/
public static final int CODE_ID_1 = 1;
public static final int CODE_ID_2 = 2;
public static final String HOST = "com.lzb.provide.myContentProvide";
/**路径*/
public static final String PATH = "students";
/**初始化UriMatcher工具类*/
private static UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
// # 为通配符
uriMatcher.addURI(HOST,PATH,CODE_ID_1);
uriMatcher.addURI(HOST,PATH + "/#",CODE_ID_2);
}
public boolean onCreate() {
sqLiteOpenHelperUtil = new SQLiteOpenHelperUtil(getContext());
return sqLiteOpenHelperUtil != null;
}
public String getType(Uri uri) {
//根据前面注册的Uri返回对应的标识码,如果找不到返回-1
int code = uriMatcher.match(uri);
switch (code){
case CODE_ID_1:
//vnd.android.cursor.dir/
return SHARE_LIST_TYPE;
case CODE_ID_2:
//vnd.android.cursor.item/
return SHARE_ITEM_TYPE;
default:
throw new IllegalArgumentException("Unknown Uir :" + uri);
}
}
public Uri insert(Uri uri, ContentValues values) {
// 首先是看Uri和我们自定义的是否匹配,,匹配则将数据属性插入到数据库中并同志更新
SQLiteDatabase sqLiteDatabase = sqLiteOpenHelperUtil.getWritableDatabase();
if (uriMatcher.match(uri) != CODE_ID_1) {
throw new IllegalArgumentException("Unknown/Invalid URI : " + uri);
}
//行 id
long rowID = sqLiteDatabase.insert(SQLiteOpenHelperUtil.TABLE_NAME,null,values);
if (rowID != -1){ //添加数据成功
//通知所用注册该Uri的监听者,数据发生了变化
getContext().getContentResolver().notifyChange(uri,null);
}
return Uri.parse(SCHEME + "://" + HOST + "/" + PATH + "/" + values.getAsInteger(SQLiteOpenHelperUtil.STUDENT_ID));
}
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
// 首先是看Uri和我们自定义的是否匹配,,匹配则将数据属性插入到数据库中并同志更新
SQLiteDatabase sqLiteDatabase = sqLiteOpenHelperUtil.getReadableDatabase();
//SQLiteQueryBuilder是一个构造SQL查询语句的辅助类
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
//根据前面注册的Uri返回对应的标识码,如果找不到返回-1
int code = uriMatcher.match(uri);
Cursor cursor = null;
switch (code){
case CODE_ID_1:
builder.setTables(SQLiteOpenHelperUtil.TABLE_NAME);
break;
case CODE_ID_2:
//设置要查询的表名
builder.setTables(SQLiteOpenHelperUtil.TABLE_NAME);
//添加条件
builder.appendWhere(SQLiteOpenHelperUtil.STUDENT_ID + "=" + uri.getPathSegments().get(1));
break;
default:
throw new IllegalArgumentException("Unknown Uir :" + uri);
}
//使用负责类开始查询数据库
cursor = builder.query(sqLiteDatabase,projection,selection,selectionArgs,null,null,sortOrder);
return cursor;
}
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
// 首先是看Uri和我们自定义的是否匹配,,匹配则将数据属性插入到数据库中并同志更新
SQLiteDatabase sqLiteDatabase = sqLiteOpenHelperUtil.getWritableDatabase();
//根据前面注册的Uri返回对应的标识码,如果找不到返回-1
int code = uriMatcher.match(uri);
long studentId = 0;
String where ;
switch (code){
case CODE_ID_1:
if (!TextUtils.isEmpty(selection)){
where = "(" + selection + ")";
}else {
where = "";
}
break;
case CODE_ID_2:
if (!TextUtils.isEmpty(selection)){
where = "(" + selection + ") AND ";
}else {
where = "";
}
String segment = uri.getPathSegments().get(1);
studentId = Long.valueOf(segment);
where += "(" + SQLiteOpenHelperUtil.STUDENT_ID + "=" + studentId + ")";
break;
default:
throw new IllegalArgumentException("Unknown Uir :" + uri);
}
//受影响行数
int count = 0;
if (values.size() > 0 ){
count = sqLiteDatabase.update(SQLiteOpenHelperUtil.TABLE_NAME,values,where,selectionArgs);
getContext().getContentResolver().notifyChange(uri,null);
}
return count;
}
说明:该方法根据Uri更新匹配selection条件的所有记录,values为数据源,这个类似上面的查询操作,对于标识码为CODE_ID_1,CODE_ID_2的对应Uri更新条件不一样,不过这里不能使用SQLiteQueryBuilder帮助类了,要用原始的方式添加条件,再进行更新操作,最后不要忘记了执行代码行:getContext().getContentResolver().notifyChange(uri,null)通知注册该Uri的监听者,数据发生了变化。
(6)delete方法的实现
public int delete(Uri uri, String selection, String[] selectionArgs) {
// 首先是看Uri和我们自定义的是否匹配,,匹配则将数据属性插入到数据库中并同志更新
SQLiteDatabase sqLiteDatabase = sqLiteOpenHelperUtil.getWritableDatabase();
//根据前面注册的Uri返回对应的标识码,如果找不到返回-1
int code = uriMatcher.match(uri);
long studentId = 0;
String where ;
switch (code){
case CODE_ID_1:
if (!TextUtils.isEmpty(selection)){
where = "(" + selection + ")";
}else {
where = "";
}
break;
case CODE_ID_2:
if (!TextUtils.isEmpty(selection)){
where = "(" + selection + ") AND ";
}else {
where = "";
}
String segment = uri.getPathSegments().get(1);
studentId = Long.valueOf(segment);
where += "(" + SQLiteOpenHelperUtil.STUDENT_ID + "=" + studentId + ")";
break;
default:
throw new IllegalArgumentException("Unknown Uir :" + uri);
}
//受影响行数
int count = sqLiteDatabase.delete(SQLiteOpenHelperUtil.TABLE_NAME, where, selectionArgs);
getContext().getContentResolver().notifyChange(uri,null);
return count;
}
说明:分析同上。
MyContentProvider完整实现代码
6 创建监听器对象
private Uri uri;
private Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
if (msg.what == 0x123){
if (uri != null){
Cursor cursor = contentResolver.query(uri,null,null,null,null);
if (null != cursor){
cursor.moveToNext();
int id = cursor.getInt(cursor.getColumnIndex(SQLiteOpenHelperUtil.STUDENT_ID));
String message = cursor.getString(cursor.getColumnIndex(SQLiteOpenHelperUtil.MESSAGE));
Toast.makeText(MainActivity.this, ("ID=" + id + " ; message=" + message), Toast.LENGTH_SHORT).show();
}
}else {
Toast.makeText(MainActivity.this, "数据发生变化", Toast.LENGTH_SHORT).show();
}
}
return false;
}
});
/** 内容提供者监听类 */
private ContentObserver contentObserver = new ContentObserver(handler) {
@Override
public boolean deliverSelfNotifications() {
Log.i(TAG ,"deliverSelfNotifications");
return super.deliverSelfNotifications();
}
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
Log.i(TAG ,"onChange-------->");
}
@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
Log.i(TAG ,"onChange-------->" + uri);
handler.sendEmptyMessage(0x123);
}
};
7 注册监听
protected void onResume() {
super.onResume();
contentResolver = getContentResolver();
/**
* 参数:
* 一 uri:该监听器所要监听的ContentProvide的uri
* 二 notifyForDescendants:假设注册监听的Uri为 content://abc notifyForDescendants为 true
* 那么Uri为content://abc/lzb、 content://abc/xxx的数据发生变化时,
* 也能触发监听器,否则不能触发监听器
* 三 observer:监听器实例
*/
contentResolver.registerContentObserver(MyContentProvide.CONTENT_URI, true, contentObserver);
}
8 反注册监听
@Override
protected void onDestroy() {
super.onDestroy();
contentResolver.unregisterContentObserver(contentObserver);
}
Activity完整实现代码
完整项目代码
当然对上述的ContentProvider进行暴露测试:
完整暴露测试项目示例代码
参考:
《疯狂Android讲义》
http://blog.csdn.net/qinjuning/article/details/7047607
http://blog.csdn.net/a497393102/article/details/44223219