安卓源码学习之【系统属性与 ContentObserver】

带你学习Android中的ContentObserver 通过使用,开发者可以有效地监听系统设置的变化,例如屏幕亮度等。这种机制使得应用能够动态响应系统设置的更改,提升用户体验。在实现需要与系统设置交互的应用时,合理使用是非常重要的。 阅读详情

1. SystemProperty

1.1 引入 SystemProperties 类

在 Android Framework 中,SystemProperties 类用于访问和操作系统属性。系统属性在 Android 系统中广泛用于存储和检索配置信息。

主要方法

get(String key)
get(String key, String def)
getInt(String key, int def)
getLong(String key, long def)
getBoolean(String key, boolean def)
set(String key, String value)

1.2 使用示例

获取系统属性
import android.os.SystemProperties;

public class SystemPropertyExample {
    public static void main(String[] args) {
        // 获取属性值,如果属性不存在则返回空字符串
        String value = SystemProperties.get("ro.build.version.release");
        System.out.println("Android Version: " + value);

        // 获取属性值,如果属性不存在则返回默认值
        String defaultValue = SystemProperties.get("non.existent.property", "default_value");
        System.out.println("Non-existent property: " + defaultValue);
    }
}
设置系统属性
import android.os.SystemProperties;

public class SystemPropertyExample {
    public static void main(String[] args) {
        // 设置属性值
        SystemProperties.set("custom.property", "custom_value");

        // 验证设置的属性值
        String customValue = SystemProperties.get("custom.property");
        System.out.println("Custom Property: " + customValue);
    }
}
获取整数、长整数和布尔值
import android.os.SystemProperties;

public class SystemPropertyExample {
    public static void main(String[] args) {
        // 获取整数属性
        int intValue = SystemProperties.getInt("ro.build.version.sdk", 0);
        System.out.println("SDK Version: " + intValue);

        // 获取长整数属性
        long longValue = SystemProperties.getLong("some.long.property", 0L);
        System.out.println("Long Property: " + longValue);

        // 获取布尔值属性
        boolean boolValue = SystemProperties.getBoolean("some.boolean.property", false);
        System.out.println("Boolean Property: " + boolValue);
    }
}

1.3 注意事项

  1. 权限:某些系统属性可能需要特定权限才能读取或修改,特别是在非系统应用中。
  2. 不可滥用:系统属性用于存储全局配置参数,不应滥用或频繁修改,以免影响系统稳定性。
  3. 性能:频繁访问系统属性可能会影响性能,建议将其值缓存到内存中以优化性能。

1.4 总结

SystemProperties 类在 Android Framework 中非常有用,可以方便地获取和设置系统配置参数。虽然它是一个隐藏 API,但在系统开发和调试中非常有帮助。

2. ContentObserver 的使用

ContentObserver 在 Android 开发中常用于监听系统设置的变化,因为系统设置存储在内容提供者(Content Provider)中。

2.1 创建一个 ContentObserver 类

import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;

public class SettingsObserver extends ContentObserver {
    public SettingsObserver(Handler handler) {
        super(handler);
    }

    @Override
    public void onChange(boolean selfChange, Uri uri) {
        super.onChange(selfChange, uri);
        // 在这里处理设置变化
        System.out.println("Settings changed: " + uri.toString());
    }
}

2.2 注册 ContentObserver

在 Activity 或 Service 中注册 ContentObserver:

import android.app.Activity;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;

public class MainActivity extends Activity {
    private SettingsObserver settingsObserver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Handler handler = new Handler();
        settingsObserver = new SettingsObserver(handler);

        // 注册观察器,监听系统设置的变化
        getContentResolver().registerContentObserver(
            Settings.System.CONTENT_URI,  // 可选择 Settings.Global.CONTENT_URI 或 Settings.Secure.CONTENT_URI
            true, // 是否监听所有的子 URI
            settingsObserver
        );
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (settingsObserver != null) {
            getContentResolver().unregisterContentObserver(settingsObserver);
        }
    }
}

2.3 处理设置变化

