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 监控统状态信息的更多相关文章

  1. Zabbix监控Nginx状态信息

    首先要检查Nginx是否安装了 http_stub_status_module 模块,通过下面的命令可以看到编译参数.yum安装的默认会带有这个模块. [root@kafka60 ~]# /data/ ...

  2. linux系统常用监控系统状态信息命令

    [root@bogon ~]# uptime #平均负载 23:33:21 up 2:09, 3 users, load average: 0.02, 0.05, 0.05 [root@bogon ~ ...

  3. Android中判断网络连接是否可用及监控网络状态

    Android中判断网络连接是否可用及监控网络状态 作者: 字体:[增加 减小] 类型:转载 获取网络信息需要在AndroidManifest.xml文件中加入相应的权限,接下来详细介绍Android ...

  4. Android 获得本地IP地址、外网IP地址、本设备网络状态信息、本地Mac地址

    本地内网IP和外网IP的区别: 根据我的经验一台电脑需要两个ip才可以上网,一个是本地的内网ip 一个是外网的ip 本地的ip 一般是192.168.1.2这种样子  只要在不同的路由器上可以重复 外 ...

  5. Android记录3--ExpandableListView使用+获取SIM卡状态信息

    Android记录3--ExpandableListView使用+获取SIM卡状态信息 2013年8月9日Android记录 ExpandableListView是一个可以实现下拉列表的控件,大家可能 ...

  6. Nginx 开启status用以监控状态信息

    Nginx 可以通过with-http_stub_status_module模块来监控nginx的一些状态信息.1.通过nginx -V来查看是否有with-http_stub_status_modu ...

  7. Android网络性能监控方案

    阿里云 云原生应用研发平台EMAS 刘宝文(木睿) 背景 移动互联网时代,移动端极大部分业务都需要通过App和Server之间的数据交互来实现,所以大部分App提供的业务功能都需要使用网络请求.如果因 ...

  8. Linux watch 监控系统状态

    1.linux下watch命令的基本用法 # watch --helpUsage: watch [-dhntv] [--differences[=cumulative]] [--help] [--in ...

  9. Android 组件系列-----Activity保存状态

    本篇随笔将详细的讲解Activity保存状态的概念,也就是saving activity state. 一.Activity状态保持概念 保存Activity的状态是非常重要的,例如我们在玩一个游戏的 ...

  10. Zabbix 监控 Nginx 状态

    简介: 如何使用 Zabbix 监控 Nginx 状态 ? 1.获取 Nginx 状态( HTTP Stub Status ) shell > /usr/local/nginx/sbin/ngi ...

随机推荐

  1. 【一文秒懂】Ftrace系统调试工具使用终极指南

    [一文秒懂]Ftrace系统调试工具使用终极指南 1.Ftrace是什么 Ftrace是Function Trace的简写,由 Steven Rostedt 开发的,从 2008 年发布的内核 2.6 ...

  2. 【C/C++】宏参数多对一和宏部分替换

    宏参数多对一:使用分号分隔多参数 宏部分替换:替换需要转换的再与后续宏接续 #include <stdio.h> #define _MESS_FAILED() printf("% ...

  3. SQL联结

    1联结 那我们又该如何创建联结呢? So easy! 规定要联结的所有表以及它们如何关联就可以了. 在设置关联条件时,为避免不同表被引用的列名相同,我们需要使用完全限定列名(用一个点分隔表名和列名), ...

  4. Linux复习笔记

    Linux复习笔记 常识说明 目录结构 Linux以树型结构管理文件,其最上层文件夹为 / ,也就是根目录. 如图所示,图中展示了一部分文件夹的结构: 所有的文件夹都属于根目录的子文件夹. 安装好系统 ...

  5. Linux-关机重启和注销

  6. [转帖]NVIDIA超级AI服务器NVIDIA DGX GH200性能介绍

    https://zhuanlan.zhihu.com/p/633219396 2023 年 5 月 28 日NVIDIA宣布推出 NVIDIA DGX GH200,这是首款 100 TB级别的GPU ...

  7. [转帖]PostgreSQL 统计所有数据表各自的总行数

    一般来说,可以使用 count(*) 来获取具体某张表的总行数: SELECT count(0) FROM t_user; 如果想获得所有表的行数信息,可以使用以下 SQL 语句: SELECT re ...

  8. [转帖]shell脚本使用expect自动化交互登录远程主机进行批量关机

    前文 1.目标主机登录用户都为root,且密码一致 2.目标主机开放启动了SSH服务且22号端口可访问(防火墙未进行拦截) 软件介绍 expect Expect是一个用来实现自动和交互式任务进行通信的 ...

  9. Docker 安装Oracle12c的镜像修改字符集 并且进行启动的简单过程

    学习来自 昨天晚上转帖的文章 这里面添加一些自己的内容 首先获取配置文件 git clone https://github.com/oracle/docker-images.git 获取之后比较容易了 ...

  10. ggrep让多行日志-无处遁形!

    相信大家都很喜欢用grep指令,查一下项目中有没有出错的,然后通过logid搜索相关出错的日志和一些关键参数,但是在多行日志的情况下就很难处理了,比如okhttp拦截器中分别打印了url,param和 ...