• Android 使用ContentObserver监听SettingsProvider值的变化


    开发中,我们会通过 Settings 设置、保存一些值,最终是存储到 SettingsProvider 的数据库里的,如

    Settings.Global.putInt(getContentResolver(), "ContentObserverTest", 0);
    Settings.System.putInt(getContentResolver(), "ContentObserverTest", 0);
    Settings.Secure.putInt(getContentResolver(), "ContentObserverTest", 0);
    
    • 1
    • 2
    • 3

    需要是系统应用且添加权限 ,

    -
    
    
    • 1
    • 2

    adb 也可以读取、写入,如

    settings put global ContentObserverTest 1
    
    settings get global ContentObserverTest
    
    • 1
    • 2
    • 3

    在需要监听这些值的变动时,
    就用 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);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    构造函数中需要传一个 Handler ,那就创建 Handler 。

    	private static Handler mHandler = new Handler(Looper.getMainLooper()){
    
            @Override
            public void handleMessage(@NonNull Message msg) {
                super.handleMessage(msg);
            }
        };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    监听

    本例监听蓝牙开关,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));
    
    • 1
    • 2

    取消监听

    使用后(Activity 、Service 退出)需要取消监听,

    getContentResolver().unregisterContentObserver(mObserver);
    
    • 1

    本例是作为普通应用监听蓝牙开关,监听是可以的,设置不行,因为没权限。

    模拟器可运行,通过通知栏开关蓝牙开关可验证。完整代码

    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;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
  • 相关阅读:
    相干函数的基本概念及其案例
    43、Kinect 深度相机初体验和vs2022测距输出
    Linux学习第23天:Linux中断驱动开发(二): 突如其来
    特性Attribute
    如何用SVG画一个特定边框
    立创EDA——PCB的走线(五)
    java游泳馆浴池管理系统-小程序
    OpenInventor/Coin3D 学习指南
    springboot点餐微信小程序毕业设计源码221144
    电脑提示MSVCP100.dll丢失错误怎么解决?分享四个解决方法帮你搞定
  • 原文地址:https://blog.csdn.net/weixin_44021334/article/details/133383736