前言
开发中,我们会通过 Settings 设置、保存一些值,最终是存储到 SettingsProvider 的数据库里的,如
Settings.Global.putInt(getContentResolver(), "ContentObserverTest", 0);
Settings.System.putInt(getContentResolver(), "ContentObserverTest", 0);
Settings.Secure.putInt(getContentResolver(), "ContentObserverTest", 0);
需要是系统应用且添加权限 ,
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />-
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
adb 也可以读取、写入,如
settings put global ContentObserverTest 1
settings get global ContentObserverTest
在需要监听这些值的变动时,
就用 registerContentObserver(Uri uri, boolean notifyForDescendants,ContentObserver observer) {}
,
3个参数
- uri :被监听数据的 uri ,可以通过 Settings.Global.getUriFor(“key”) 得到。
- notifyForDescendants :false 表示精确匹配。true 表示还可以匹配 uri 派生的 uri 。
- observer :数据变化时接收消息的 ContentObserver
创建自定义ContentObserver
重写 onChange 方法,回调时会跑这里。selfChange 意思不大,一般都是 false 。
private static class MyContentObserver extends ContentObserver{
/**
* Creates a content observer.
*
* @param handler The handler to run {@link #onChange} on, or null if none.
*/
public MyContentObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange, @Nullable Uri uri) {
super.onChange(selfChange, uri);
}
}
构造函数中需要传一个 Handler ,那就创建 Handler 。
private static Handler mHandler = new Handler(Looper.getMainLooper()){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
}
};
监听
本例监听蓝牙开关,uri 是 content://settings/global/bluetooth_on ,
- uri.getScheme() :content
- uri.getAuthority() :settings
- uri.getHost() :settings
- uri.getPath() :/global/bluetooth_on
- uri.getLastPathSegment() :bluetooth_on
Uri uri = Settings.Global.getUriFor(Settings.Global.BLUETOOTH_ON);// content://settings/global/bluetooth_on
getContentResolver().registerContentObserver(uri, true, new MyContentObserver(mHandler));
取消监听
使用后(Activity 、Service 退出)需要取消监听,
getContentResolver().unregisterContentObserver(mObserver);
本例是作为普通应用监听蓝牙开关,监听是可以的,设置不行,因为没权限。
模拟器可运行,通过通知栏开关蓝牙开关可验证。完整代码
public class ContentObserverActivity extends AppCompatActivity {
private static class MyContentObserver extends ContentObserver{
/**
* Creates a content observer.
*
* @param handler The handler to run {@link #onChange} on, or null if none.
*/
public MyContentObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange, @Nullable Uri uri) {
super.onChange(selfChange, uri);
}
}
private static Handler mHandler = new Handler(Looper.getMainLooper()){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
}
};
private MyContentObserver mObserver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_content_observer);
Objects.requireNonNull(getSupportActionBar()).setTitle("ContentObserverActivity");
mObserver = new MyContentObserver(mHandler);
Uri uri = Settings.Global.getUriFor(Settings.Global.BLUETOOTH_ON);// content://settings/global/bluetooth_on
getContentResolver().registerContentObserver(uri, true, mObserver);
}
@Override
protected void onStop() {
super.onStop();
if (null != mObserver) {
getContentResolver().unregisterContentObserver(mObserver);
mObserver = null;
}
}
}