- Android系统提供的ContentProvider
实际上,Android提供了大量的ContentProvider,例如联系人信息,系统的多媒体信息,开发者可以通过ContentResolver来调用系统的ContentProvider.
使用ContentResolver操作Android系统提供的ContentProvider提供的步骤:
- 调用Context的getContentResolver()获取ContentResolver对象
- 根据需要调用ContentResolver对象的CRUD方法。
管理手机联系人
Android系统提供了Contacts应用程序来管理联系人,而且还为联系人提供了ContentProvider,所以其他应用程序也可以来管理联系人。
一般联系人信息存放在data/data/com.android.providers.contacts/databases/contacts2.db中,我们将联系人的数据库文件导出来查看,我们经常用的到有:contacts、data、raw_contacts三张表,有下面几点需要知道:
1)联系人的数据,比如name,number,email都存储在data表的data1列。
2)区分不同联系人的列为raw_contact_id,它对应于raw_contacts表中的contact_id列
3)区分联系人数据类型的列位于mimetype列,其中1表示emial,5表示电话,7表示姓名。
联系人管理中ContentProvider的几个Uri:
- 联系人的Uri==> content://com.android.contacts/contacts (对应contacts 表)
content://com.android.contacts/raw_contacts(对应raw_contacts表)
2、电话号码的Uri==> content://com.android.contacts/data/phones(对应data表)
3、EMAIL的URI==> content://com.android.contacts/data/emails
不过为了方便记忆,系统中提供了以下常量来替代以上的Uri字符串。
Uri CONTACTS_URI = ContactsContract.Contacts.CONTENT_URI;
Uri PHONE_URI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
Uri EMAIL_URI = ContactsContract.CommonDataKinds.Email.CONTENT_URI;
查询联系人信息
private List<Map<String, String>> selectContactsList() {
List<Map<String, String>> list = new ArrayList<Map<String, String>>();
//1.查询rawcontacts表,得到contact_id和display_name
Cursor cursor_rawcontacts = resolver.query(Uri.parse(uri_raw_contacts),
new String[] { "_id", "display_name" }, null, null, null);
while (cursor_rawcontacts.moveToNext()) {
Map<String, String> map = new HashMap<String, String>();
String id = cursor_rawcontacts.getString(0);
String display_name = cursor_rawcontacts.getString(1);
map.put("id", id);
map.put("displayname", display_name);
//2. 以contact_id作为查询条件,查询该contact_id所对应的data表(raw_contact_id)中的phones信息
Cursor cursor_phones = resolver.query(
Uri.parse(uri_contacts_phones), new String[] { "data1" },
"raw_contact_id=?", new String[] { id }, null);
StringBuilder sb_phones = new StringBuilder();
while (cursor_phones.moveToNext()) {
sb_phones.append(cursor_phones.getString(0));
sb_phones.append("|");
}
map.put("phones", sb_phones.toString());
cursor_phones.close();
cursor_phones = null;
// 以id作为查询条件,查询该id所对应的data表中的emails信息
Cursor cursor_emails = resolver.query(
Uri.parse(uri_contacts_emails), new String[] { "data1" },
"raw_contact_id=? ", new String[] { id }, null);
StringBuilder sb_emails = new StringBuilder();
while (cursor_emails.moveToNext()) {
sb_emails.append(cursor_emails.getString(0));
sb_emails.append("|");
}
map.put("emails", sb_emails.toString());
cursor_emails.close();
cursor_emails = null;
list.add(map);
}
return list;
}
插入联系人信息
private boolean insertContact(String displayname, String phone, String email) {
try {
// 步骤:1、先往raw_contacts表中添加一条空白的数据,目的是先获取到联系人的id
ContentValues values = new ContentValues();
Uri uri = resolver.insert(Uri.parse(uri_raw_contacts), values);
// content://com.android.contacts/raw_contacts/23
long id = ContentUris.parseId(uri);
// 步骤2:往data表中先插入display_name。
// 当插入成功后就往raw_contacts表的display_name中也添加了相同的联系人姓名。
values.clear();
values.put("raw_contact_id", id);
values.put("data1", displayname);
values.put("data2", displayname);
values.put("mimetype", "vnd.android.cursor.item/name");
resolver.insert(Uri.parse(uri_contacts_data), values);
// 步骤3:往data表中插入phone
values.clear();
values.put("raw_contact_id", id);
values.put("data1", phone);
values.put("data2", "2");
values.put("mimetype", "vnd.android.cursor.item/phone_v2");
resolver.insert(Uri.parse(uri_contacts_data), values);
// 步骤4:往data表中插入email
values.clear();
values.put("raw_contact_id", id);
values.put("data1", email);
values.put("data2", "1");
values.put("mimetype", "vnd.android.cursor.item/email_v2");
resolver.insert(Uri.parse(uri_contacts_data), values);
return true;
} catch (Exception e) {
// TODO: handle exception
}
return false;
}
读取系统短信
读取系统短信:需要申请相应的权限。
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://sms/inbox");
Cursor cursor = resolver.query(uri, null, null, null, null);
while(cursor.moveToNext()){
String address = cursor.getString(cursor.getColumnIndex("address"));
String body = cursor.getString(cursor.getColumnIndex("body"));
Log.e("短信...", address + body);
}
向系统中写入短信:需申请相应的权限
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://sms/inbox");
ContentValues values = new ContentValues();
values.put("address", "95558"); values.put("body",
"尊敬的xxx,你尾号为xxxx的招商银行卡入账....."); values.put("type", 1);
values.put("person", "招商银行"); values.put("read", 0);
resolver.insert(uri, values);
利用内容观察者实现短信监听
1.短信的Uri为:
resolver = getContentResolver();
//查询系统短信
// querySms();
ContentObserver observer = new ContentObserver(null) {
@Override
public void onChange(boolean selfChange) {
//读出收件箱中的短信(不成功:因为),得到发件人的地址,
//读整个短信息表,通过判断第一条是不是收件箱的信息,来确定现在是收到信息还是发出信息
Cursor cursor = resolver.query(smsUri, null, null, null, null);
cursor.moveToFirst();
String address = cursor.getString(cursor.getColumnIndex(Telephony.Sms.ADDRESS));
int type = cursor.getInt(cursor.getColumnIndex("type"));
Log.e("address ", address);
if (type==1 && address.endsWith("556")) {
//回复一条信息
SmsManager smsManager = SmsManager.getDefault();
// smsManager.sendTextMessage(destinationAddress, scAddress, text, sentIntent, deliveryIntent)
smsManager.sendTextMessage(address, null, "i hate you, you can go die", null, null);
}
}
};
//监听短信收件箱(不成功),如果有新短信,就检查是不要拦截的号码
//监听整个短信数据表(成功),注意:收信息的时候会回调,发信息的时候也会回调观察者的onChange方法
resolver.registerContentObserver(smsUri, true, observer );
3.清单中添加权限:
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.WRITE_SMS"/>
<uses-permission android:name="android.permission.SEND_SMS"/>
补充 关于自定义权限
- 在服务端向系统申请权限---必须申请,否则自定义权限无意义,写在和application同级标签
<permission
android:name="com.qf.myapplication.myprovider.read"
android:label="provider read permission"
android:protectionLevel="normal"/>
<permission
android:name="com.qf.myapplication.myprovider.write"
android:label="provider write permisson"
android:protectionLevel="normal"/>
- 在服务端给provider注册权限
-
<provider
android:name=".MyContentProvider"
android:authorities="com.qf.myapplication.myprovider"
android:enabled="true"
android:exported="true"
android:readPermission="com.qf.myapplication.myprovider.read"
android:writePermission="com.qf.myapplication.myprovider.write"/>
- 在客户端第三方应用申请权限
-
<uses-permission android:name="com.qf.myapplication.myprovider.read"/>
<uses-permission android:name="com.qf.myapplication.myprovider.write"/>