转载请注明出处:内容提供者 ContentProvider、内容观察者ContentObserver_内容提供者和内容观察者交互实现_Mr_Leixiansheng的博客-CSDN博客
作用:跨进程数据共享(使用现有的内容提供者)
(获取联系人为例)
步骤:
1、设置好布局
2、权限添加
3、利用Cursor进行访问
代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/contact_data"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
注册中添加权限
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.leixiansheng.contactstest">
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
主程序
package com.leixiansheng.contactstest;
import android.Manifest;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.provider.ContactsContract;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private ArrayAdapter<String> arrayAdapter;
private List<String> contactList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView) findViewById(R.id.contact_data);
arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, contactList);
listView.setAdapter(arrayAdapter);
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, 1);
} else {
readContacts();
}
}
private void readContacts() {
Cursor cursor = null;
try {
cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
if (cursor != null) {
while (cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contactList.add(name + "\n" + number);
}
arrayAdapter.notifyDataSetChanged();
}
} catch (Exception e) {
e.printStackTrace();
}finally {
if (cursor != null) {
cursor.close();
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case 1:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
readContacts();
} else {
Toast.makeText(this, "Need Permission", Toast.LENGTH_SHORT).show();
}
break;
}
}
}
自定义内容提供者
例:定义一个程序被另一个程序访问修改数据
内容提供者(提供数据)
步骤:
1、构建数据库,新建MySQLiteOpenHelper 类继承SQLiteOpenHelper
public class MySQLiteOpenHelper extends SQLiteOpenHelper {
public MySQLiteOpenHelper(Context context) {
super(context, "person.db", null, 1);
}
/**
* @param context :环境
* @param name :表格名
* @param factory :工厂
* @param version :表格版本
*/
public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, "person.db", null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table person(_id integer primary key autoincrement, name char(10), phone char(20), money integer(10))");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
2、新建类PersonProvider并继承ContentProvider,实现其增删改查
public class PersonProvider extends ContentProvider {
private SQLiteDatabase mDb;
//uri 匹配器,将表格及对应返回值匹配
private UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
{
mUriMatcher.addURI("com.leixiansheng.people", "person", 1); //content://com.leixiansheng.people/person 返回 1
mUriMatcher.addURI("com.leixiansheng.people", "man", 2); //content://com.leixiansheng.people/man 返回 2
//路径后面还可以携带数据, '#' 代表所有数字 long id = ContentUris.parseId(uri) 一般做指定位置查询
mUriMatcher.addURI("com.leixiansheng.people", "man/#", 3); //content://com.leixiansheng.people/man/2 返回 3
}
/**
* 创建时调用
* @return
*/
@Override
public boolean onCreate() {
MySQLiteOpenHelper helper = new MySQLiteOpenHelper(getContext());
mDb = helper.getWritableDatabase();
return false;
}
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
Cursor cursor = null;
if (mUriMatcher.match(uri) == 1) {
cursor = mDb.query("person", projection, selection, selectionArgs, null, null, sortOrder, null);
} else if(mUriMatcher.match(uri)==2){
cursor = mDb.query("man", projection, selection, selectionArgs, null, null, sortOrder, null);
} else if (mUriMatcher.match(uri) == 3) {
long id = ContentUris.parseId(uri); //取出末尾带的数字
cursor = mDb.query("man", projection, "_id", new String[]{"" + id}, null, null, sortOrder, null);
}
return cursor;
}
//返回指定uri 对应的 mimetType
@Nullable
@Override
public String getType(@NonNull Uri uri) {
if (mUriMatcher.match(uri) == 1) {
return "vnd.android.cursor.dir/person"; //person 多条数据
} else if (mUriMatcher.match(uri) == 2) {
return "vnd.android.cursor.dir/man"; //man 多条数据
} else if (mUriMatcher.match(uri) == 3) {
return "vnd.android.cursor.item/man"; //man 单条数据
}
return null;
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
Log.e("PersonProvider", "uri:" + uri);
if (mUriMatcher.match(uri) == 1) {
mDb.insert("person", null, values);
} else if(mUriMatcher.match(uri)==2){
mDb.insert("man", null, values);
}
return uri;
}
@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
int i = 0;
if (mUriMatcher.match(uri) == 1) {
i = mDb.delete("person", selection, selectionArgs);
} else if(mUriMatcher.match(uri)==2){
i = mDb.delete("man", selection, selectionArgs);
}
return i;
}
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
int i = 0;
if (mUriMatcher.match(uri) == 1) {
i = mDb.update("person", values, selection, selectionArgs);
} else if(mUriMatcher.match(uri)==2){
i = mDb.update("man", values, selection, selectionArgs);
}
return i;
}
}
3、 manifest注册申明
<!-- exported:是否对外开放
authorities:访问路径-->
<provider
android:exported="true"
android:authorities="com.leixiansheng.people"
android:name="com.leixiansheng.test2.PersonProvider"/>
到这里,提供内容访问的进程则已经基本完成
新建访问内容 提供者工程项目:
步骤:
通过ContentResolver获取到自定义的内容提供者,Uri是之前在manifest中定义的android:authorities="com.leixiansheng.people",
然后实现对应增删改查
private void queryData() {
ContentResolver resolver = getContentResolver();
Cursor cursor = resolver.query(Uri.parse("content://com.leixiansheng.people/person"), null, null, null);
// Cursor cursor = resolver.query(Uri.parse("content://com.leixiansheng.people/man"), null, null, null);
while (cursor.moveToNext()) {
String name = cursor.getString(1);
String phone = cursor.getString(2);
String money = cursor.getString(3);
Log.e("MainActivity", "name:" + name + ",phone:" + phone + ",money:" + money);
System.out.print("name:" + name + ",phone:" + phone + ",money:" + money);
}
}
private void updateData() {
ContentResolver resolver = getContentResolver();
ContentValues values = new ContentValues();
values.put("money", 2000);
resolver.update(Uri.parse("content://com.leixiansheng.people/person"), values, "name = ?", new String[]{"大白"});
// resolver.update(Uri.parse("content://com.leixiansheng.people/man"), values, "name = ?", new String[]{"大白"});
}
private void deleteData() {
ContentResolver resolver = getContentResolver();
resolver.delete(Uri.parse("content://com.leixiansheng.people/person"), "name = ?", new String[]{"大白"});
// resolver.delete(Uri.parse("content://com.leixiansheng.people/man"), "name = ?", new String[]{"大白"});
}
private void insertData() {
//获取ContentResolver
ContentResolver resolver = getContentResolver();
ContentValues values = new ContentValues();
values.put("name", "小明");
values.put("phone", 123456);
values.put("money", 100);
//访问内容提供者,插入数据
resolver.insert(Uri.parse("content://com.leixiansheng.people/person"), values);
values.clear(); //清空之前数据
values.put("name", "大白");
values.put("phone", 654321);
values.put("money", 500);
//访问内容提供者,插入数据
resolver.insert(Uri.parse("content://com.leixiansheng.people/man"), values);
}
内容观察者ContentObserver
本例:观察短信库是否改变,可用于获取短信验证码
public class MainActivity extends AppCompatActivity {
private PermissionListener mListener;
private ContentResolver mContentResolver;
private MyObserver mObserver = new MyObserver(new Handler());
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
mContentResolver = getContentResolver();
mContentResolver.registerContentObserver(Uri.parse("content://sms"), //监听短信
true,//true 发生变化则通知
mObserver);
}
@Override
protected void onDestroy() {
super.onDestroy();
mContentResolver.unregisterContentObserver(mObserver);
}
class MyObserver extends ContentObserver {
/**
* Creates a content observer.
*
* @param handler The handler to run {@link #onChange} on, or null if none.
*/
public MyObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
Log.e("MyObserver", "短信库改变");
}
}
}