• 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
  • 相关阅读:
    LeetCode 4. 寻找两个正序数组的中位数
    springboot幼儿园幼儿基本信息管理系统设计与实现毕业设计源码201126
    天软特色因子看板 (2023.09 第05期)
    爱上开源之golang入门至实战第四章函数(Func)(二)
    中国第一大微商TST涉嫌传销案听证会结束
    功能出新|酷雷曼3D漫游,更沉浸的三维空间体验
    一文读懂面试官都在问的Fastjson漏洞
    【pytorch】目标检测:YOLO的基本原理与YOLO系列的网络结构
    DNS外带注入
    八种十倍提升API性能的方式
  • 原文地址:https://blog.csdn.net/weixin_44021334/article/details/133383736