内容提供者-读取短信内容
我们已经实现向日历中插入提醒事件了
然后我们又从通讯录中获取到联系人数据
接下来,当然连短信也不会放过啦!
我们尝试去读取短信内容,嗯。当然得获取到授权才可以!
源码
Uri
前面我们整下来,不管是向日历里插入提醒事件,还是从通讯录中读取联系人,我们都是从Uri开始的。
provider的地址:
搜索"static {"
真是简单粗暴呀,就一个sms,
所以我们的uri就有了。
Uri uri = Uri.parse("content://sms/");
读取信息内容
public void getSMS(View view) {
Uri uri = Uri.parse("content://sms/");
ContentResolver contentResolver = getContentResolver();
Cursor query = contentResolver.query(uri,null,null,null,null);
String[] columnNames = query.getColumnNames();
while(query.moveToNext()) {
for(String columnName : columnNames) {
Log.d(TAG,columnName + " == " + query.getString(query.getColumnIndex(columnName)));
}
}
query.close();
}
权限
短信的读取和修改也要权限:
竟然没有声明写的权限了?
private void checkSmsPermission() {
int readSmsPermission = checkSelfPermission(Manifest.permission.READ_SMS);
if(readSmsPermission != PackageManager.PERMISSION_GRANTED || writeSmsPermission != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.READ_SMS},PERMISSION_REQUEST_CODE);
}
}
结果返回
@Override
public void onRequestPermissionsResult(int requestCode,@NonNull String[] permissions,@NonNull int[] grantResults) {
if(PERMISSION_REQUEST_CODE == requestCode) {
Log.d(TAG,"grantResults -- > " + grantResults[0]);
}
}
我模拟器返回的都是有权限了,但是"android.permission.WRITE_SMS"这个常量在manifest里竟然没有,所以后面的高版本可能不支持写的权限了,也就是修改短信的权限,同学们写的时候要用机器测试一下。这也是很正常的,这些年google慢慢地收回了一些权限。
读取短信内容
首先我们用模拟器发送一条信息:
这是前面我们代码读取出来的内容:
D/MainActivity: _id == 1
D/MainActivity: thread_id == 4
D/MainActivity: address == 6505551212
D/MainActivity: person == null
D/MainActivity: date == 1573442151375
D/MainActivity: date_sent == 1573499751000
D/MainActivity: protocol == 0
D/MainActivity: read == 1
D/MainActivity: status == -1
D/MainActivity: type == 1
D/MainActivity: reply_path_present == 0
D/MainActivity: subject == null
D/MainActivity: body == You have receive a message.
D/MainActivity: service_center == null
D/MainActivity: locked == 0
D/MainActivity: sub_id == 1
D/MainActivity: error_code == 0
D/MainActivity: creator == com.google.android.apps.messaging
D/MainActivity: seen == 1
应用场景
如果你无法写短信进去,那么你备份数据就做不了的。那我们用这个读取短信的功能干啥呢?
我们可以读取短信,去截取短信验证码呀,然后直接填充到输入框里,不是很好的用户体验么?
比如说:
private static UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
public static final int MATCH_CODE = 1;
static {
sUriMatcher.addURI("sms","#",MATCH_CODE);
}
以上这个是用来校验结果的
接着注册短信内容变化的观察者
final ContentResolver contentResolver = getContentResolver();
Uri uri = Uri.parse("content://sms/");
contentResolver.registerContentObserver(uri,true,new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange,Uri uri) {
if(sUriMatcher.match(uri) == MATCH_CODE) {
Log.d(TAG,"selfChange -- > " + " uri -- > " + uri);
Cursor query = contentResolver.query(uri,null,null,null,null);
if(query.moveToNext()) {
String body = query.getString(query.getColumnIndex("body"));
Log.d(TAG,"body -- > " + body);
handlerMsg(body);
}
query.close();
}
}
});
处理结果:
private void handlerMsg(String body) {
if(body != null && body.startsWith("【阳光沙滩】")) {
//符合条件
//截取数字
Pattern p = Pattern.compile("(?<![0-9])([0-9]{4})(?![0-9])");
Matcher matcher = p.matcher(body);
boolean contain = matcher.find();
if(contain) {
Log.d(TAG,"verifyCode -- > " + matcher.group());
}
}
}
运行结果:
D/MainActivity: selfChange -- > uri -- > content://sms/19
D/MainActivity: body -- > 【阳光沙滩】验证码:4356,15分钟内有效
D/MainActivity: verifyCode -- > 4356
验证码拿到了,设置到UI上,让用户确认一下,没什么事就可以提交啦!