在 SettingsObserver 的 onChange 方法中处理设置变化。例如,如果你只关心特定的设置项,可以根据 URI 进行过滤处理:

@Override
public void onChange(boolean selfChange, Uri uri) {
    super.onChange(selfChange, uri);
    if (uri.equals(Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS))) {
        int brightness = Settings.System.getInt(
            context.getContentResolver(),
            Settings.System.SCREEN_BRIGHTNESS,
            -1
        );
        System.out.println("Screen brightness changed: " + brightness);
    }
}

2.4 示例总结

SettingsObserver.java
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.provider.Settings;

public class SettingsObserver extends ContentObserver {
    private Context context;

    public SettingsObserver(Handler handler, Context context) {
        super(handler);
        this.context = context;
    }

    @Override
    public void onChange(boolean selfChange, Uri uri) {
        super.onChange(selfChange, uri);
        if (uri.equals(Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS))) {
            int brightness = Settings.System.getInt(
                context.getContentResolver(),
                Settings.System.SCREEN_BRIGHTNESS,
                -1
            );
            System.out.println("Screen brightness changed: " + brightness);
        }
    }
}
MainActivity.java
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;

public class MainActivity extends Activity {
    private SettingsObserver settingsObserver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Handler handler = new Handler();
        settingsObserver = new SettingsObserver(handler, this);

        getContentResolver().registerContentObserver(
            Settings.System.CONTENT_URI,
            true,
            settingsObserver
        );
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (settingsObserver != null) {
            getContentResolver().unregisterContentObserver(settingsObserver);
        }
    }
}

2.5 注意事项

  1. 监听或操作 SettingsProvider 数据库,需要系统应用权限:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:sharedUserId="android.uid.system">
  
    <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
</manifest>

  1. 部分设置项可能需要额外权限或无法被修改。

3. 实战演示

修改 MyApplication 代码:

public class MainActivity extends AppCompatActivity {

    private SettingsObserver mSettingsObserver;
    private String TEST_KEY = "test_key";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);

        int value = Settings.System.getInt(getContentResolver(),TEST_KEY,-1);
        Log.d("wyd"," onCreate get TEST_KEY value :" + value);
        Settings.System.putInt(getContentResolver(),TEST_KEY,-3);
        mSettingsObserver = new SettingsObserver(new Handler());
        getContentResolver().registerContentObserver(Settings.System.getUriFor(TEST_KEY),true,mSettingsObserver);
    }

    class SettingsObserver extends ContentObserver {

        /**
         * Creates a content observer.
         *
         * @param handler The handler to run {@link #onChange} on, or null if none.
         */
        public SettingsObserver(Handler handler) {
            super(handler);
        }


        @Override
        public void onChange(boolean selfChange, @Nullable Uri uri) {
            super.onChange(selfChange, uri);

            int value = Settings.System.getInt(getContentResolver(),TEST_KEY,-1);
            Log.d("wyd"," value : " + value);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        getContentResolver().unregisterContentObserver(mSettingsObserver);
    }
}

AndroidManifest.xml 增加:

android:sharedUserId="android.uid.system"

和权限

<uses-permission android:name="android.permission.WRITE_SETTINGS"/>

修改编译文件: vendor/apps/MyApplication/Android.mk

#每个 Android.mk 文件必须以定义 LOCAL_PATH 为开始,它用于在开发树中查找源文件。  
LOCAL_PATH:= $(call my-dir)
#CLEAR_VARS 变量由 Build System 提供,并指向一个指定的 GNU Makefile,由它负责清理很多 LOCAL_xxx。
include $(CLEAR_VARS)
#模块名
LOCAL_MODULE := MyApplication
#apk 名  
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
#user、eng、tests、optional(所有版本都编译)
LOCAL_MODULE_TAGS := optional
#指定模块的类型,可不用定义 APPS、JAVA_LIBRAYIES、 SHARED_LIBRAYIES、 EXECUTABLES
LOCAL_MODULE_CLASS := APPS
#签名 platform 、PRESIGNED、 shared
LOCAL_CERTIFICATE := platform
# in system/app/
LOCAL_SYSTEM_MODULE := true
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
include $(BUILD_PREBUILT)

