【Android】使用 ContentObserver 监控统状态信息
1 前言
使用ContentProvider实现跨进程通讯 中介绍了自定义 ContentProvider,为外界提供操作 SQLite 的接口。但是大多数情况下,服务端的 ContentProvider 不需要用户编写,用户只需要知道怎么调用就行,比如系统资源。因此,本文将以监控飞行模式状态和最新短信为例,讲解使用 ContentObserver 监控系统状态信息。
常用的系统 URI 取值如下:
| 内容名称 | URI常量名 | URI常量值 |
|---|---|---|
| 联系人 | ContactsContract.Contacts.CONTENT_URI | content://com.android.contacts/contacts |
| 联系人电话 | ContactsContract.CommonDataKinds.Phone.CONTENT_URI | content://com.android.contacts/data/phones |
| 联系人邮箱 | ContactsContract.CommonDataKinds.Email.CONTENT_URI | content://com.android.contacts/data/emails |
| 短信 | Telephony.Sms.CONTENT_URI | content://sms |
| 采信 | Telephony.Mms.CONTENT_URI | content://mms |
| 通话记录 | CallLog.Calls.CONTENT_URI | content://call_log/calls |
2 项目结构

3 代码
(1)权限
在 AndroidManifest.xml 中的 manifest 标签(application 同级标签)下添加读短信权限,如下:
<uses-permission android:name="android.permission.READ_SMS" />
(2)飞行模式监听类
AirplaneObserver.java
package com.zhyan8.content_o;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.provider.Settings;
public class AirplaneObserver extends ContentObserver {
private ContentResolver mResolver;
private Handler mHandler;
private Uri mUri = Settings.System.getUriFor(Settings.System.AIRPLANE_MODE_ON);
public AirplaneObserver(Context context, Handler handler) {
super(handler);
mResolver = context.getContentResolver();
mHandler = handler;
}
@Override
public void onChange(boolean selfChange) {
try {
int isAirplaneOpen = Settings.System.getInt(mResolver, Settings.System.AIRPLANE_MODE_ON);
mHandler.obtainMessage(0x100, isAirplaneOpen).sendToTarget() ;
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
}
public void registerObserver() {
mResolver.registerContentObserver(mUri, false, this);
}
public void unregisterObserver() {
mResolver.unregisterContentObserver(this);
}
}
(3)短信监听类
SMSObserver.java
package com.zhyan8.content_o;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
public class SMSObserver extends ContentObserver {
private ContentResolver mResolver;
private Handler mHandler;
private Uri mUri = Uri.parse("content://sms");
public SMSObserver(Context context, Handler handler) {
super(handler);
mResolver = context.getContentResolver();
mHandler = handler;
}
@Override
public void onChange(boolean selfChange) {
String[] projection = new String[]{"address", "body", "date"}; //查询的列属性
String selection = String.format("date>%d", System.currentTimeMillis()-1000*3); //查询条件(1秒内的短信)
Cursor cursor = mResolver.query(mUri, projection, selection, null,"date desc");
if(cursor!=null && cursor.moveToNext()){
String sender = cursor.getString(0);
String content = cursor.getString(1);
String msg = "sender: " + sender + "\ncontent: \n " + content;
cursor.close();
mHandler.obtainMessage(0x101, msg).sendToTarget();
}
}
public void registerObserver() {
mResolver.registerContentObserver(mUri, true, this);
}
public void unregisterObserver() {
mResolver.unregisterContentObserver(this);
}
}
(4)主类
MainActivity.java
package com.zhyan8.content_o;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
private SMSObserver mSMSObserver;
private AirplaneObserver mAirplaneObserver;
public static final String[] permissions = {"android.permission.READ_SMS"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
if(Build.VERSION.SDK_INT>=23){
requestPermissions(permissions,1);
}
mAirplaneObserver = new AirplaneObserver(this, mHandler);
mSMSObserver = new SMSObserver(this, mHandler);
mAirplaneObserver.registerObserver();
mSMSObserver.registerObserver();
}
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
String content = msg.obj.toString();
switch (msg.what) {
case 0x100:
Log.e("xxx", "飞行模式状态改变了: " + content);
break;
case 0x101:
Log.e("xxx", "收到短信:\n" + content);
break;
}
}
};
@Override
public void onDestroy() {
mAirplaneObserver.unregisterObserver();
mSMSObserver.unregisterObserver();
super.onDestroy();
}
}
4 效果展示
(1)点击2次飞行模式按钮,打印日志如下:
2020-11-23 02:17:56.065 2785-2785/com.zhyan8.content_o E/xxx: 飞行模式状态改变了: 1
2020-11-23 02:17:57.887 2785-2785/com.zhyan8.content_o E/xxx: 飞行模式状态改变了: 0
(2)给10086 发送短信,内容为“11”,会收到【套餐查询】、【语音】、【流量】已使用和剩余信息,打印日志如下:
2020-11-23 02:18:12.856 2785-2785/com.zhyan8.content_o E/xxx: 收到短信:
sender: 10086
content:
【套餐查询】尊敬的客户,您好!截至11月23日2时18分,扣除您已产生的消费(34.76元)后,您当前余额38.71元。 您各项套餐的准实时消费情况如下:
【语音】本月套内包含100分钟,剩余97分钟。
1、校园青春卡大流量套餐48元:本月套内包含国内主叫100分钟,剩余97分钟。
【流量】本月套内包含20GB,具体明细如下:
1、校园青春卡大流量套餐48元:本月套内包含国内流量(套内)20GB,剩余18.30GB。
仅供参考,具体以月结账单为准。
【中国移动】
声明:本文转自【Android】使用 ContentObserver 监控统状态信息
【Android】使用 ContentObserver 监控统状态信息的更多相关文章
- Zabbix监控Nginx状态信息
首先要检查Nginx是否安装了 http_stub_status_module 模块,通过下面的命令可以看到编译参数.yum安装的默认会带有这个模块. [root@kafka60 ~]# /data/ ...
- linux系统常用监控系统状态信息命令
[root@bogon ~]# uptime #平均负载 23:33:21 up 2:09, 3 users, load average: 0.02, 0.05, 0.05 [root@bogon ~ ...
- Android中判断网络连接是否可用及监控网络状态
Android中判断网络连接是否可用及监控网络状态 作者: 字体:[增加 减小] 类型:转载 获取网络信息需要在AndroidManifest.xml文件中加入相应的权限,接下来详细介绍Android ...
- Android 获得本地IP地址、外网IP地址、本设备网络状态信息、本地Mac地址
本地内网IP和外网IP的区别: 根据我的经验一台电脑需要两个ip才可以上网,一个是本地的内网ip 一个是外网的ip 本地的ip 一般是192.168.1.2这种样子 只要在不同的路由器上可以重复 外 ...
- Android记录3--ExpandableListView使用+获取SIM卡状态信息
Android记录3--ExpandableListView使用+获取SIM卡状态信息 2013年8月9日Android记录 ExpandableListView是一个可以实现下拉列表的控件,大家可能 ...
- Nginx 开启status用以监控状态信息
Nginx 可以通过with-http_stub_status_module模块来监控nginx的一些状态信息.1.通过nginx -V来查看是否有with-http_stub_status_modu ...
- Android网络性能监控方案
阿里云 云原生应用研发平台EMAS 刘宝文(木睿) 背景 移动互联网时代,移动端极大部分业务都需要通过App和Server之间的数据交互来实现,所以大部分App提供的业务功能都需要使用网络请求.如果因 ...
- Linux watch 监控系统状态
1.linux下watch命令的基本用法 # watch --helpUsage: watch [-dhntv] [--differences[=cumulative]] [--help] [--in ...
- Android 组件系列-----Activity保存状态
本篇随笔将详细的讲解Activity保存状态的概念,也就是saving activity state. 一.Activity状态保持概念 保存Activity的状态是非常重要的,例如我们在玩一个游戏的 ...
- Zabbix 监控 Nginx 状态
简介: 如何使用 Zabbix 监控 Nginx 状态 ? 1.获取 Nginx 状态( HTTP Stub Status ) shell > /usr/local/nginx/sbin/ngi ...
随机推荐
- 远程连接-ssh
- [转帖]Java 提速之 Large pages【译】
https://juejin.cn/post/7011002046899978253 一.前言 最近花了很多时间在 JVM 的内存预留代码上.它开始是因为我们得到了外部贡献,以支持在 Linux 上使 ...
- [转帖]【数据库架构】NewSQL和PGXC
数据库架构风格 数据库的基本架构 分库分表方案 分布式事务和跨节点查询 PGXC NewSQL:原生分布式数据库 总结 数据库的两种架构风格:NewSQL(代表Google Spanner).Prxo ...
- [转帖]大模型训练,英伟达Turing、Ampere和Hopper算力分析
https://www.eet-china.com/mp/a219195.html 大 GPU 优势在于通过并行计算实现大量重复性计算.GPGPU即通用GPU,能够帮助 CPU 进行非图形相关程序的运 ...
- redis 6源码解析之 事件
redis的事件分为:文件事件和时间事件.文件事件是基于I/O的事务处理,时间事件则是基于时间点的事务处理.redis事件支持的多路复用包含四个实现:ae_epoll.c,ae_evport.c,ae ...
- MySQL 知识点总结(简易版)
MySQL 总结(简易版) 基本语法 0. 1基本语法 # 登录MySQL $ mysql -u root -p12345612 # 退出MySQL数据库服务器 exit; -- 显示所有数据库 sh ...
- 【JS 逆向百例】网洛者反爬练习平台第五题:控制台反调试
关注微信公众号:K哥爬虫,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后 ...
- Unity2019及Unity2020打包android的环境配置
2019安卓打包只有gradle模式了,因为谷歌把adt删了 unity2019可以自定义gradle模板,国内请把repo地址改成阿里云的源 unity2019打apk配置 引擎版本:unity20 ...
- 基于 hugging face 预训练模型的实体识别智能标注方案:生成doccano要求json格式
强烈推荐:数据标注平台doccano----简介.安装.使用.踩坑记录_汀.的博客-CSDN博客_doccano huggingface官网 参考:数据标注平台doccano----简介.安装.使用. ...
- 使用visio如何快速生成一个网格状图案,文档技巧!
如何使用visio如何快速生成一个网格状图案 我的成果图: 操作步骤如下: 1.新建一个visio文件,选择"基本框图".点击创建. 2.从左侧形状窗口中基本形状中选中正方形拖动到 ...