1.ContentProvider简介
☆☆☆ ContentProvider是Android平台在不同应用程序之间实现数据共享的唯一机制;如果一个应用程序需要让别的应用程序能够操作自己的数据,可采用这种机制。
☆☆☆ ContentProvider为存储和获取数据提供统一的接口;以类似数据库中表的形式来组成数据,提供了一种多应用间数据共享的方式;且Android内置的许多数据都是使用该方式供开发者调用的,这时就用到另外一个类(ContentResolver),通过Uri来操作数据从而实现对数据的处理。
☆☆☆ 使用Uri类来实现对数据的处理:
Uri是一个通用资源标志符,将其分为A、B、C、D,4个部分:
A:无法改变的标准前缀,如:“content://”、"tel://"等。当前缀是"content://"时,说明可通过ContentProvider控制这些数据;
B:URI的标识,它通过authorities属性声明,限制一个类的访问,用于限制是哪个ContentProvider能够有权限提供这些数据。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的类名;
C:路径,可以近似的理解为需要操作的数据库中表的名字;
D:如果URI中包含表示需要获取的记录的ID,则就返回该ID对应的数据,如果没有ID,就表示返回全部。
2.使用Uri类和UriMatcher类以及ContentUris类来实现对数据的匹配
☆2.1 可以通过Uri类的parse方法将字符串转换为Uri对象:
Uri uri = Uri.parse(“content://com.android.contentprovider/Topic”);
☆2.2 使用UriMatcher类来实现对数据的匹配:
使用UriMatcher类对象的addURI(contact,path,code)方法注册URI:
方法 | 说明 |
---|---|
public void addURI(String authority, String path, int code) | 往UriMatcher类里添加一个Uri,我们可以理解为UriMatcher为一个Uri的容器,里面包含着要操作的Uri,用于业务逻辑的处理,path相当于Uri中上述所说的路径,也就是想要操作的数据表名,第三个参数code,如果通过下面的match()方法匹配成功就返回这个code值。 |
使用UriMatcher类对象的match(Uri uri)方法来匹配Uri:
方法 | 说明 |
---|---|
public int match(Uri uri) | 与传入的Uri匹配,它会首先与找我们之前通过addURI方法添加进来的Uri匹配,如果匹配成功就返回之前我们设置的code值,否则返回一个值为-1的常量UriMatcher.NO_MATCH。 |
☆2.3.使用ContentUris类来实现对数据的匹配
可以通过该类的withAppendedId(Uri uri, long id)来添加id:
给只有路径的Uri添加id,返回添加了id信息的Uri;
可通过该方法来获取到特定行的数据。
可以通过该类的parseId(Uri uri)来获取Uri中的id信息:
通过该方法可以知道uri具体访问的是哪行的数据。
3.ContentProvider核心类
ContentProvider常用方法:
方法 | 说明 |
---|---|
public abstract boolean onCreate() | 在ContentProvider创建后被调用 |
public abstract Uri insert(Uri uri, Content Values values) | 根据Uri插入values对应的数据 |
public abstract int delete(Uri uri, String selection, String[] selectionArgs) | 根据Uri删除selection指定条件所匹配的全部记录 |
public abstract int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) | 根据Uri修改selection指定条件所匹配的全部记录 |
public abstract Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) | 根据Uri查询出selection指定条件所匹配的全部记录,并且可以指定查询哪些列(projection)以什么方式(sortOrder)排序 |
public abstract String getType(Uri uri) | 返回当前Uri所指向数据的MIME类型,MIME类型由自己定义。如果该Uri对应的数据包括多条记录,那MIME类型的字符串就以vnd.android.cursor.dir/开头, 如果Uri对应的数据只包含一条记录,那MIME类型的字符串就以vnd.android.cursor.item/开头,执行query()方法返回Cursor对象时,系统将不需要再验证,若返回的字符串不能被系统识别,在执行query()方法返回Cursor对象时将需要再验证。 |
☆☆☆Android Studio实现ContentProvider访问联系人数据
1.打开Android Studio,新建工程后,在activity_main.xml中,建立1个Button,1个ListView。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="lession.example.com.learncontentprovider.MainActivity">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:text="获取手机联系人信息"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/button"
android:textSize="20sp"
android:textColor="@android:color/holo_red_dark" />
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/listView" />
</LinearLayout>
</RelativeLayout>
2.在MainActivity.java中,编写相关代码。
package lession.example.com.learncontentprovider;
import android.content.ContentResolver;
import android.database.Cursor;
import android.provider.ContactsContract;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.List;
/*
* 获取手机联系人信息
*/
public class MainActivity extends AppCompatActivity {
private ArrayAdapter<String> adapter;
private List<String> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取ListView实例
ListView lv = (ListView) findViewById(R.id.listView);
//获取Button实例
Button bt = (Button) findViewById(R.id.button);
ContentResolver cr = this.getContentResolver();
final Cursor cs = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,null,null,null);
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
while (cs.moveToNext()){
String name = cs.getString
(cs.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String number = cs.getString
(cs.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
//添加信息
list.add(name+"\n"+number);
}
//更新适配器
adapter.notifyDataSetChanged();
}
});
//获取数据源
list = new ArrayList<>();
//创建适配器
adapter = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,list);
//设置适配器
lv.setAdapter(adapter);
}
}
3.在AndroidManifest.xml中,添加权限。
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
运行结果:
这就是ContentProvider存储数据的使用,如果转载以及CV操作,请务必注明出处,谢谢!