运行效果图:
预备知识:
为了监听指定的ContentProvider的数据的改变,需要通过ContentResolver向指定Uri注册CotentObserver监听器。ContentResolver提供了如下方法来注册监听器:
publicfinal void registerContentObserver(Uriuri, boolean notifyForDescendents, ContentObserver observer)
参数:uri :该监听器所监听的ContentProvider的Uri。
notifyForDescendents :为false 表示精确匹配,即只匹配该Uri,为true 表示可以同时匹配其派生的Uri。
observer:ContentObserver派生的监听器实例。
取消注册监听器:
public finalvoid unregisterContentObserver(ContentObserver observer)
功能:取消对给定Uri的观察
参数: observer ContentObserver的派生类实例。
ContentObserver——内容观察者,目的是观察(捕捉)特定Uri引起的数据库的变化,继而做一些相应的处理,它类似于数据库技术中的触发器(Trigger),当ContentObserver所观察的Uri发生变化时,便会触发它。触发器分为表触发器、行触发器,相应地ContentObserver也分为“表“ContentObserver、“行”ContentObserver,当然这是与它所监听的Uri MIME Type有
关的。
ContentObserver类介绍:
接收回调的更改内容。必须由被添加到一个ContentObservable对象实现。
构造方法:
Public Constructors |
|
ContentObserver(Handler handler) onChange() will happen on the provider Handler. |
说明:所有 ContentObserver的派生类都需要调用该构造方法
参数:handler Handler对象。可以是主线程Handler(这时候可以更新UI 了),也可以是任何Handler对象。
常用方法:
Public Methods |
|
boolean |
deliverSelfNotifications() Returns true if this observer is interested in notifications for changes made through the cursor the observer is registered with. |
final void |
dispatchChange(boolean selfChange) |
void |
onChange(boolean selfChange) This method is called when a change occurs to the cursor that is being observed. |
说明:
void onChange(booleanselfChange)
功能:当观察到的Uri发生变化时,回调该方法去处理。所有ContentObserver的派生类都需要重载该方法去处理逻辑。
参数:selfChange 回调后,其值一般为false,该参数意义不大(我也不懂,理解方法最重要)。
观察特定Uri的步骤如下:
1、 创建我们特定的ContentObserver派生类,必须重载父类构造方法,必须重载onChange()方法去处理回调后的功能实现
2、 利用context.getContentResolover()获得ContentResolove对象,接着调用registerContentObserver()方法去注册内容观察者
如://为content://sms的数据改变注册监听器getContentResolver().registerContentObserver(Uri.parse
("content://sms"), true, new SmsObserver(new Handler()));
3、 由于ContentObserver的生命周期不同步于Activity和Service等,因此,在不需要时,需要手动的调用unregisterContentObserver()去取消注册。
短信相关权限:
<!-- 发送消息--><uses-permission android:name="android.permission.SEND_SMS"/>
<!-- 阅读消息-->
<uses-permission android:name="android.permission.READ_SMS"/>
<!-- 写入消息-->
<uses-permission android:name="android.permission.WRITE_SMS" />
<!-- 接收消息 -->
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
相关的协议:
content://sms/sent
content://sms/draft
content://sms/outbox
content://sms/failed
content://sms/queued
数据库中sms相关的字段及说明:
字段 |
说明 |
_id |
短信序号,如100 |
thread_id |
对话的序号,如100,与同一个手机号互发的短信,其序号是相同的 |
address |
发件人地址,即手机号,如+86138138000 |
person |
发件人,如果发件人在通讯录中则为具体姓名,陌生人为null |
date |
日期,long型,如1346988516,可以对日期显示格式进行设置 |
protocol |
协议0SMS_RPOTO短信,1MMS_PROTO彩信 |
read |
是否阅读0未读,1已读 |
status |
短信状态-1接收,0complete,64pending,128failed |
type |
短信类型1是接收到的,2是已发出 |
body |
短信具体内容 |
service_center |
短信服务中心号码编号,如+8613800755500 |
应用实例:
package com.jph.monitorsms; import java.text.SimpleDateFormat; import java.util.Date; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.widget.TextView; import android.widget.Toast; import android.app.Activity; import android.database.ContentObserver; import android.database.Cursor; /** * Describe:</br> * 获取用户正在发送的短信 * 本实例通过为content://sms的数据改变注册监听器来 * 获取手机正在发送的消息。 * @author JPH * Date:2014.07.20 * */ public class MonitorSms extends Activity { TextView txtView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); txtView=(TextView)findViewById(R.id.txtView); //为content://sms的数据改变注册监听器 getContentResolver().registerContentObserver(Uri.parse ("content://sms"), true, new SmsObserver(new Handler())); } //一个继承自ContentObserver的监听器类 class SmsObserver extends ContentObserver{ public SmsObserver(Handler handler) { super(handler); // TODO Auto-generated constructor stub } @Override public void onChange(boolean selfChange) { // TODO Auto-generated method stub //查询发送向箱中的短信 Cursor cursor=getContentResolver().query(Uri.parse( "content://sms/outbox"), null, null, null, null); //遍历查询结果获取用户正在发送的短信 while (cursor.moveToNext()) { StringBuffer sb=new StringBuffer(); //获取短信的发送地址 sb.append("发送地址:"+cursor.getString(cursor.getColumnIndex("address"))); //获取短信的标题 sb.append("\n标题:"+cursor.getString(cursor.getColumnIndex("subject"))); //获取短信的内容 sb.append("\n内容:"+cursor.getString(cursor.getColumnIndex("body"))); //获取短信的发送时间 Date date=new Date(cursor.getLong(cursor.getColumnIndex("date"))); //格式化以秒为单位的日期 SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日 hh时mm分ss秒"); sb.append("\n时间:"+sdf.format(date)); System.out.println("查询到的正在发送的短信:"+sb.toString()); Toast.makeText(MonitorSms.this, sb.toString(), Toast.LENGTH_LONG).show(); txtView.setText(sb.toString()); } super.onChange(selfChange); } } }