前面介绍的是当ContentProvider将数据共享出来之后,ContentResolver会根据业务需要去主动查询ContentProvider所共享的数据;但有时候程序需要实时监听ContentProvider所共享的数据,并提供相应的响应,这就需要利用ContentObserver了。
其实在ContentProvider中,不管实现的哪个方法,只要该方法导致数据发生了变化。程序就调用了如下代码:
getContext().getContentResolver().notifyChange(uri, null);
用于通知所有注册在该Uri上的监听者:该ContentProvider所共享的数据发生了改变。
监听ContentProvider数据改变的监听器需要继承ContentObserver类,并重写onChange方法,当ContentProvider数据发生改变时,该方法会被触发。
为了监听指定ContentProvider的数据变化,需要通过ContentResolver向指定的Uri注册监听器。ContentResolver提供了如下方法来组成监听器:
该方法中三个参数说明如下:
下面用监听用户发送短信的实例来演示,通过Activity启动一个Service服务,去监听ContentProvider数据的变化。代码如下:
Activity:
package com.lovo.testcontentobserver;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener {
private Button startBtn, stopBtn;
private Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startBtn = (Button) findViewById(R.id.main_btn_start);
stopBtn = (Button) findViewById(R.id.main_btn_stop);
startBtn.setOnClickListener(this);
stopBtn.setOnClickListener(this);
intent = new Intent();
// 为intent设置Action属性
intent.setAction("com.lovo.myservice");
}
@Override
public void onClick(View v) {
if (v == startBtn) {
// 启动指定Service
startService(intent);
}
if (v == stopBtn) {
// 停止指定Service
stopService(intent);
}
}
}
布局XML只有2个按钮就省略不写了。
Service:
package com.lovo.service;
import android.app.Service;
import android.content.Intent;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service {
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
// 为content://sms的数据改变注册监听器
getContentResolver().registerContentObserver(
Uri.parse("content://sms"), true,
new SmsObserver(new Handler()));
}
// 提供自定义的ContentProvider监听器类
private final class SmsObserver extends ContentObserver {
public SmsObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
// 查询发送箱中的短信(处于正在发送状态的短信放在发送箱中)
Cursor cursor = getContentResolver().query(
Uri.parse("content://sms/outbox"), null, null, null, null);
while (cursor.moveToNext()) {
StringBuffer sb = new StringBuffer();
// 获取短信的发送地址
sb.append("address=").append(
cursor.getString(cursor.getColumnIndex("address")));
// 获取短信的标题
sb.append(";subject=").append(
cursor.getString(cursor.getColumnIndex("subject")));
// 获取短信的内容
sb.append(";body=").append(
cursor.getString(cursor.getColumnIndex("body")));
// 获取短信的发生时间
sb.append(";time=").append(
cursor.getLong(cursor.getColumnIndex("date")));
Log.i("发送的短信:", sb.toString());
}
}
}
}
加上权限:
<uses-permission android:name="android.permission.WRITE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>