内容提供者的步骤
- 有一个应用程序,带一个私有的数据库,需求是暴露这个私有的数据库。
- 写ContentProvider的一个子类
-
定义匹配规则
- 定义匹配器 UriMatcher
- 定义匹配规则 mUriMatcher.addURI("com.itheima.db", "info", SUCCESS);
- 参数解释:1.主机名 2.path 3.成功校验码
- 根据业务需求实现增删改查的方法
-
在清单文件中声明内容提供者节点
<application节点下 <provider android:name = "要暴露数据的应用程序包名" android:authorities = "主机名">
模板代码:
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
int code = mUriMatcher.match(uri);
if (code == SUCCESS) {
SQLiteDatabase db = helper.getReadableDatabase();
Cursor cursor = db.query("info", projection, selection,
selectionArgs, null, null, sortOrder);
return cursor;
}else{
throw new IllegalArgumentException("uri 不匹配");
}
短信的内容提供者
路径uri /data/data/com.android.telephony/databases/mmssms.db * 备份 public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* 备份短信按钮点击事件
*
* @param v
*/
public void btnOnclick(View v) {
try {
// xml序列化器
XmlSerializer serializer = Xml.newSerializer();
File file = new File(Environment.getExternalStorageDirectory(),
"backup.xml");
FileOutputStream fos = new FileOutputStream(file);
// 初始化序列化器
serializer.setOutput(fos, "utf-8");
serializer.startDocument("utf-8", true);
// 得到内容解析器
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://sms/");
Cursor cursor = resolver.query(uri, new String[] { "address",
"body", "type", "date" }, null, null, null);
serializer.startTag(null, "smss");
while (cursor.moveToNext()) {
serializer.startTag(null, "sms");
serializer.startTag(null, "address");
String address = cursor.getString(cursor
.getColumnIndex("address"));
serializer.text(address);
serializer.endTag(null, "address");
serializer.startTag(null, "body");
String body = cursor.getString(cursor.getColumnIndex("body"));
serializer.text(body);
serializer.endTag(null, "body");
serializer.startTag(null, "type");
String type = cursor.getString(cursor.getColumnIndex("type"));
serializer.text(type);
serializer.endTag(null, "type");
serializer.startTag(null, "date");
long date = cursor.getLong(cursor.getColumnIndex("date"));
serializer.text(String.valueOf(date));
serializer.endTag(null, "date");
Date date2 = new java.sql.Date(date);
System.out.println(address + "!" + body + "!" + type + "!"
+ date2);
serializer.endTag(null, "sms");
}
cursor.close();
serializer.endDocument();
Toast.makeText(this, "备份完成", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(this, "备份失败", Toast.LENGTH_SHORT).show();
}
}
-
还原
解析xml
联系人的内容提供者
联系人的数据uri
data/data/com.android.providers.contacts/databases/contacts2.db 应用场景: 微信,支付宝
重要的三张表
- data表 保存联系人的数据 表中 rwacontactid表示联系人id
- rawcontacts表 保存联系人的id contactid
- mimetypes表 保存联系人数据的类型
如何获取联系人
raw_contacts表的Uri:
RawContacts.CONTENT_URI
data表的Uri:
Data.CONTENT_URI
- 查询raw_contacts表,把联系人的id取出来
- 根据联系人的id,查询data表,把这个id的数据取出来
- 根据mimetype区分数据的类型
Android删除一个联系人后并不是将联系人删除而是将联系人的contact_id设置为null 此时注意程序会报空
添加联系人
- 添加raw_contacts表,添加一条联系人的id
- 操作data表,插入联系人的数据,每个联系人数据都对应一列 rawcontactid
内容观察者
观察内容的作用,当被观察的内容发生改变时会发出通知表示内容改变
在某个需要被观察的项目中 getContent().getContentResolver().notifycation(uri,observer);
在观察者中 getContentResolver().registerContentObserver(uri,是否完全匹配,观察者);
实现步骤:
- 继承ContentObserver
- 实现默认构造方法
-
重写onChange()方法
class MyObserver extends ContentObserver{public MyObserver(Handler handler) { super(handler); // TODO Auto-generated constructor stub } //数据改变时,收到通知时,调用onChange方法 @Override public void onChange(boolean selfChange) { // TODO Auto-generated method stub super.onChange(selfChange); }
发送数据改变的方法:
//参数1:注册内容提供者的uri 参数2:内容观察者对象 getContext().getContentResolver().notifyChange(Uri,Observer)
这里要注意:发送数据改变通知的uri,也就是主机名,要和内容提供者中定义的uri相同,也就是哪个uri发送的就用哪个uri来注册
使用方法
- 获取内容观察者对象
-
注册内容观察者registerContentObserver(),参数:1.要观察的主机名 2.是否精确匹配,true只要以指定的uri开头的数据改变,都能收到通知。如果是false就必须是精确匹配uri才能收到通知,观察者对象。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // content://com.itheima.db/info/103 Uri uri = Uri.parse("content://com.itheima.db/info/"); getContentResolver().registerContentObserver(uri, true, new MyObserver(new Handler())); } private class MyObserver extends ContentObserver{ public MyObserver(Handler handler) {//handler 是一个消息处理器。 super(handler); } @Override public void onChange(boolean selfChange) { System.out.println("哈哈数据库的内容变化了"); super.onChange(selfChange); } }