Android uses ContentObserver to monitor changes in SettingsProvider value

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;
        }
    }
}

Guess you like

Origin blog.csdn.net/weixin_44021334/article/details/133383736