Android四大组件之一的ContentProvider
上次说了Activity,这次说一下Android四大组件之一的ContentProvider
1.ContentProvider是什么
ContentProvider是Android四大组件之一 内容提供者
作用:进程之间数据交互&共享,即跨进程通信
2.uri介绍
1.定义:Uniform Resource Identifier,即统一资源标识符
2.作用:唯一标识Content Provider其中的数据,外界进程通过Uri找到对应的ContentProvider其中的数据,在进行数据操作
uri的定义格式
3.简单介绍一下系统的获取
//简单的读取收件箱信息
private void getMsgs() {
Uri parse = Uri.parse("content://sms/");
ContentResolver contentResolver = getContentResolver();
Cursor query = contentResolver.query(parse, new String[]{"address", "date", "type", "body"}, null, null, null
);
if (query == null) {
Toast.makeText(this, "我没有邮箱", Toast.LENGTH_SHORT).show();
} else {
while (query.moveToNext()) {
String address = query.getString(0);
String date = query.getString(1);
String type = query.getString(2);
String body = query.getString(3);
Log.d("MainActivity", "地址:" + address);
Log.d("MainActivity", "时间:" + date);
Log.d("MainActivity", "类型:" + type);
Log.d("MainActivity", "内容:" + body);
Log.d("MainActivity", "======================");
}
query.close();
}
}
//别忘了加权限<uses-permission android:name="android.permission.READ_SMS"/>
//简单的往收件箱里插入一条信息
private void insertMsg() {
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://sms/");
ContentValues conValues = new ContentValues();
conValues.put("address", "18888888888");
conValues.put("type", 1);
conValues.put("date", System.currentTimeMillis());
conValues.put("body", "你是毕牛逼吗?");
resolver.insert(uri, conValues);
Log.e("HeHe", "短信插入完毕~");
}
//别忘了加权限 <uses-permission android:name="android.permission.WRITE_SMS"/>
// <uses-permission android:name="android.permission.SEND_SMS"/>
//简单的读取手机联系人
private void getContacts(){
//①查询raw_contacts表获得联系人的id
ContentResolver resolver = getContentResolver();
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
//查询联系人数据
Cursor cursor = resolver.query(uri, null, null, null, null);
while(cursor.moveToNext())
{
//获取联系人姓名,手机号码
String cName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String cNum = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
Log.d("MainActivity", "姓名:" + cName);
Log.d("MainActivity", "号码:" + cNum.trim());
Log.d("MainActivity", "======================");
}
cursor.close();
}
//别忘了加 读联系人的权限 <uses-permission android:name="android.permission.READ_CONTACTS"/>
//别忘了读写权限的 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
//查询指定电话的联系人信息
private void queryContact(String number){
Uri uri = Uri.parse("content://com.android.contacts/data/phones/filter/" + number);
ContentResolver resolver = getContentResolver();
Cursor cursor = resolver.query(uri, new String[]{"display_name"}, null, null, null);
if (cursor.moveToFirst()) {
String name = cursor.getString(0);
System.out.println(number + "对应的联系人名称:" + name);
}
cursor.close();
}
//添加一个新的联系人
private void AddContact() throws RemoteException, OperationApplicationException {
//使用事务添加联系人
Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
Uri dataUri = Uri.parse("content://com.android.contacts/data");
ContentResolver resolver = getContentResolver();
ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
ContentProviderOperation op1 = ContentProviderOperation.newInsert(uri)
.withValue("account_name", null)
.build();
operations.add(op1);
//依次是姓名,号码,邮编
ContentProviderOperation op2 = ContentProviderOperation.newInsert(dataUri)
.withValueBackReference("raw_contact_id", 0)
.withValue("mimetype", "vnd.android.cursor.item/name")
.withValue("data2", "Coder-pig")
.build();
operations.add(op2);
ContentProviderOperation op3 = ContentProviderOperation.newInsert(dataUri)
.withValueBackReference("raw_contact_id", 0)
.withValue("mimetype", "vnd.android.cursor.item/phone_v2")
.withValue("data1", "13798988888")
.withValue("data2", "2")
.build();
operations.add(op3);
ContentProviderOperation op4 = ContentProviderOperation.newInsert(dataUri)
.withValueBackReference("raw_contact_id", 0)
.withValue("mimetype", "vnd.android.cursor.item/email_v2")
.withValue("data1", "[email protected]")
.withValue("data2", "2")
.build();
operations.add(op4);
//将上述内容添加到手机联系人中~
resolver.applyBatch("com.android.contacts", operations);
Toast.makeText(getApplicationContext(), "添加成功", Toast.LENGTH_SHORT).show();
}
//添加权限
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_PROFILE"/>
4.自定义ContentProvider流程
public class DBOpenHelper extends SQLiteOpenHelper {
final String CREATE_SQL = "CREATE TABLE test(_id INTEGER PRIMARY KEY AUTOINCREMENT,name)";
public DBOpenHelper(Context context, String name, CursorFactory factory,
int version) {
super(context, name, null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_SQL);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
Step 1:自定义ContentProvider类,实现onCreate(),getType(),根据需求重写对应的增删改查方法:
NameContentProvider.java
public class NameContentProvider extends ContentProvider {
//初始化一些常量
private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
private DBOpenHelper dbOpenHelper;
//为了方便直接使用UriMatcher,这里addURI,下面再调用Matcher进行匹配
static{
matcher.addURI("com.jay.example.providers.myprovider", "test", 1);
}
@Override
public boolean onCreate() {
dbOpenHelper = new DBOpenHelper(this.getContext(), "test.db", null, 1);
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
return null;
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
switch(matcher.match(uri))
{
//把数据库打开放到里面是想证明uri匹配完成
case 1:
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
long rowId = db.insert("test", null, values);
if(rowId > 0)
{
//在前面已有的Uri后面追加ID
Uri nameUri = ContentUris.withAppendedId(uri, rowId);
//通知数据已经发生改变
getContext().getContentResolver().notifyChange(nameUri, null);
return nameUri;
}
}
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;
}
}
Step 2:AndroidManifest.xml中为ContentProvider进行注册:
<!--属性依次为:全限定类名,用于匹配的URI,是否共享数据 -->
<provider android:name="com.jay.example.bean.NameContentProvider"
android:authorities="com.jay.example.providers.myprovider"
android:exported="true" />
public class MainActivity extends Activity {
private Button btninsert;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btninsert = (Button) findViewById(R.id.btninsert);
//读取contentprovider 数据
final ContentResolver resolver = this.getContentResolver();
btninsert.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
ContentValues values = new ContentValues();
values.put("name", "测试");
Uri uri = Uri.parse("content://com.jay.example.providers.myprovider/test");
resolver.insert(uri, values);
Toast.makeText(getApplicationContext(), "数据插入成功", Toast.LENGTH_SHORT).show();
}
});
}
}
通过ContentObserver监听ContentProvider 数据的变化
5.ContentProvider 、ContentResolver与ContentObserver之间的关系?
ContentProvider :管理数据,提供数据的增删改查操作,数据源可以是数据库、文件、xml、网络等,Content Provider为这些数据提供了统一的接口,可以用来做进程间数据共享(内容提供者,用于对外提供数据)
ContentResolver :ContentResolver可以不同URI操作不同的ContentProvider中的数据,外部进程可以通过ContentResolver与Content Provider进行交互(notifyChange(Uri)发出消息)(内容解析者,用于获取内容提供者提供数据)(ContentResolver.registerContentObserver()监听消息)
ContentObserver:观察ContentProvider中的数据变化,并将变化通知给外界(内容监听器,可以监听数据的改变状态)