During development, we will set and save some values through Settings, and finally store them in the database of SettingsProvider, such as
Settings.Global.putInt(getContentResolver(), "ContentObserverTest", 0);
Settings.System.putInt(getContentResolver(), "ContentObserverTest", 0);
Settings.Secure.putInt(getContentResolver(), "ContentObserverTest", 0);
It needs to be a system application and add permissions.
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />-
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
adb can also read and write, such as
settings put global ContentObserverTest 1
settings get global ContentObserverTest
When you need to monitor changes in these values,
use registerContentObserver(Uri uri, boolean notifyForDescendants,ContentObserver observer) {}
,
3 parameters
- uri: The uri of the monitored data can be obtained through Settings.Global.getUriFor("key").
- notifyForDescendants: false indicates an exact match. true means that uri -derived uris can also be matched.
- observer: ContentObserver that receives messages when data changes
Create a custom ContentObserver
Override the onChange method and the callback will run here. selfChange doesn't mean much, it's usually 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);
}
}
If you need to pass a Handler in the constructor, create a Handler.
private static Handler mHandler = new Handler(Looper.getMainLooper()){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
}
};
monitor
In this example, the Bluetooth switch is monitored. The uri is 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));
Cancel monitoring
After use (Activity, Service exit), you need to cancel the monitoring.
getContentResolver().unregisterContentObserver(mObserver);
This example is used as a normal application to monitor the Bluetooth switch. Monitoring is possible, but setting is not possible because there is no permission.
The emulator can run and can be verified by turning the Bluetooth switch on and off in the notification bar. Complete code
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;
}
}
}