Android——ContentObserver监听短信

news/2024/10/4 7:25:32/

概述

  • 内容观察器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")@Overridepublic 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,比如上面的20Log.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;@Overrideprotected 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);}@Overrideprotected 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")@Overridepublic 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,比如上面的20Log.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()
  • 案例
   @Overridepublic 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;}

案例代码


http://www.ppmy.cn/news/1533634.html

相关文章

【chrome 插件】初窥

目录结构 -----manifest.json #配置文件 |----content.js #对应操纵浏览器页面 |----background.js #一直运行在后台&#xff0c;负责持久化数据, 负责与服务器交互数据 |----popup.js #自动配置到 popup.html, 有权限操纵 popup.html |----popup.html #插件页面其中 popup.j…

相互作用感知的 3D 分子生成 VAE 模型 - DeepICL 评测

DeepICL 是一个基于相互作用感知的 3D 分子生成模型&#xff0c;能够在目标结合口袋内进行相互作用引导的小分子设计。DeepICL 通过利用蛋白质-配体相互作用的普遍模式作为先验知识&#xff0c;在有限的实验数据下也能实现高度的泛化能力。 一、背景介绍 DeepICL 来源于韩国科学…

MySQL 实验 3:创建数据表

MySQL 实验 3&#xff1a;创建数据表 目录 MySQL 实验 3&#xff1a;创建数据表一、创建数据表的语法二、常用的数据类型1、数值型2、日期时间型3、文本类型 三、查看数据库中的表四、查看表结构 关系数据库中的所有数据都保存在数据表&#xff08;table&#xff09;中。表是数…

React第九章(组件通信)

组件通信Props React 组件使用 props 来互相通信。每个父组件都可以提供 props 给它的子组件&#xff0c;从而将一些信息传递给它。Props 可能会让你想起 HTML 属性&#xff0c;但你可以通过它们传递任何 JavaScript 值&#xff0c;包括对象、数组和函数 以及html 元素&#x…

【C#生态园】构建安全可靠的身份验证:六种C# OAuth认证库全面比较

选择最适合你的C# OAuth认证库&#xff1a;核心功能与使用场景解析 前言 在当今互联网时代&#xff0c;用户身份验证和授权已经成为每个应用程序的关键组成部分。为了简化开发人员的工作并提供安全可靠的解决方案&#xff0c;许多C# OAuth认证库和身份验证服务平台已经涌现出…

Spring Cloud Gateway接入WebSocket:实现实时通信

在现代的微服务架构中&#xff0c;实时通信变得越来越重要。Spring Cloud Gateway作为Spring Cloud生态中的API网关&#xff0c;提供了动态路由、监控、弹性、安全等功能。本文将介绍如何通过Spring Cloud Gateway接入WebSocket&#xff0c;实现服务之间的实时通信。 为什么需…

NOI Linux 2.0 使用指南 Code Blocks 手把手教会你

安装 NOI Linux 2.0 的镜像可以从 NOI 官网下载。(NOI Linux 2.0发布&#xff0c;将于9月1日起正式启用&#xff01;) 可以采用 Virtual Box 或者 VMWare 来安装虚拟机&#xff08;不建议安装实体机&#xff0c;如果想要尝试 Linux 环境&#xff0c;推荐使用 WSL 2.0&#xf…

Java面向对象第二章方法与方法重载练习题

练习1&#xff1a;简易计算器 需求说明 实现简易计算器&#xff0c;分别实现两个整数、三个浮点数的加法运算 package dierzhang;import java.util.Scanner;public class LianxiCounter {public static void main(String[] args) {Scanner sc new Scanner(System.in);//读取…