主要注意使用平台签名:LOCAL_CERTIFICATE := platform 和 将应用放到 system/app/ 下 LOCAL_SYSTEM_MODULE := true

然后删除之前编译的镜像文件out/target/product/emulator_x86_64/ 目录下搜索 .img 全部删除

然后执行四步走:

//先初始化环境(每次打开虚拟机只需要执行一次环境即可)
source build/envsetup.sh

//选择上次编译过的机型(这个也是只选一次)
lunch sdk_phone_x86_64-eng

//开始整编(后续修改源码,只需要执行m就行,上面两个指令执行一次就行了)
m 

//启动模拟器
emulator -writable-system

编译完成,运行模拟器,打开预装的应用,在终端输入以下指令设置值和获取值:

adb shell settings put system test_key 0
adb shell settings put system test_key 1
adb shell settings get system test_key

日志打印:

总结

  • SystemProperties 可用于获取和修改系统属性,但它是隐藏 API,需要特殊方法访问。
  • ContentObserver 用于监听 ContentProvider 数据变化,适用于监听系统设置的修改。
android内容观察者ContentObserver类 结合android.developer网站看,常用方法在那个网站看 contentObserver——内容观察者,目的是观察特定Uri引起的数据库的变化,方便监听插入数据库中数据的变化 有的项目中数据库数据进行改变后,去到某一个页面需要刷新数据,如果有这个需求使用ContentObserver就比较有用了 如果每次在页面显示都刷新数据库的数据,对于会多次显示的页面效率就很低了 则如果我们希望监测一个数据源的变化情况,如果单独使用一个线程去不断的进行查询,那么效率就太低了,我们可以使用Cont 阅读详情

相关推荐

使用ContentObserver监听ContentProvider数据变化的编程实现

在上述代码中,我们在MainActivity的onCreate方法中创建了MyContentObserver的实例,并使用getContentResolver().registerContentObserver()方法注册了ContentObserver。通过创建一个继承自ContentObserver的子类,并在其中处理数据变化的逻辑,我们可以及时获得ContentProvider数据的变化通知,并做出相应的处理。在这个方法中,我们可以根据实际需求编写处理数据变化的逻辑。

BrchCpp的博客 432

ContentObserver 内容观察者作用及特点

eg: 1、定义Uri public static Uri KEY_BROWSER_URI = Uri.parse("content://com.android.browser.provider.search_engine/search_engine"); 2、new 一个ContentObserver private ContentObserver mBrowse...

weixin_30611509的博客 499

Arduino平台软硬件原理及使用——Arduino Uno板卡的使用

Arduino Uno板卡的基本使用

洪博hopes的博客 4171

Android 内容观察者 ContentObserver 类

ContentObserver——内容观察者,目的是观察特定Uri引起的数据库的变化 这个是官方的文档,将的也是比较少 一般使用分为四步, 1、创建内容观察者 ContentObserver 2、注册监听registerContentObserver 3、刷新数据库改变onChange 4、注销监听unregisterContentObserver 下面写2个demo 监听手机的手机,和手机的显示12小时制还是24小时制对上面的步骤进行说明,可以看下我录制的一个gif图 下面直接...

小牧在一直在学习,在前进的道路上大家一起学习,进步。 5433

【TM1640】STM32 TM1640芯片驱动程序

以下为.h文件: #ifndef __TM1640_H__ #define __TM1640_H__ #include "stm32f10x.h" #define ADDR_START1640 0XC0 #define DSP1640_DIS 0 #define DSP1640_ENB 1 /* 控制显示 ...

cxw312864660的博客 1万+

基于YOLOv5/v8/v10的垃圾分类识别系统:设计实现与性能优化(附代码+数据集)

