一、核心概念与差异
1.1 系统设置项(Settings)
系统设置项是Android Framework提供的一套键值对存储机制,用于保存应用程序和系统的配置信息。它提供了三个命名空间:
- Global:全局设置,所有应用和系统组件共享
- System:系统级设置,与用户无关
- Secure:安全敏感设置,需要特殊权限访问
1.2 系统属性(System Properties)
系统属性是Android底层(Native层)的键值对存储,主要用于系统启动、运行时配置和组件间通信。它通过init进程维护,支持进程间通信。
1.3 核心差异对比
| 特性 | 系统设置项 | 系统属性 |
|---|---|---|
| 存储位置 | SQLite数据库(/data/data/com.android.providers.settings) | 共享内存(/dev/properties) |
| 访问方式 | ContentProvider(SettingsProvider) | SystemProperties类 / getprop/setprop命令 |
| 生命周期 | 持久化存储,重启后保留 | 重启后重置(部分属性持久化) |
| 访问权限 | 需要相应权限(READ/WRITE_SETTINGS) | 需要root权限或system权限 |
| 性能 | 相对较慢(数据库操作) | 极快(内存操作) |
| 适用场景 | 应用配置、用户偏好设置 | 系统启动参数、运行时状态 |
二、系统设置项(Settings)详解
2.1 访问系统设置项
2.1.1 Java层访问
// 读取设置项
String value = Settings.Global.getString(getContentResolver(),
Settings.Global.WIFI_ON);
boolean wifiEnabled = "1".equals(value);
// 写入设置项
Settings.Global.putString(getContentResolver(),
Settings.Global.WIFI_ON, "1");
// 监听设置项变化
ContentObserver observer = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
// 处理变化
}
};
getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.WIFI_ON),
false, observer);
2.1.2 权限声明
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.READ_SETTINGS" />
2.2 常用系统设置项
2.2.1 Global命名空间
// 飞行模式
Settings.Global.AIRPLANE_MODE_ON
// 蓝牙开关
Settings.Global.BLUETOOTH_ON
// 位置服务
Settings.Global.LOCATION_MODE
// 开发者选项
Settings.Global.DEVELOPMENT_SETTINGS_ENABLED
// ADB调试
Settings.Global.ADB_ENABLED
2.2.2 System命名空间
// 屏幕亮度
Settings.System.SCREEN_BRIGHTNESS
// 屏幕超时
Settings.System.SCREEN_OFF_TIMEOUT
// 系统音量
Settings.System.VOLUME_MUSIC
// 字体缩放
Settings.System.FONT_SCALE
2.2.3 Secure命名空间
// 锁屏密码
Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT
// 安装未知来源应用
Settings.Secure.INSTALL_NON_MARKET_APPS
// 默认输入法
Settings.Secure.DEFAULT_INPUT_METHOD
// 无障碍服务
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES
2.3 自定义设置项
2.3.1 定义自定义设置项
public class CustomSettings {
public static final String CUSTOM_SETTING = "custom_setting_key";
public static String getCustomSetting(Context context) {
return Settings.System.getString(context.getContentResolver(), CUSTOM_SETTING);
}
public static void setCustomSetting(Context context, String value) {
Settings.System.putString(context.getContentResolver(), CUSTOM_SETTING, value);
}
}
2.3.2 在SettingsProvider中注册
<!-- res/xml/settings_system.xml -->
<settings>
<setting name="custom_setting_key" value="default_value" />
</settings>
三、系统属性(System Properties)详解
3.1 访问系统属性
3.1.1 Java层访问
import android.os.SystemProperties;
// 读取属性
String value = SystemProperties.get("persist.sys.timezone", "GMT");
int intValue = SystemProperties.getInt("ro.build.version.sdk", 0);
boolean boolValue = SystemProperties.getBoolean("persist.sys.debug", false);
// 设置属性(需要system权限)
SystemProperties.set("custom.property", "value");
// 监听属性变化
SystemProperties.addChangeCallback(new Runnable() {
@Override
public void run() {
// 属性发生变化
}
});
3.1.2 Native层访问(C/C++)
#include <cutils/properties.h>
// 读取属性
char value[PROPERTY_VALUE_MAX];
property_get("ro.build.version.release", value, "unknown");
// 设置属性
property_set("custom.property", "value");
3.1.3 Shell命令
# 读取属性
getprop ro.build.version.release
# 设置属性(需要root权限)
setprop custom.property value
# 查看所有属性
getprop
3.2 常用系统属性
3.2.1 只读属性(ro.*)
# 系统版本
ro.build.version.release
ro.build.version.sdk
# 设备信息
ro.product.model
ro.product.brand
ro.product.device
# 硬件信息
ro.hardware
ro.board.platform
ro.arch
# 构建信息
ro.build.type
ro.build.tags
ro.build.fingerprint
3.2.2 持久化属性(persist.*)
# 时区
persist.sys.timezone
# 语言
persist.sys.language
persist.sys.country
# 调试设置
persist.sys.debug
persist.sys.usb.config
# 网络配置
persist.sys.network
3.2.3 运行时属性
# 系统服务状态
init.svc.<service_name>
# 网络状态
net.dns1
net.dns2
# 调试设置
debug.performance.tuning
debug.hwui.render_dirty_regions
# SELinux状态
ro.build.selinux
3.3 自定义系统属性
3.3.1 定义属性文件
# /system/build.prop 或 /vendor/build.prop
# 只读属性
ro.custom.property=value
# 持久化属性
persist.custom.property=value
3.3.2 在init.rc中设置
# /system/etc/init/init.rc
on property:sys.boot_completed=1
setprop custom.boot.complete true
四、实战应用场景
4.1 监听网络状态变化
public class NetworkObserver {
private static final String TAG = "NetworkObserver";
public void startObserving(Context context) {
// 监听网络设置变化
ContentObserver observer = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
checkNetworkState(context);
}
};
context.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.WIFI_ON),
false, observer);
context.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON),
false, observer);
}
private void checkNetworkState(Context context) {
boolean wifiEnabled = Settings.Global.getInt(context.getContentResolver(),
Settings.Global.WIFI_ON, 0) == 1;
boolean airplaneMode = Settings.Global.getInt(context.getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
Log.d(TAG, "WiFi: " + wifiEnabled + ", Airplane: " + airplaneMode);
}
}
4.2 动态调整系统配置
public class SystemConfigManager {
// 设置屏幕亮度
public static void setScreenBrightness(Context context, int brightness) {
if (brightness < 0) brightness = 0;
if (brightness > 255) brightness = 255;
Settings.System.putInt(context.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS, brightness);
}
// 设置屏幕超时
public static void setScreenTimeout(Context context, int timeoutMs) {
Settings.System.putInt(context.getContentResolver(),
Settings.System.SCREEN_OFF_TIMEOUT, timeoutMs);
}
// 设置系统音量
public static void setSystemVolume(Context context, int volume) {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audioManager.setStreamVolume(AudioManager.STREAM_SYSTEM, volume, 0);
// 同时保存到设置
Settings.System.putInt(context.getContentResolver(),
Settings.System.VOLUME_SYSTEM, volume);
}
}
4.3 系统属性监控服务
public class PropertyMonitorService extends Service {
private static final String TAG = "PropertyMonitorService";
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 监听系统属性变化
SystemProperties.addChangeCallback(mPropertyChangeCallback);
return START_STICKY;
}
private final Runnable mPropertyChangeCallback = new Runnable() {
@Override
public void run() {
// 检查感兴趣的属性
checkDebugMode();
checkNetworkProperties();
}
};
private void checkDebugMode() {
boolean debugMode = SystemProperties.getBoolean("persist.sys.debug", false);
if (debugMode) {
Log.d(TAG, "Debug mode enabled");
// 执行调试相关操作
}
}
private void checkNetworkProperties() {
String dns1 = SystemProperties.get("net.dns1", "");
String dns2 = SystemProperties.get("net.dns2", "");
Log.d(TAG, "DNS servers: " + dns1 + ", " + dns2);
}
@Override
public void onDestroy() {
super.onDestroy();
// 移除监听
SystemProperties.removeChangeCallback(mPropertyChangeCallback);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
4.4 系统启动配置
public class BootConfigManager {
// 检查系统启动完成
public static boolean isBootCompleted() {
return SystemProperties.getInt("sys.boot_completed", 0) == 1;
}
// 设置启动参数
public static void setBootParameter(String key, String value) {
SystemProperties.set(key, value);
}
// 获取设备信息
public static String getDeviceInfo() {
String model = SystemProperties.get("ro.product.model", "Unknown");
String brand = SystemProperties.get("ro.product.brand", "Unknown");
String sdk = SystemProperties.get("ro.build.version.sdk", "Unknown");
return String.format("Model: %s, Brand: %s, SDK: %s", model, brand, sdk);
}
}
五、权限管理与安全
5.1 系统设置项权限
5.1.1 权限声明
<!-- 读取设置项 -->
<uses-permission android:name="android.permission.READ_SETTINGS" />
<!-- 写入设置项 -->
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<!-- 安全设置项(需要特殊权限) -->
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
5.1.2 运行时权限检查
public class SettingsPermissionHelper {
public static boolean canWriteSettings(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return Settings.System.canWrite(context);
}
return true;
}
public static void requestWriteSettingsPermission(Activity activity, int requestCode) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + activity.getPackageName()));
activity.startActivityForResult(intent, requestCode);
}
}
public static boolean hasSecureSettingsPermission(Context context) {
return context.checkCallingOrSelfPermission(
"android.permission.WRITE_SECURE_SETTINGS") == PackageManager.PERMISSION_GRANTED;
}
}
5.2 系统属性权限
5.2.1 SELinux策略
# 允许应用读取属性
allow appdomain property_socket:sock_file { read write getattr };
# 允许应用设置属性
allow appdomain property_service:service_manager { find };
# 允许访问特定属性
allow appdomain system_prop:property_service { set };
5.2.2 权限检查
public class PropertyPermissionHelper {
public static boolean canSetProperty(String propertyName) {
// 检查当前进程权限
if (Process.myUid() == Process.SYSTEM_UID) {
return true;
}
// 检查selinux上下文
String context = SELinux.getContext();
return context != null && context.contains("system");
}
public static void setPropertyWithPermissionCheck(String key, String value) {
if (canSetProperty(key)) {
SystemProperties.set(key, value);
} else {
Log.w("PropertyHelper", "No permission to set property: " + key);
}
}
}
六、性能优化与最佳实践
6.1 系统设置项优化
6.1.1 批量操作
public class SettingsBatchHelper {
public static void batchUpdateSettings(Context context, ContentValues[] values) {
ContentResolver resolver = context.getContentResolver();
// 使用ContentProviderOperation进行批量操作
ArrayList<ContentProviderOperation> operations = new ArrayList<>();
for (ContentValues value : values) {
operations.add(ContentProviderOperation.newUpdate(
Settings.Global.CONTENT_URI)
.withValues(value)
.build());
}
try {
resolver.applyBatch(Settings.AUTHORITY, operations);
} catch (Exception e) {
Log.e("SettingsBatchHelper", "Batch update failed", e);
}
}
}
6.1.2 异步操作
public class SettingsAsyncHelper {
public static void getSettingAsync(Context context, String key,
OnSettingResultListener listener) {
new AsyncTask<Void, Void, String>() {
@Override
protected String doInBackground(Void... voids) {
return Settings.Global.getString(context.getContentResolver(), key);
}
@Override
protected void onPostExecute(String result) {
if (listener != null) {
listener.onResult(result);
}
}
}.execute();
}
public interface OnSettingResultListener {
void onResult(String value);
}
}
6.2 系统属性优化
6.2.1 属性缓存
public class PropertyCache {
private static final ConcurrentHashMap<String, String> sCache = new ConcurrentHashMap<>();
public static String get(String key, String defaultValue) {
String value = sCache.get(key);
if (value == null) {
value = SystemProperties.get(key, defaultValue);
sCache.put(key, value);
}
return value;
}
public static void invalidate(String key) {
sCache.remove(key);
}
public static void invalidateAll() {
sCache.clear();
}
}
6.2.2 属性监听优化
public class PropertyChangeManager {
private static final String TAG = "PropertyChangeManager";
private static final long DEBOUNCE_DELAY = 1000; // 1秒防抖
private final Handler mHandler = new Handler(Looper.getMainLooper());
private final Runnable mPropertyChangeCallback;
private final Set<String> mWatchedProperties = new HashSet<>();
public PropertyChangeManager(Runnable callback) {
mPropertyChangeCallback = callback;
SystemProperties.addChangeCallback(this::onPropertyChange);
}
private void onPropertyChange() {
// 防抖处理
mHandler.removeCallbacks(mPropertyChangeCallback);
mHandler.postDelayed(mPropertyChangeCallback, DEBOUNCE_DELAY);
}
public void watchProperty(String property) {
mWatchedProperties.add(property);
}
public void unwatchProperty(String property) {
mWatchedProperties.remove(property);
}
public void destroy() {
mHandler.removeCallbacksAndMessages(null);
// 注意:SystemProperties.removeChangeCallback需要传入相同的Runnable实例
}
}
七、调试与问题排查
7.1 系统设置项调试
7.1.1 查看所有设置项
# 查看Global设置
adb shell content query --uri content://settings/global
# 查看System设置
adb shell content query --uri content://settings/system
# 查看Secure设置
adb shell content query --uri content://settings/secure
# 按条件查询
adb shell content query --uri content://settings/global --where "name='wifi_on'"
# 插入设置项
adb shell content insert --uri content://settings/global --bind name:s:test_key --bind value:s:test_value
# 更新设置项
adb shell content update --uri content://settings/global --bind value:s:new_value --where "name='test_key'"
# 删除设置项
adb shell content delete --uri content://settings/global --where "name='test_key'"
7.1.2 设置项变化监听
# 监听ContentProvider变化
adb shell content observe --uri content://settings/global
7.2 系统属性调试
7.2.1 查看属性
# 查看所有属性
adb shell getprop
# 查看特定属性
adb shell getprop ro.build.version.release
# 查看属性分类
adb shell getprop | grep "ro\."
adb shell getprop | grep "persist\."
adb shell getprop | grep "sys\."
7.2.2 设置属性
# 设置属性(需要root权限)
adb shell setprop debug.performance.tuning 1
# 设置持久化属性
adb shell setprop persist.sys.debug true
7.2.3 属性变化监听
# 监听属性变化
adb shell watchprops
7.3 常见问题排查
7.3.1 权限问题
# 检查应用权限
adb shell dumpsys package <package_name> | grep permission
# 检查SELinux权限
adb shell dmesg | grep avc
adb shell cat /proc/kmsg | grep avc
7.3.2 数据库问题
# 查看Settings数据库
adb shell sqlite3 /data/data/com.android.providers.settings/databases/settings.db
sqlite> .tables
sqlite> select * from global;
sqlite> select * from system;
sqlite> select * from secure;
7.3.3 属性文件问题
# 查看属性文件
adb shell cat /system/build.prop
adb shell cat /vendor/build.prop
adb shell cat /default.prop
# 查看属性服务状态
adb shell ps | grep property
八、总结
系统设置项和系统属性是Android Framework中两个重要的配置管理机制,它们分别适用于不同的场景:
- 系统设置项:适用于应用配置、用户偏好设置等需要持久化存储的场景,通过ContentProvider提供安全的访问控制
- 系统属性:适用于系统启动参数、运行时状态等高性能要求的场景,通过共享内存提供快速的读写能力
在实际开发中,需要根据具体需求选择合适的机制,并注意权限管理和性能优化。同时,掌握相关的调试工具和问题排查方法,能够帮助快速定位和解决配置相关的问题。
若内容若侵犯到您的权益,请发送邮件至:platform_service@jienda.com我们将第一时间处理!
所有资源仅限于参考和学习,版权归JienDa作者所有,更多请访问JienDa首页。
