一、内容提供者简介
内容提供者(ContentProvider)是Android系统四大组件之一,用于保存和检索数据,是Android系统中不同应用程序之间共享数据的接口。
ContentProvider是不同应用程序之间进行数据交换的标准API,以Uri形式对外提供数据,允许其他应用操作本应用数据。其他应用则使用ContentResolver,并根据ContentProvider提供的Uri操作指定数据。

二、创建一个内容提供者
定义一个类继承android.content包下的ContentProvider类(抽象类)。子类需要重写它的onCreate()、delete()、getType()、insert()、query()、update()这几个抽象方法。
ContentProvider是四大组件之一,必须要在清单文件中注册。
<provider
android:name="cn.itcast.db.PersonDBProvider"
android:authorities="cn.itcast.db.personprovider">
</provider>
Uri简介
ContentProvider的几个抽象方法,这几个抽象方法中有一个参数Uri,它代表了数据的操作方法。Uri是由scheme、authorites、path三部分组成。

scheme:“content://”是一个标准的前缀,表明这个数据被内容提供者所 控制,它不会被修改;
authorities:“cn.itcast.db.personprovider”是在清单文件中指定的android:authorities属性值,该值必须唯一,它表示了当前的内容提供者;
path:“/person”代表资源(或者数据),当访问者需要操作不同数据时,这个部分是动态改变的
Uri.parse(String str)方法是将字符串转化成Uri对象的。为了解析Uri对象,Android系统提供了一个辅助工具类UriMatcher用于匹配Uri。––UriMatcher中的常用方法如表所示:
| 方法名称 | 方法说明 |
| public UriMatcher(int code) | 创建UriMatcher对象时调用,参数通常使用UriMatcher.NO_MATCH,表示路径不满足条件返回-1 |
| public void addURI(String authority, String path, int code) | 添加一组匹配规则,authority即Uri的authoritites部分,path即Uri的path部分 |
| public int match(Uri uri) | 匹配Uri与addURI方法相对应,匹配成功则返回addURI方法中传入的参数code的值。 |
三、案例—读取联系人信息
接下来通过一个案例“读取联系人信息”讲解如何使用内容提供者暴露数据。该案例实现了查询自己暴露的数据,并将数据捆绑到ListView控件中的功能。

布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<Button
android:onClick="click"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="备份短信" />
</RelativeLayout>
Java文件:
public class SmsInfo {
private long date; //时间
private int type; //类型
private String body; //短信内容
private String address; // 发送地址
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
//构造方法
public SmsInfo() {
}
//构造方法
public SmsInfo(long date, int type, String body, String address,int id) {
this.date = date;
this.type = type;
this.body = body;
this.address = address;
this.id = id;
}
//构造方法
public SmsInfo(long date, int type, String body, String address) {
this.date = date;
this.type = type;
this.body = body;
this.address = address;
}
public long getDate() {
return date;
}
public void setDate(long date) {
this.date = date;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
public class SmsUtils {
//将短息信息保存至sdcard目录下的backup2.xml文件中
public static void backUpSms(List<SmsInfo> smsInfos,Context context) {
try {
XmlSerializer serializer = Xml.newSerializer();
File file = new File(Environment.getExternalStorageDirectory(),
"sms.xml");
FileOutputStream os = new FileOutputStream(file);
// 初始化 序列号器 指定xml数据写入到哪个文件 并且指定文件的编码方式
serializer.setOutput(os, "utf-8");
serializer.startDocument("utf-8", true);
//构建根节点
serializer.startTag(null, "smss");
for (SmsInfo info : smsInfos) {
//构建父节点开始标签
serializer.startTag(null, "sms");
serializer.attribute(null, "id", info.getId() + "");
//构建子节点body
serializer.startTag(null, "body");
serializer.text(info.getBody());
serializer.endTag(null, "body");
//构建子节点address
serializer.startTag(null, "address");
serializer.text(info.getAddress());
serializer.endTag(null, "address");
//构建子节点type
serializer.startTag(null, "type");
serializer.text(info.getType() + "");
serializer.endTag(null, "type");
//构建子节date
serializer.startTag(null, "date");
serializer.text(info.getDate() + "");
serializer.endTag(null, "date");
//父节点结束标签
serializer.endTag(null, "sms");
}
serializer.endTag(null, "smss");
serializer.endDocument();
os.close();
Toast.makeText(context, "备份成功", 0).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(context, "备份失败", 0).show();
}
}
}
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//点击Button时触发的方法
public void click(View view) {
// content://sms 查询系统所有短信的uri
Uri uri = Uri.parse("content://cn.itcast.contentprovider.personprovider/query");
//获取ContentResolver对象
ContentResolver resolver = getContentResolver();
Cursor cursor = resolver.query(uri, new String[] { "name", "number"}, null, null, null);
while (cursor.moveToNext()) {
String name = cursor.getString(0);
String number = cursor.getString(1);
System.out.println("===:"+name+","+number);
}
cursor.close();
}
/*
public void click(View view) {
// content://sms 查询系统所有短信的uri
Uri uri = Uri.parse("content://sms/");
//获取ContentResolver对象
ContentResolver resolver = getContentResolver();
//通过ContentResolver对象查询系统短信
Cursor cursor = resolver.query(uri, new String[] { "address", "date",
"type", "body" }, null, null, null);
List<SmsInfo> smsInfos = new ArrayList<SmsInfo>();
while (cursor.moveToNext()) {
String address = cursor.getString(0);
long date = cursor.getLong(1);
int type = cursor.getInt(2);
String body = cursor.getString(3);
SmsInfo smsInfo = new SmsInfo(date, type, body, address);
smsInfos.add(smsInfo);
}
cursor.close();
SmsUtils.backUpSms(smsInfos, this);
}*/
}