做完这个毕设,你已经掌握了从数据准备、模型训练到界面开发的全流程。把模型部署到树莓派上,做个真正的“智能垃圾桶”硬件装置;加入语音提示功能,检测到垃圾后自动语音播报类别;试试融合多个YOLO模型的优势,让分类精度再上一个台阶。按照这个教程一步步做,你的毕设不仅能顺利完成,还能做出很多亮点。要是过程中遇到啥问题,别慌,慢慢琢磨或者咱们一起聊聊,肯定能把这个毕设做成让你满意的作品。

know_F0727的博客 462

Android之ContentObserver

内容观察者知识点笔记

七夜聖君的博客 780

PowerDesigner 数据库建模使用详解

PowerDesigner 数据库建模使用详解

congge 7081

Android中内容观察者的使用---- ContentObserver类详解

转载请注明出处:http://blog.youkuaiyun.com/qinjuning                             前言: 工作中,需要开启一个线程大量的查询某个数据库值发送了变化,导致的开销很大,后来在老大的指点下,利用了      ContentObserver完美的解决了该问题,感到很兴奋,做完之后自己也对ContentObserver做下总结。

qinjuning、lets go 13万+

linux驱动由浅入深系列:基于高通平台分析触摸屏(TP)、虚拟按键驱动

触摸屏的触摸板(touch panel简称TP)驱动的基本架构和普通按键驱动基本一致,可以参考文章:linux驱动由浅入深系列:输入子系统之二(编写一个gpio_key驱动)。只是其功能稍稍复杂些,配置也多些,下面一起来看一下。 TP包括 触摸屏、虚拟按键、虚拟按键背光灯 TP驱动芯片厂商主要有:Goodix(汇顶),FocalTech(敦泰科技),cypress(赛普拉斯),synapt

Radia的专栏 4767

3分钟学会SQL中的断点去重技术,轻松搞定连续重复数据去重问题?

传感器采集的温度数据中,存在连续重复的值,需仅在数值变化时保留记录(例如:温度从 25°C 变为 26°C 时记录一次)。:判断逻辑,current_value!若当前温度与前一行的温度不同(或为第一条记录),则保留该行。的技术,常用于时间序列或状态日志中。:将连续相同值的记录合并,只保留断点处的记录。保留断点处的记录(即温度变化时的第一条)。原始数据表 sensor_data。最终仅保留值变化的断点记录。获取前一行的温度值。

石榴姐yyds 1019

【安卓学习积累】ContentObserver的使用

在开发过程中使用到ContentObserver的主要用途就是监听数据库内容的变化,例如我们经常会通过在SettingProvider中写入一个标志位来进行各种判断。如果我们要监听这个标志位的变化就是使用到ContentObserver。还有假如我们需要监听(蓝牙开关、飞行模式开关等)都会用到ContentObserver。 一、ContentObserver的创建 创建ContentOb...

xiangzaixiansheng的博客 1487

Ollama本地大模型-个性化AI:训练自己的风格模型和数据投喂打造专属智能体验

之前我们使用Ollama下载了deepseek模型,现在我想将其训练成自己风格的模型,应该怎么做?

瑶山的博客 1782

Android监听截屏

Android系统没有提供默认的截屏事件监听方式,需要开发者自己想办法实现。查看了网上推荐的实现方式,主要是通过内容观察者(ContentObserver)监听媒体数据库的变化,根据内容名称(路径)中是否包含关键字,判断是否为截屏事件。 关键字: 第一步:对ContentResolver添加内、外存储变化监听; 第二步:当内容观察者(ContentObserver)监听到变化时,会调用onChange方法,此时,我们使用ContentResolver去查询最新的一条数据; 需要注意的是,查询外部存储一定要有

大模型学习路线 4295

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

ContentObserver内容监听者(内容观察者)

这里外加一个思维导图:关于ContentProvider 好了,现在来看看ContentObserver。 ContentObserver——内容监听者(内容观察者)。指的是监听某一指定路径里面的数据。目的是观察(捕捉)特定URI引起的数据库的变化,从而做一些相当应的处理。当数据一旦发生改变会通过调用onChange()方法,通过handler把数据发送出去。  

