ContentProvider概览:
我们自己应用的数据库只能给自己使用,无法提供给其他应用直接操作,于是便有了ContentProvider,但在实际开发中很少有应用需要编写自己的ContentProvider 把自己的数据库暴露给别人,一半都是用ContentProvider来访问紫铜应用的数据库,比如系统的短信和联系人。我们学习怎么写ContentProvider是要去了解它实现的原理,其实就是一个URI的匹配 比如android系统的短信应用源代码 里面写URIMatcher 就有content://sms/这个URI 那么我们就可以通过这个URI的匹配 去访问到系统的短信。
下面就来看看怎么读取系统的短信, 监听系统的短信 读取系统的联系人 和添加修改系统的联系人:
1. 读取短信:
_id address date body type(1表示收件 2表示发件) 这几个列名比较常用
这段代码读到了所有 95555发来的短信:
sb = new StringBuilder();
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://sms/");
Cursor cursor = resolver.query(uri, null, "address=?", new String[]{"95555"}, null);
while(cursor.moveToNext()){
String address = cursor.getString(cursor.getColumnIndexOrThrow("address"));
String body = cursor.getString(cursor.getColumnIndexOrThrow("body"));
String content = address+"---"+body+"\n";
sb.append(content);
}
2. 短信窃听器:
谷歌在写ContentProvider的时候 其实注册了一个监听,当内容提供者的数据发生变化时候 我们通过内容观察者可以监听到:关键代码在第六行,我们为这个ContentResolver注册一个内容观察者ContentObserver:
Uri 我们要监听的数据路径 在本例中我们监听所有的短信 所以与contentResolver的一样
Boolean true: 我们的Uri只要是以contentResolver的Uri开头就行了 false: 必须和contentResolver的Uri一样
new myObserver: 继承ContentObserver 重写了i免得change方法,我们要做的事情:打印出最新的一条短信(注意是倒序排列 所以是moveToFirst())
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ContentResolver contentResolver = getContentResolver();
Uri uri = Uri.parse("content://sms/");
contentResolver.registerContentObserver(uri, true, new myObserver(new Handler()));
}
class myObserver extends ContentObserver{
public myObserver(Handler handler) {
super(handler);
// TODO Auto-generated constructor stub
}
@Override
public void onChange(boolean selfChange) {
// TODO Auto-generated method stub
super.onChange(selfChange);
Toast.makeText(MainActivity.this, "已经监听到一条短信", Toast.LENGTH_LONG).show();
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://sms/");
Cursor cursor = resolver.query(uri, null, null, null, null);
cursor.moveToFirst();
String address = cursor.getString(cursor.getColumnIndex("address"));
String body = cursor.getString(cursor.getColumnIndex("body"));
System.out.println(address+"----"+body);
}}
}
3.联系人的应用
系统的联系人与短信有不同的地方就是 数据库的存储不只是一张表,而是3张表:
第一张表是 raw_contacts : 用contact_id保存联系人的ID . Uri是:content://com.android.contacts/raw_contacts
第二张表是data: 用data1来存放数据, mimetype_id存放数据(实际访问不能这个列名,应该用mimetype),raw_contact_id存放这个data对应的ID 。Uri是:content://com.android.contacts/data 看看这张表的结构:
第三张表是mimetype表: 来表示每种数据的类型:1 : EMAIL 5:phone 7:name
获得所有联系人的思路很简单: 先去查询raw_contacts表得到所有的ID 然后用得到的ID去查询data表格,在遍历循环中用mimetype来判断数据类型 来完成自己的业务!