一、为什么需要内容提供者
1-1.回忆定义数据库
- 新建一个类继承SQLiteOpenHelper
public class MyOpenHelper extends SQLiteOpenHelper {
public MyOpenHelper(Context context) {
super(context, "test.db", null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table info(_id integer primary key autoincrement,name varchar(20),money varchar(20))");
db.execSQL("insert into info(name,money) values(?,?)", new String[]{"张三","5000"});
db.execSQL("insert into info(name,money) values(?,?)", new String[]{"李四","3000"});
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
- 打开数据库
MyOpenHelper myOpenHelper = new MyOpenHelper(this);
SQLiteDatabase db = myOpenHelper.getWritableDatabase();
- 读取数据库
Cursor cursor = db.query("info", null, null, null, null, null, null);
if (cursor != null && cursor.getCount() > 0) {
while (cursor.moveToNext()) {
String name = cursor.getString(1);
String phone = cursor.getString(2);
System.out.println("___" + name + ": " + phone);
}
}
- chmod linux下修改文改文件的权限
二、内容提供者的原理
- 内容提供者把数据进行封装,其他应用都是用过内容解析者来访问
- 定义内容提供者,定义一个类继承ContentProvider
三、实现内容提供者的步骤
- 定义一个类继承ContentProvider
public class TestdbProvider extends ContentProvider {
@Override
public boolean onCreate() {
// TODO Auto-generated method stub
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// TODO Auto-generated method stub
return null;
}
@Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
// TODO Auto-generated method stub
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
}
- 在清单文件进行配置
<provider
android:name="com.elnui.day09_db.TestdbProvider"
android:authorities="com.elnui.testdbprovider"
android:exported="true"
android:enabled="true">
</provider>
- Url和Uri说明
- Url:http://www.baidu.com
- Uri:也是一个路径
- 写一个静态代码块,添加匹配规则
static
{
/**
* authority 和清单文件里面定义的要一样
* path 任意的路径
*
* com.elnui.provider/query
* */
sUriMather.addURI("com.elnui.provider", "query", QUERY_SUCCESS);
}
[完整的TestdbProvider类代码]
public class TestdbProvider extends ContentProvider {
// 定义一个urimatcher,路径匹配器
private static final UriMatcher sUriMather = new UriMatcher(UriMatcher.NO_MATCH);
private static final int QUERY_SUCCESS = 1;
private MyOpenHelper myOpenHelper;
// 定义静态代码块,添加匹配规则,规则可以多个
static
{
/**
* authority 和清单文件里面定义的要一样
* path 任意的路径
*
* com.elnui.provider/query
* */
sUriMather.addURI("com.elnui.testdbprovider", "query", QUERY_SUCCESS);
}
@Override
public boolean onCreate() {
myOpenHelper = new MyOpenHelper(getContext());
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
int code = sUriMather.match(uri);
if(code == QUERY_SUCCESS){ // 说明路径匹配成功
/**
* 数据库的查询
* */
SQLiteDatabase db = myOpenHelper.getReadableDatabase();
/**
* table 表名
* columns 查询的列,由参数String[] projection给出
* selection 查询的条件
* selectionArgs 查询的条件参数
* */
Cursor cursor = db.query("info", projection, selection, selectionArgs, null, null, sortOrder);
// 注意,这里的Cursor不能关
return cursor;
}else{
throw new IllegalArgumentException("路径不匹配,请检查");
}
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
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) {
// TODO Auto-generated method stub
return 0;
}
}
- 解析
Uri uri = Uri.parse("content://com.elnui.testdbprovider/query"); // 路径和内容提供者路径一样,前面还应加协议content://
/**
* uri
* projection 查询列
* selection
* selectionArgs
* sortOrder
* */
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
if(cursor != null){
while(cursor.moveToNext()){
String name = cursor.getString(1);
String phone = cursor.getString(2);
System.out.println("___2" + name + ": " + phone);
}
}
四、备份短信案例
public void click1(View v){
try {
// 获取XmlSerializer序列化实例
XmlSerializer serializer = Xml.newSerializer();
// 设置序列化参数
File file = new File(Environment.getExternalStorageDirectory().getPath(),"backup.xml");
FileOutputStream fos = new FileOutputStream(file);
serializer.setOutput(fos, "utf-8");
// 开始写
serializer.startDocument("utf-8", true);
serializer.startTag(null, "smss");
// 使用内容解析者去解析即可
Uri uri = Uri.parse("content://sms/inbox");
Cursor cursor = getContentResolver().query(uri, new String[]{"address","date","body"}, null, null, null);
if(cursor != null){
while(cursor.moveToNext()){
String addr = cursor.getString(0);
String date = cursor.getString(1);
String body = cursor.getString(2);
System.out.println("___" + addr + date + body);
// 写sms节点
serializer.startTag(null, "sms");
// address
serializer.startTag(null, "address");
serializer.text(addr);
serializer.endTag(null, "address");
// body
serializer.startTag(null, "body");
serializer.text(body);
serializer.endTag(null, "body");
// date
serializer.startTag(null, "date");
serializer.text(date);
serializer.endTag(null, "date");
serializer.endTag(null, "sms");
}
serializer.endTag(null, "smss");
serializer.endDocument();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
五、利用内容提供者插入短信
public void click1(View v){
Uri uri = Uri.parse("content://sms");
ContentValues values = new ContentValues();
values.put("address","10086");
values.put("body","你的花费余额不足!");
values.put("date", System.currentTimeMillis());
getContentResolver().insert(uri, values);
}
六、读取联系人的案例
6-1. 三张重要的表
data表
- raw_contact_id ,实际上是raw_contacts表
- mimetype_id ,1-email, 2-im, 3-nickname,5-phone, 7-name, 8-address,实际上对应mimetype表
raw_contacts表
- mimetypes
6-2.实现步骤
- 读raw_contacts表的contact_id字段,获取联系人总数
- 根据raw_contacts_id读取data表的data1列和mimetype列
6-3.小细节
getContentResolver().query(data_uri, new String[]{"data1","mimetype_id"}, "raw_contact_id=?", new String[]{contact_id}, null);
查询的不是data表,查询的是view_data的视图
七、插入联系人
- 先往raw_contact表,contact_id列插入元素
- 同步到data表,data1列存所以联系人数据
public void click1(View v){
Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
Uri data_uri = Uri.parse("content://com.android.contacts/data");
String name = et_name.getText().toString().trim();
String address = et_address.getText().toString().trim();
String emall = et_email.getText().toString().trim();
String phone = et_phone.getText().toString().trim();
// 查询raw_contacts中共几条数据
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
int count = cursor.getCount();
int countid = count+1;
ContentValues values = new ContentValues();
values.put("contact_id", countid);
getContentResolver().insert(uri, values);
////////////////////////////////////////////////////////////////////////
// 插入名字
ContentValues valuesName = new ContentValues();
valuesName.put("data1", name); //把数据插入到data1列
valuesName.put("raw_contact_id", countid);//插入的数据属于那条联系人
valuesName.put("mimetype","vnd.android.cursor.item/name"); //插入的 数据的数据类型是名字
getContentResolver().insert(data_uri, valuesName);
// 插入地址
ContentValues valuesAddress = new ContentValues();
valuesAddress.put("data1", address); //把数据插入到data1列
valuesAddress.put("raw_contact_id", countid);//插入的数据属于那条联系人
valuesAddress.put("mimetype","vnd.android.cursor.item/postal-address_v2"); //插入的 数据的数据类型是名字
getContentResolver().insert(data_uri, valuesAddress);
// 插入email
ContentValues valuesMail = new ContentValues();
valuesMail.put("data1", emall); //把数据插入到data1列
valuesMail.put("raw_contact_id", countid);//插入的数据属于那条联系人
valuesMail.put("mimetype","vnd.android.cursor.item/email_v2"); //插入的 数据的数据类型是名字
getContentResolver().insert(data_uri, valuesMail);
// 插入号码
ContentValues valuesPhone = new ContentValues();
valuesPhone.put("data1", phone); //把数据插入到data1列
valuesPhone.put("raw_contact_id", countid);//插入的数据属于那条联系人
valuesPhone.put("mimetype","vnd.android.cursor.item/phone_v2"); //插入的 数据的数据类型是名字
getContentResolver().insert(data_uri, valuesPhone);
}
八、内容观察者
==内容提供者==是四大组件,需要在清单文件配置
8-1.被观察的提供者中添加
// 数据库被改了,自己发送消息
getContext().getContentResolver().notifyChange(uri, null);
8-2.内容观察者
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 注册内存观察者
Uri uri = Uri.parse("content://com.elnui.testdbprovider");
getContentResolver().registerContentObserver(uri, true, new MyObserver(new Handler()));
}
private class MyObserver extends ContentObserver{
public MyObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
System.out.println("___[ContentObserver]数据被修改了");
super.onChange(selfChange);
}
}