当前位置: 首页 > article >正文

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;
    }

案例代码


http://www.kler.cn/news/324122.html

相关文章:

  • Mysql高级篇(中)——锁机制
  • 前端测试最强教程 - 实现 fake http 和 fake db
  • [SAP ABAP] SELECT-OPTIONS
  • 线程池面试集
  • 「JavaScript深入」深拷贝与浅拷贝,如何手写实现?
  • npm下载淘宝镜像的方式和用法
  • 在一个.NET Core项目中使用RabbitMQ进行即时消息管理
  • 前端注释规范
  • Mac安装manim
  • R包:VennDiagram韦恩图
  • 1.2.3 HuggingFists安装说明-MacOS安装
  • 供应链 | 顶刊POMS论文精读:交易成本经济学(TCE)——供应链效率理论
  • 小白投资理财 - 证券开户
  • WPF MVVM入门系列教程(一、MVVM模式介绍)
  • React 有哪些生命周期
  • 开源服务器管理软件Nexterm
  • 提取出来的ip与我原本的ip是在同一个区吗
  • Python编码系列—Python备忘录模式:掌握对象状态保存与恢复技术
  • 【成神之路】Ambari实战-013-代码生命周期-metainfo-configFiles详解
  • 【Linux】包管理器、vim详解及简单配置
  • 实战C++手写线程池
  • windows11下vscode配置lua环境
  • 1欧几里得聚类提取
  • WPF入门教学二十二 多线程与异步编程
  • Django——admin创建和使用
  • 【Python游戏开发】扫雷游戏demo
  • Linux云计算 |【第四阶段】RDBMS1-DAY2
  • 使用python获取百度一下,热搜TOP数据详情
  • 什么是聚类?
  • Docker数据卷有哪些常见的驱动类型?