1、利用ContentObserver监听短信
内容观察器ContentObserver给目标内容注册一个观察器,目标内容的数据一旦发生改变,观察器规定好的动作马上触发,从而执行开发者预定义的代码。
参数原理:
notifyForDescendents 通知子孙后代
false:表示精确匹配,即只匹配Uri。
true可以表示同时匹配其派生的Uri
假设UriMatcher 里注册的Uri共有以下类型
1、content://AUTHORITIES/table
2、content://AUTHORITIES/table/#
3、content://AUTHORITIES/table/subtable
假设我们当前需要的Uri为content://AUTHORITIES/stuent:
如果我们需要发生变化的Uri为3
当notifyForDescendents为false,那么该ContentObserver就监听不到
麻烦的地方:
来到一条短信,onChange可能会执行两到三次
mUri===content://sms/raw/20
mUri===content://sms/inbox/20
android 7.0以上的系统,点击标记为已读,也会调用一次
mUri == content://sms
收到一条短信都是Uri后边都会有一个确切的数字,对应数据库的_id,比如上边的20
参考代码:
package com.example.client;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
public class MonitorSmsActivity extends AppCompatActivity {
SmsGetObserver smsGetObserver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_monitor_sms);
//给指定Uri注册 内容观察器,一旦数据发生变化,就会触发观察器的onChange方法
Uri uri = Uri.parse("content://sms");
/**
* notifyForDescendents 通知子孙后代
* false:表示精确匹配,即只匹配Uri。tru可以表示同时匹配其派生的Uri
* 假设UriMatcher 里注册的Uri共有以下类型
* 1、content://AUTHORITIES/table
* 2、content://AUTHORITIES/table/#
* 3、content://AUTHORITIES/table/subtable
* 假设我们当前需要的Uri为content://AUTHORITIES/stuent:
* 如果我们需要发生变化的Uri为3
* 当notifyForDescendents为false,那么该ContentObserver就监听不到
*/
smsGetObserver = new SmsGetObserver(this);
getContentResolver().registerContentObserver(uri, true, smsGetObserver);
}
@Override
protected void onDestroy() {
super.onDestroy();
getContentResolver().unregisterContentObserver(smsGetObserver);
}
private static class SmsGetObserver extends ContentObserver {
private Context mContext;
public SmsGetObserver(Context context) {
super(new Handler(Looper.getMainLooper()));
this.mContext = context;
}
/**
* 麻烦的地方:来到一条短信,onChange可能会执行两到三次
* mUri===content://sms/raw/20
* mUri===content://sms/inbox/20
* android 7.0以上的系统,点击标记为已读,也会调用一次
* mUri == content://sms
* 收到一条短信都是Uri后边都会有一个确切的数字,对应数据库的_id,比如上边的20
*/
@Override
public void onChange(boolean selfChange, @Nullable Uri uri) {
super.onChange(selfChange, uri);
if (uri == null) {
return;
}
if (uri.toString().contains("content://sms/raw")
|| uri.toString().equals("content://sms")) {
return;
}
//通过内容解析器获取符合条件的结果集游标
Cursor cursor = mContext.getContentResolver().query(uri, new String[]{"address", "body", "date"}, null, null, "date desc");
if(cursor.moveToNext()){
//短信的发送号码
String sender = cursor.getString(cursor.getColumnIndex("address"));
//短信内容
String content = cursor.getString(cursor.getColumnIndex("body"));
Log.d("pansd",String.format("sender:%s,content:%s",sender,content));
}
cursor.close();
}
}
}
执行结果: