1. SystemProperty
1.1 引入 SystemProperties 类
在 Android Framework 中,SystemProperties
类用于访问和操作系统属性。系统属性在 Android 系统中广泛用于存储和检索配置信息。
主要方法
java
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 使用示例
获取系统属性
java
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);
}
}
设置系统属性
java
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);
}
}
获取整数、长整数和布尔值
java
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.4 总结
SystemProperties
类在 Android Framework 中非常有用,可以方便地获取和设置系统配置参数。虽然它是一个隐藏 API,但在系统开发和调试中非常有帮助。
2. ContentObserver 的使用
ContentObserver
在 Android 开发中常用于监听系统设置的变化,因为系统设置存储在内容提供者(Content Provider
)中。
2.1 创建一个 ContentObserver 类
java
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
:
java
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 进行过滤处理:
java
@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
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
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 注意事项
- 监听或操作
SettingsProvider
数据库,需要系统应用权限:
xml
<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>
- 部分设置项可能需要额外权限或无法被修改。
3. 实战演示
修改 MyApplication 代码:
xml
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
增加:
xml
android:sharedUserId="android.uid.system"
和权限
xml
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
修改编译文件: vendor/apps/MyApplication/Android.mk
makefile
#每个 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
全部删除
然后执行四步走:
makefile
//先初始化环境(每次打开虚拟机只需要执行一次环境即可)
source build/envsetup.sh
//选择上次编译过的机型(这个也是只选一次)
lunch sdk_phone_x86_64-eng
//开始整编(后续修改源码,只需要执行m就行,上面两个指令执行一次就行了)
m
//启动模拟器
emulator -writable-system
编译完成,运行模拟器,打开预装的应用,在终端输入以下指令设置值和获取值:
makefile
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
数据变化,适用于监听系统设置的修改。