一、ContentProvider
Android中数据存储方式有Shared Preferences、文件储存、SQLite及其他网络存储等,但只能单独一个应用程序达到数据共
享,ContentProvider是一种使数据在不同进程间共享的组件
二、Uri&MIME
-Uri指通用资源标志符,形如
content://com.example.app.provider/music/#
content://前缀表明数据受控于一个内容提供者
com.example.app.provider是指在AndroidMainfest.xml中注册的android:authorities属性所对应的值,表示调用方期望访问
com.example.app这个应用程序
/music指具体操作的表
/#指具体某表下的某条数据(#*均为通配符,#表示任意长度的数字,*表示任意长度的任意字符)
-MIME(Multipurpose Internet Mail Extensions)多功能Internet邮件 扩充服务,形如
vnd.android.cursor.dir/vnd.com.example.app.provider.table1
必须以vnd开头
如果Uri以路径结尾,则后接android.cursor.dir/,如果Uri以id结尾,则后接android.cursor.item/
最后接上vnd.<authority>.<path>
三、使用方法
android中,联系人数据源位于/data/data/com.android.providers.contacts
1、使用现有Content Provider
Android系统中自带电话簿、短信、媒体库都可通过现有Content Provider提供数据
-通过getContentResolver()获取ContentResolver对象,通过ContentResolver对数据进行操作
insert():添加数据
update():更新数据
delete():删除数据
query(uri,projection,selection,selectionArgs,sortOrder):查询数据(uri指定某应用程序下的某一张表,projection指定查询列
名,selection指定约束条件,selectionArgs占位符提供具体
值,sortOrder指定查询结果排序方式)
-查询数据返回Cursor 对象,移动游标遍历Cursor所有行,取出数据
-在AndroidManifiest.xml中声明权限<uses-permission android:name="android.permission.READ_CONTACTS"/>
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ContentResolver cr = getContentResolver();
Cursor c = cr.query(Contacts.CONTENT_URI, new String[]{Contacts._ID , Contacts.DISPLAY_NAME}, null , null , null);
if(c != null){
while (c.moveToNext()){
int id = c.getInt(c.getColumnIndex("_id"));
Log.i("info" , "_id:" + id);
Log.i("info" , "姓名:" + c.getString(c.getColumnIndex(Phone.DISPLAY_NAME)));
//获取手机号
Cursor c1 = cr.query(Phone.CONTENT_URI, new String[]{Phone.NUMBER , Phone.TYPE} , Phone.CONTACT_ID+ "=" + id , null , null);
if(c1 != null){
while(c1.moveToNext()){
int type = c1.getInt(c1.getColumnIndex(Phone.TYPE));
if(type == Phone.TYPE_HOME){
Log.i("info" , "家庭号码:" + c1.getString(c1.getColumnIndex(Phone.NUMBER)));
}else if(type == Phone.TYPE_MOBILE) {
Log.i("info" , "手机号码:" + c1.getString(c1.getColumnIndex(Phone.NUMBER)));
}
}
c1.close();
}
//获取邮箱
Cursor c2 = cr.query(Email.CONTENT_URI , new String[]{Email.DATA , Email.TYPE} , Email.CONTACT_ID+ "=" + id , null ,null);
if(c2 != null){
while(c2.moveToNext()){
int type = c2.getInt(c2.getColumnIndex(Email.TYPE));
if(type == Email.TYPE_WORK){
Log.i("info" , "工作邮箱:" + c2.getString(c2.getColumnIndex(Email.DATA)));
}else if(type == Email.TYPE_HOME){
Log.i("info" , "家庭邮箱:" + c2.getString(c2.getColumnIndex(Email.DATA)));
}
}
c2.close();
}
}
c.close();
}
}
}
插入数据
-在AndroidManifiest.xml中声明权限<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ContentResolver cr = getContentResolver();
ContentValues contentValues = new ContentValues();
Uri uri = cr.insert(ContactsContract.RawContacts.CONTENT_URI , contentValues);
Long raw_contact_id = ContentUris.parseId(uri);
//插入人名
contentValues.clear();
contentValues.put(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID , raw_contact_id);
contentValues.put(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME , "Elon Musk");
contentValues.put(ContactsContract.CommonDataKinds.StructuredName.MIMETYPE , ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
uri = cr.insert(ContactsContract.Data.CONTENT_URI , contentValues);
//插入电话
contentValues.clear();
contentValues.put(ContactsContract.CommonDataKinds.Phone.RAW_CONTACT_ID , raw_contact_id);
contentValues.put(ContactsContract.CommonDataKinds.Phone.NUMBER , "13404329660");
contentValues.put(ContactsContract.CommonDataKinds.Phone.MIMETYPE , ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
uri = cr.insert(ContactsContract.Data.CONTENT_URI ,contentValues);
}
}
2、自定义ContentProvider
-自定义ContentProvider继承ContentProvider实现数据的增删改查
onCreate():初始化ContentProvider时调用,返回true表示初始化成功,false表示失败。只有当ContentResolve访问数据时,才会
被初始化
query():查询数据,查询结果存放在Cursor对象中返回
insert():添加数据,返回用于表示新纪录的Uri
update():更新已有数据,受影响的行数作为返回值
delete():删除数据,受影响的行数作为返回值
getType():根据传入的Uri值返回相应的MIME类型
-在AndroidMainfest.xml中注册自定义ContentProvider并授权
-使用UriMatcher类中的addUri()匹配内容Uri
-使用UriMatcher类中match(uri)返回某个能匹配次Uri对象对应的自定义代码
-在getType()中返回Uri对象所对应的MIME类型