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 监控统状态信息
标签:ContentObserver,void,private,public,content,监控,import,Android,android From: https://www.cnblogs.com/zhyan8/p/17233628.html