为了在应用程序之间交换数据,Android提供ContentProvider,ContentProvider是不同应用程序之间进行数据交换的标准API。当一个应用程序需要把自己的数据暴露给其他应用程序使用时,该应用程序可以通过提供ContentProvider来实现;而其他应用程序需要使用这些数据时,可以通过ContentResolver来操作ContentProvider暴露的数据。
一旦某个应用程序通过ContentProvider暴露了自己的数据操作接口,那么不管该应用程序是否启动,其他应用程序都可以通过该接口来操作被暴露的内部数据,包括增加数据、删除数据、修改数据、查询数据等。
虽然大部分使用ContentProvider操作的数据都来自于数据库,但是也可以来自于文件、SharedPreferences、XML或网络等其他存储方式。
总结来说就是跨程序之间的数据共享
外界的程序通过ContentResolver接口可以访问ContentProvider提供的数据,可以通过Context使用getContentResolver()获得。
数据操作:CRUD–insert(),update(),delete(),query()
Uri参数: Uri是ContentResolver和ContentProvider进行数据交换的标识。两部分组成–权限+路径
具体使用过程如下:得到uri字符串后转化为Uri对象
使用Uri.parse()方法,把字符串转化成Uri对象。
如果查询:
Cursor cursor=getContentResolver().query{uri,…(其他参数)}
参数 | 说明 |
---|---|
Uri uri | 指定某个程序下某张表 |
String[] projection | 相当于要查询的字段名 |
String where | 查询的条件 |
String[] whereArgs | 查询条件的占位符插入的参数 |
String sortOrder | 排序方式 |
系统默认有内容提供器,我们正确的uri就能读取系统。下面读取系统联系人显示出来:
读取
public class MainActivity extends AppCompatActivity {
private ListView listView;
private ArrayAdapter adapter;
private List contentlist = new ArrayList();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listview);
adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, contentlist);
listView.setAdapter(adapter);
readConteats();
}
private void readConteats() {
Cursor cursor = null;
try {
cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
while (cursor.moveToNext()) {
String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contentlist.add(displayName + "\n" + number);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null) {
cursor.close();
}
}
}
}
添加权限:
自定义MyProvider继承ContentProvider并实现他的6个方法。
看下这6个方法:
根据uri确定MIME的类型
@Override
public String getType(Uri uri) {
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;
}
插入方法,uri确定插入的表
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
查询方法,uri参数确定那张表
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
return null;
}
初始化方法onCreate,返回True表示成功
@Override
public boolean onCreate() {
return false;
}
类似content://com.example.app.provider/table1
或者再加一个id content://com.example.app.provider/table1/1
content+程序包名+表名+id
关于id的指定,有两种通配符*和#
*–人员长度字符串
#任意长度数字
匹配任意表:
content://com.example.app.provider/*
匹配表的任意一行:
content://com.example.app.provider/table1/#
因为Uri代表了要操作的数据,所以我们很经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher 和ContentUris 。掌握它们的使用,会便于我们的开发工作。UriMatcher类用于匹配Uri,具体使用如下:
1.实例化UriMatcher对象。
//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码
UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
2.使用addURL添加uri,接收三个参数
//如果match()方法匹配content://cn.xxt.provider.personprovider/person路径,返回匹配码为1
sMatcher.addURI(“cn.xxt.provider.personprovider”, “person”, 1);//添加需要匹配uri,如果匹配就会返回匹配码
//如果match()方法匹配content://cn.xxt.provider.personprovider/person/230路径,返回匹配码为2
sMatcher.addURI(“cn.xxt.provider.personprovider”, “person/#”, 2);//#号为通配符
3.调用match()方法,传入uri对象,返回uri的自定义对象,判断调用方调用的表。
//使用uri.parse方法使字符型变量变成uri对象
switch (sMatcher.match(Uri.parse("content://cn.xxt.provider.personprovider/person/10"))) {
case 1
break;
case 2
break;
default://不匹配
break;
}