Android ContentObserver 监听短信思路详解
概述
内容观察器ContentObserver给目标内容注册一个观察器,目标内容的数据一旦发生变化,观察器规定好的动作马上触发,从而执行开发者预先定义的代码。

思路
注册一个监听
getContentResolver().registerContentObserver(uri, true, mObserver);
继承 ContentObserver 实现一个用于回调的监听类
private static class SmsGetObserver extends ContentObserver {
private final Context mContext;
public SmsGetObserver(Context context) {
super(new Handler(Looper.getMainLooper()));
this.mContext = context;
}
@SuppressLint("Range")
@Override
public void onChange(boolean selfChange, @Nullable Uri uri) {
super.onChange(selfChange, uri);
// onChange会多次调用,收到一条短信会调用两次onChange
// mUri===content://sms/raw/20
// mUri===content://sms/inbox/20
// 安卓7.0以上系统,点击标记为已读,也会调用一次
// mUri===content://sms
// 收到一条短信都是uri后面都会有确定的一个数字,对应数据库的_id,比如上面的20
Log.d("aabb",uri.toString());
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("AAAA", String.format("sender:%s,content:%s", sender, content));
}
cursor.close();
}
}短信相关权限
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />完整代码
package com.example.cpclient;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import android.annotation.SuppressLint;
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 {
private SmsGetObserver mObserver;
@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,true :表示可以同时匹配其派生的Uri
// 假设UriMatcher 里注册的Uri共有以下类型:
// 1.content://AUTHORITIES/[table]
// 2.content://AUTHORITIES/[table]/#
// 3.content://AUTHORITIES/[table]/[subtable]
// 假设我们当前需要观察的Uri为content://AUTHORITIES/student:
// 如果发生数据变化的 Uri 为 3。
// 当notifyForDescendents为false,那么该ContentObserver会监听不到,但是当notifyForDescendents 为ture,能捕捉该Uri的数据库变化。
mObserver = new SmsGetObserver(this);
getContentResolver().registerContentObserver(uri, true, mObserver);
}
@Override
protected void onDestroy() {
super.onDestroy();
getContentResolver().unregisterContentObserver(mObserver);
}
private static class SmsGetObserver extends ContentObserver {
private final Context mContext;
public SmsGetObserver(Context context) {
super(new Handler(Looper.getMainLooper()));
this.mContext = context;
}
@SuppressLint("Range")
@Override
public void onChange(boolean selfChange, @Nullable Uri uri) {
super.onChange(selfChange, uri);
// onChange会多次调用,收到一条短信会调用两次onChange
// mUri===content://sms/raw/20
// mUri===content://sms/inbox/20
// 安卓7.0以上系统,点击标记为已读,也会调用一次
// mUri===content://sms
// 收到一条短信都是uri后面都会有确定的一个数字,对应数据库的_id,比如上面的20
Log.d("aabb",uri.toString());
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("AAAA", String.format("sender:%s,content:%s", sender, content));
}
cursor.close();
}
}
}拓展
当在你的provider中,别人insert了一条数据,你要告知他是否成功了
使用 notifyChange进行通知回调
getContext().getContentResolver().notifyChange()
案例
@Override
public Uri insert(Uri uri, ContentValues values) {
if (URI_MATCHER.match(uri) == USERS) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
long rowId = db.insert(UserDBHelper.TABLE_NAME, null, values);
if (rowId > 0) {
// 如果添加成功,就利用新记录的行号生成新的地址
Uri newUri = ContentUris.withAppendedId(UserInfoContent.CONTENT_URI, rowId);
// 通知监听器,数据已经改变
getContext().getContentResolver().notifyChange(newUri, null);
}
}
return uri;
}到此这篇关于Android ContentObserver 监听短信的文章就介绍到这了,更多相关Android ContentObserver 监听短信内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
android Tween Animation属性设置方法实例
在Android开发中,Animation是用来给控件制作效果的,本文介绍二种实现方法2013-11-11
Android开发InputManagerService创建与启动流程
这篇文章主要为大家介绍了Android开发InputManagerService创建与启动流程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2022-11-11
Android使用android-wheel实现省市县三级联动
这篇文章主要为大家详细介绍了Android使用android-wheel实现省市县三级联动,具有一定的参考价值,感兴趣的小伙伴们可以参考一下2016-08-08
android图像绘制(六)获取本地图片或拍照图片等图片资源
从SD卡中获取图片资源,或者拍一张新的图片,然后再进行处理(直接处理返回图片/获得图片的地址再处理)接下来为您详细介绍,感兴趣的朋友可以了解下2013-01-01
Android使用友盟集成QQ、微信、微博等第三方分享与登录方法详解
之前的项目第三方分享和登录一直都使用ShareSDK实现的。为了统一使用友盟的全家桶,所以三方分享和登录也就选择了友盟,这里为大家整理出详细方法2018-03-03
Android 中TextureView和SurfaceView的属性方法及示例说明
这篇文章主要介绍了Android 中TextureView和SurfaceView的属性方法及示例说明,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下2022-06-06


最新评论