监听ContentProvider的数据改变
使用ContentProvider时,不管实现insert、delete、update方法中的哪一个,只要该方法导致ContentProvider数据的改变,程序就会调用如下代码:
getContext().getContentResolver().notifyChange(uri, null);
这行代码可用于通知所有注册在该Uri上的监听者:该ContentProvider所共享的数据发生了改变。
为了在该应用程序中监听ContentProvider数据的改变,需要利用Android提供的ContentObserver基类。监听ContentProvider数据改变的监听器需要继承ContentObserver类,并重写该基类所定义的onChange(boolean selfChange)方法——当它所监听的ContentProvider数据发生改变时,该onChange()方法将会被触发。
为了监听指定ContentProvider的数据变化,需要通过ContentResolver向指定Uri注册ContentObserver监听器。ContentResolver提供了如下方法来注册监听器。
registerContentObserver(Uri uri, boolean notifyForDescendents, ContentObserver observer)
该方法中的三个参数说明如下。
uri:该监听器所监听的ContentProvider的uri。
notifyForDescendents:如果该参数设为true,假如注册监听的Uri为content://abc,那么Uri为content://abc/xyz、content://abc/foo的数据改变时也会触发 该监听器;如果该参数设为false,假如注册监听的Uri为content://abc,那么只有content://abc的数据发生改变时才会触发该监听器。
observer:监听器实例。
例如,如下代码片段可用于为指定Uri注册监听器:
getContentResolver().registerContentObserver(Uri.parse(“content://sms”)), true, new SmsObserver(new Handler()));
上面的代码中SmsObserver就是ContentObserver的子类。
实例:监听用户发出的短信
本实例通过监听Uri为content://sms的数据改变即可监听到用户短信的数据改变,并在监听器的onChange(boolean selfChange)方法里查询Uri为content://sms/outbox的数据,这样即可获取用户正在发送的短信(用户正在发送的短信保存在发件箱内)。
该程序的代码如下。
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//为content://sms的数据改变注册监听器,可以监听到用户短信数据的改变
getContentResolver().registerContentObserver(Uri.parse("content://sms"), true, new SmsObserver(new Handler()));
}
//提供自定义的ContentObserver监听器类
private final class SmsObserver extends ContentObserver {
public SmsObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
//查询发件箱中的短信(处于正在发送状态的短信放在发件箱中),用于查询content://sms/outbox的全部数据,也就是查询发件箱(正在发送的短信保存在发件箱内)内的全部短信,这样就可以获取用户正在发送的短信详情
Cursor cursor = getContentResolver().query(Uri.parse("content://sms/outbox"), null, null, null, null);
//遍历查询得到的结果集,即可获取用户正在发送的短信
while (cursor.moveToNext()) {
StringBuilder stringBuilder = new StringBuilder();
//获取短信的发送地址
stringBuilder.append("address=").append(cursor.getString(cursor.getColumnIndex("address")));
//获取短信的标题
stringBuilder.append(";subject=").append(cursor.getString(cursor.getColumnIndex("subject")));
//获取短信的内容
stringBuilder.append(";body=").append(cursor.getString(cursor.getColumnIndex("body")));
//获取短信的发送时间
stringBuilder.append(";time=").append(cursor.getLong(cursor.getColumnIndex("date")));
System.out.println("发送短信:" + stringBuilder.toString());
}
}
}
}
运行该程序,在不关闭该程序的情况下打开Android系统内置的”Messaging”程序发送短信——直接向本机号码发送即可。当用户发送短信时,可以在LogCat面板看到如下:
发送短信:address=555-4;subject=null;body=this is test message;time=14217364484
本程序需要读取系统短信的内容,因此还需要为该应用添加读取短信的权限
后记:
这个监听用户发送短信的程序采用Activity来实现并不合适——因为用户必须先主动打开该Activity,并保持该Activity不关闭的情况下,用户所发送的短信才会被监听到。这明显不太符合实际需求场景,在实际情况下,可能更希望该程序以后台进程的方式“不知不觉”的运行,这就需要利用Android的service组件了。