前面介绍的是当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"/>