GD_Tiny的博客 857

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

ContentResolver与ContentObserver是什么?

是 Android 中用于管理和监听内容提供者(ContentProvider)数据的两个重要组件。它们在数据访问和变化监听方面各有不同的职责,但通常会结合使用以实现数据的动态和实时更新。是用于监听内容提供者数据变化的观察者。当数据发生变化时,ContentObserver 会收到通知,从而可以执行相应的操作,例如更新 UI 或重新加载数据。通常,ContentResolver 和 ContentObserver 会结合使用,以实现数据的动态更新。是用于访问内容提供者的主要接口。

小新的博客 582

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Android内容服务ContentService原理浅析

ContentService可以看做Android中一个系统级别的消息中心,可以说搭建了一个系统级的观察者模型,APP可以向消息中心注册观察者,选择订阅自己关心的消息,也可以通过消息中心发送信息,通知其他进程,简单模型如下: ContentService服务伴随系统启动,本身是一个Binder系统服务,运行在SystemServer进程。作为系统服务,最好能保持高效运行,因此ContentSer...

weixin_34212762的博客 342

ContentObserver注册和触发流程分析

ContentObserver注册和触发流程 获取ContentResolver mContext.getContentResolver() Context是一个抽象类,他的实现类之一是ContextImpl,分析ContextImpl源码可以看到: //android.app.ContextImpl public ContentResolver getContentResolver() { return mContentResolver; } mContentResolver声明

programW的博客 1550

ContentObserver 的原理

ContentObserver——内容观察者,目的是观察(捕捉)特定Uri引起的数据库的变化,继而做一些相应的处理,它类似于数据库技术中的触发器(Trigger),当ContentObserver所观察的Uri发生变化时,便会触发它。触发器分为表触发器、行触发器,相应地ContentObserver也分为“表“ContentObserver、“行”ContentObserver,当然这是与它所监听的

在路上的大蜗牛 3257

Android内部数据库

介绍Android内部数据库种类,以及查询和监听数据库的方法

ccpat的专栏 2743

Android内容观察者(案例:监听数据库+代码+效果图)

Android内容观察者(案例:监听数据库+代码+效果图)

. 1984

ContentProvider ,ContentObserver 和ContentResolver

1ContentProvider 是共享数据 2ContentObserver是监听数据 3ContentObserver是解析数据  这个是测试程序,是用来接收另一个程序的信息 public class TestContent extends AndroidTestCase{ public void testInsert(){ ContentResolver resolver

oJianLian的专栏 782

ContentService简单分析

ContentService采用的是观察者模式,APP通过ContentResolver向ContentService注册自己感兴趣的Uri消息。当对应的数据发生变化时,ContentResolver调用notifyChange函数向ContentService发送对应Uri数据改变的通知,ContentService查询对应Uri所对应的ContentObserver代理对象集合,通过IContentObserver代理对象回调ContentObserver的notifyChange函数 1 Conten

he980725866的博客 2339

ContentProvider、ContentResolver、ContentObserver之间的关系

ContentProvider: 四大组件的内容提供者,主要用于对外提供数据 实现各个应用程序之间的(跨应用)数据共享,比如联系人应用中就使用了ContentProvider,你在自己的应用中可以读取和修改联系人的数据,不过需要获得相应的权限。其实它也只是一个中间人,真正的数据源是文件或者SQLite等 一个应用实现ContentProvider来提供内容给别的应用来操作,通过Cont...

倚栏静望的博客 3688

ContentObserver监听系统属性变化

ContentObserver监听系统属性变化 有时候我们需要监听系统属性变化,或者通过修改系统属性的值来通知其它应用做相应的操作。 以无障碍服务的属性为例,通过ContentObserver监听其变化:Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES 1、新建MyContentObserver.java类继承ContentObserver; import android.database.ContentObserver; import android.os.H

feng海涛 3605
上一篇: Android源码学习之Overlay
下一篇: 我的创作纪念日
_蓝橙
博客等级 码龄7年 1179粉丝 174原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值