本文系统介绍了Android系统设置的访问与管理方法,重点解析了adb shell settings命令的三大命名空间(system、global、secure)及其常用操作。同时详细阐述了如何在应用程序中通过ContentResolver和Settings API编程读写系统配置,包括权限要求、设置监听等关键技术要点。此外,本文还补充了系统属性访问的adb shell getpropadb shell setprop命令,为系统调试、自动化测试和高级功能开发提供了核心支持,是Android开发者深入理解设备行为、实现定制化需求的重要基础。

博主博客

一、概述

Android 系统提供了丰富的配置选项,这些设置分布在不同的命名空间中,可以通过 adb shell settings 命令或代码 API 进行访问和修改。此外,Android 还提供了系统属性访问机制,通过 adb shell getpropadb shell setprop 命令可以访问和修改系统底层属性。了解这些系统设置和属性对于开发、测试和系统定制都至关重要。

二、adb shell settings 命令详解

2.1 基础命令结构

# 基本语法
adb shell settings [subcommand] [namespace] [key] [value]

# 获取设置值
adb shell settings get system screen_brightness
adb shell settings get global airplane_mode_on
adb shell settings get secure location_providers_allowed

# 列出所有设置
adb shell settings list system
adb shell settings list global
adb shell settings list secure

2.2 三种命名空间

  1. system - 与设备特定相关的设置

    # 屏幕相关设置
    adb shell settings get system screen_brightness
    adb shell settings get system screen_brightness_mode
    
    # 声音设置
    adb shell settings get system volume_music
    adb shell settings get system volume_ring
    
    # 显示设置
    adb shell settings get system font_scale
    adb shell settings get system screen_off_timeout
    
  2. global - 跨所有用户/应用的全局设置

    # 网络相关
    adb shell settings get global airplane_mode_on
    adb shell settings get global wifi_on
    adb shell settings get global bluetooth_on
    
    # 开发选项
    adb shell settings get global adb_enabled
    adb shell settings get global stay_on_while_plugged_in
    
    # 系统状态
    adb shell settings get global device_provisioned
    
  3. secure - 安全敏感设置(需要权限)

    # 位置服务
    adb shell settings get secure location_providers_allowed
    
    # 锁屏设置
    adb shell settings get secure lock_screen_lock_after_timeout
    
    # 输入法
    adb shell settings get secure default_input_method
    

2.3 常用操作命令

# 设置值
adb shell settings put system screen_brightness 200
adb shell settings put global airplane_mode_on 1

# 删除设置
adb shell settings delete system screen_brightness

# 重置设置
adb shell settings reset system
adb shell settings reset global

# 查看帮助
adb shell settings --help

2.4 系统属性(system properties)访问

除了系统设置,Android还提供了系统属性访问机制,通过adb shell getpropadb shell setprop命令可以访问和修改系统底层属性。

# 基本语法
adb shell getprop [属性名]
adb shell setprop [属性名] [属性值]

# 获取所有系统属性
adb shell getprop

# 获取特定属性值
adb shell getprop ro.build.version.release  # Android版本
adb shell getprop ro.product.model          # 设备型号
adb shell getprop ro.serialno               # 设备序列号
adb shell getprop persist.sys.timezone      # 系统时区

# 设置属性值
adb shell setprop debug.layout true         # 开启布局调试
adb shell setprop log.tag.MyApp VERBOSE     # 设置日志级别

# 查看与网络相关的属性
adb shell getprop | grep net

# 查看与Dalvik/ART虚拟机相关的属性
adb shell getprop | grep dalvik
adb shell getprop | grep art

2.4.1 系统属性分类

  1. 只读属性(ro.* - 系统启动时设置,不可更改

    adb shell getprop ro.build.version.sdk      # SDK版本
    adb shell getprop ro.build.version.release  # Android版本号
    adb shell getprop ro.product.manufacturer   # 制造商
    adb shell getprop ro.product.model          # 设备型号
    adb shell getprop ro.build.type             # 构建类型(user/userdebug/eng)
    
  2. 持久化属性(persist.* - 重启后仍然保留

    adb shell getprop persist.sys.timezone      # 时区设置
    adb shell getprop persist.sys.language      # 语言设置
    adb shell getprop persist.sys.country       # 国家设置
    
  3. 控制属性(ctl.* - 用于控制服务

    adb shell setprop ctl.start surfaceflinger  # 启动surfaceflinger服务
    adb shell setprop ctl.stop zygote           # 停止zygote服务
    
  4. 调试属性(debug.* - 用于系统调试

    adb shell setprop debug.sf.showupdates 1    # 显示SurfaceFlinger更新
    adb shell setprop debug.egl.trace 1         # 开启EGL跟踪
    adb shell setprop debug.layout true         # 开启布局调试
    

2.4.2 常用系统属性

# 设备信息
adb shell getprop ro.product.brand            # 品牌
adb shell getprop ro.product.name             # 产品名称
adb shell getprop ro.build.fingerprint        # 构建指纹
adb shell getprop ro.build.id                 # 构建ID
adb shell getprop ro.build.tags               # 构建标签
adb shell getprop ro.build.display.id         # 显示ID

# 系统配置
adb shell getprop ro.config.low_ram           # 是否为低内存设备
adb shell getprop ro.config.small_battery     # 是否为小电池设备
adb shell getprop dalvik.vm.heapstartsize     # 堆起始大小
adb shell getprop dalvik.vm.heapsize          # 堆大小

# 网络相关
adb shell getprop net.dns1                    # 主DNS
adb shell getprop net.dns2                    # 备用DNS
adb shell getprop net.eth0.dns1               # 以太网DNS
adb shell getprop net.rmnet0.dns1             # 移动网络DNS

# 调试相关
adb shell getprop debug.hwui.render_dirty_regions  # 渲染脏区域
adb shell getprop debug.performance.tuning         # 性能调优
adb shell getprop debug.force_rtl                  # 强制RTL布局

2.4.3 属性与设置的区别

特性 系统设置 (Settings) 系统属性 (Properties)
存储位置 数据库(settings.db) 属性文件(/system/build.prop等)和内存
访问方式 adb shell settings 或 ContentResolver adb shell getprop/setprop
权限要求 分命名空间,secure需要特殊权限 读通常无限制,写需要root权限
作用范围 主要影响应用层和系统UI 系统底层、服务、内核参数
持久化 自动持久化到数据库 非persist属性重启后丢失

三、代码中访问系统设置

3.1 通过 ContentResolver 访问

import android.content.ContentResolver;
import android.provider.Settings;

public class SystemSettingsHelper {
    
    private ContentResolver mContentResolver;
    
    public SystemSettingsHelper(ContentResolver contentResolver) {
        this.mContentResolver = contentResolver;
    }
    
    // 获取系统设置
    public int getScreenBrightness() {
        try {
            return Settings.System.getInt(
                mContentResolver, 
                Settings.System.SCREEN_BRIGHTNESS
            );
        } catch (Settings.SettingNotFoundException e) {
            e.printStackTrace();
            return -1;
        }
    }
    
    // 获取全局设置
    public int isAirplaneModeOn() {
        try {
            return Settings.Global.getInt(
                mContentResolver,
                Settings.Global.AIRPLANE_MODE_ON
            );
        } catch (Settings.SettingNotFoundException e) {
            e.printStackTrace();
            return 0;
        }
    }
    
    // 获取安全设置(需要权限)
    public String getDefaultInputMethod() {
        return Settings.Secure.getString(
            mContentResolver,
            Settings.Secure.DEFAULT_INPUT_METHOD
        );
    }
    
    // 修改设置
    public boolean setScreenBrightness(int brightness) {
        // 亮度值范围:0-255
        brightness = Math.max(0, Math.min(255, brightness));
        
        return Settings.System.putInt(
            mContentResolver,
            Settings.System.SCREEN_BRIGHTNESS,
            brightness
        );
    }
    
    // 监听设置变化
    public void registerSettingsObserver() {
        ContentResolver contentResolver = mContentResolver;
        
        contentResolver.registerContentObserver(
            Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS),
            false,
            new ContentObserver(new Handler()) {
                @Override
                public void onChange(boolean selfChange) {
                    super.onChange(selfChange);
                    int brightness = getScreenBrightness();
                    onBrightnessChanged(brightness);
                }
            }
        );
    }
    
    private void onBrightnessChanged(int brightness) {
        // 处理亮度变化
        Log.d("Settings", "亮度已更改为: " + brightness);
    }
}

3.2 使用 Settings.System 常量

Android 提供了完整的设置键名常量:

// 系统设置常量
Settings.System.SCREEN_BRIGHTNESS
Settings.System.SCREEN_BRIGHTNESS_MODE
Settings.System.VOLUME_MUSIC
Settings.System.VIBRATE_ON

// 全局设置常量  
Settings.Global.AIRPLANE_MODE_ON
Settings.Global.WIFI_ON
Settings.Global.BLUETOOTH_ON
Settings.Global.DEVICE_PROVISIONED

// 安全设置常量
Settings.Secure.LOCATION_PROVIDERS_ALLOWED
Settings.Secure.ANDROID_ID
Settings.Secure.INSTALL_NON_MARKET_APPS

3.3 代码中访问系统属性

在应用程序中,也可以通过 SystemProperties 类访问系统属性(需要系统权限):

import android.os.SystemProperties;

public class SystemPropertiesHelper {
    
    // 获取系统属性
    public static String getSystemProperty(String key, String defaultValue) {
        return SystemProperties.get(key, defaultValue);
    }
    
    // 设置系统属性(需要系统权限)
    public static void setSystemProperty(String key, String value) {
        SystemProperties.set(key, value);
    }
    
    // 示例:获取SDK版本
    public static String getSDKVersion() {
        return SystemProperties.get("ro.build.version.sdk", "unknown");
    }
    
    // 示例:获取设备型号
    public static String getDeviceModel() {
        return SystemProperties.get("ro.product.model", "unknown");
    }
    
    // 示例:检查是否为调试版本
    public static boolean isDebugBuild() {
        String buildType = SystemProperties.get("ro.build.type", "user");
        return "eng".equals(buildType) || "userdebug".equals(buildType);
    }
    
    // 示例:设置调试属性
    public static void enableLayoutDebug() {
        SystemProperties.set("debug.layout", "true");
    }
}

注意:SystemProperties 类是隐藏API,通常只有系统应用可以使用。普通应用可以通过反射调用,但需要系统签名权限。

3.4 权限要求

在 AndroidManifest.xml 中添加相应权限:

<!-- 读取系统设置 -->
<uses-permission android:name="android.permission.READ_SETTINGS" />

<!-- 写入系统设置(需要系统签名或特殊权限) -->
<uses-permission android:name="android.permission.WRITE_SETTINGS"
    android:protectionLevel="signature|system" />

<!-- 安全设置权限 -->
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"
    android:protectionLevel="signature" />

<!-- 读取系统属性(通常需要系统权限) -->
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
    android:protectionLevel="signature" />

四、实际应用示例

4.1 屏幕亮度控制工具

public class BrightnessController {
    
    public static void setAutoBrightness(Context context, boolean enabled) {
        Settings.System.putInt(
            context.getContentResolver(),
            Settings.System.SCREEN_BRIGHTNESS_MODE,
            enabled ? Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC 
                    : Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL
        );
    }
    
    public static void adjustBrightness(Context context, int levelPercent) {
        int brightness = (int) (255 * levelPercent / 100.0);
        brightness = Math.max(0, Math.min(255, brightness));
        
        // 设置亮度
        Settings.System.putInt(
            context.getContentResolver(),
            Settings.System.SCREEN_BRIGHTNESS,
            brightness
        );
        
        // 更新窗口亮度(立即生效)
        Window window = ((Activity) context).getWindow();
        WindowManager.LayoutParams layoutParams = window.getAttributes();
        layoutParams.screenBrightness = brightness / 255f;
        window.setAttributes(layoutParams);
    }
}

4.2 系统状态监控

public class SystemStateMonitor {
    
    private static final String[] MONITORED_SETTINGS = {
        Settings.Global.AIRPLANE_MODE_ON,
        Settings.Global.WIFI_ON,
        Settings.Global.BLUETOOTH_ON,
        Settings.System.SCREEN_BRIGHTNESS
    };
    
    public void startMonitoring(Context context) {
        ContentResolver resolver = context.getContentResolver();
        
        for (String setting : MONITORED_SETTINGS) {
            resolver.registerContentObserver(
                Settings.System.getUriFor(setting),
                true,
                mSettingsObserver
            );
        }
    }
    
    private final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) {
        @Override
        public void onChange(boolean selfChange, Uri uri) {
            super.onChange(selfChange, uri);
            
            String key = uri.getLastPathSegment();
            Log.i("SystemMonitor", "设置变更: " + key);
            
            // 根据变更的设置执行相应操作
            handleSettingChange(key);
        }
    };
    
    private void handleSettingChange(String key) {
        switch (key) {
            case Settings.Global.AIRPLANE_MODE_ON:
                // 处理飞行模式变更
                break;
            case Settings.Global.WIFI_ON:
                // 处理WiFi开关变更
                break;
            // ... 其他设置处理
        }
    }
}

4.3 设备信息获取工具

public class DeviceInfoHelper {
    
    /**
     * 获取设备信息(通过系统属性)
     */
    public static Map<String, String> getDeviceInfo() {
        Map<String, String> info = new LinkedHashMap<>();
        
        // 设备基本信息
        info.put("品牌", getSystemProperty("ro.product.brand", "未知"));
        info.put("型号", getSystemProperty("ro.product.model", "未知"));
        info.put("制造商", getSystemProperty("ro.product.manufacturer", "未知"));
        info.put("设备", getSystemProperty("ro.product.device", "未知"));
        
        // 系统版本信息
        info.put("Android版本", getSystemProperty("ro.build.version.release", "未知"));
        info.put("SDK版本", getSystemProperty("ro.build.version.sdk", "未知"));
        info.put("构建ID", getSystemProperty("ro.build.id", "未知"));
        info.put("构建类型", getSystemProperty("ro.build.type", "未知"));
        
        // 硬件信息
        info.put("处理器", getSystemProperty("ro.product.cpu.abi", "未知"));
        info.put("硬件", getSystemProperty("ro.hardware", "未知"));
        info.put("序列号", getSystemProperty("ro.serialno", "未知"));
        
        // 显示信息
        info.put("屏幕密度", getSystemProperty("ro.sf.lcd_density", "未知"));
        info.put("屏幕尺寸", getSystemProperty("ro.config.screen_size", "未知"));
        
        return info;
    }
    
    /**
     * 获取网络信息(通过系统属性)
     */
    public static Map<String, String> getNetworkInfo() {
        Map<String, String> info = new LinkedHashMap<>();
        
        info.put("主机名", getSystemProperty("net.hostname", "未知"));
        info.put("主DNS", getSystemProperty("net.dns1", "未知"));
        info.put("备用DNS", getSystemProperty("net.dns2", "未知"));
        info.put("DHCP状态", getSystemProperty("dhcp.wlan0.state", "未知"));
        info.put("IP地址", getSystemProperty("dhcp.wlan0.ipaddress", "未知"));
        info.put("网关", getSystemProperty("dhcp.wlan0.gateway", "未知"));
        
        return info;
    }
    
    /**
     * 获取系统属性(通过反射调用SystemProperties)
     */
    private static String getSystemProperty(String key, String defaultValue) {
        try {
            Class<?> systemProperties = Class.forName("android.os.SystemProperties");
            Method getMethod = systemProperties.getMethod("get", String.class, String.class);
            return (String) getMethod.invoke(null, key, defaultValue);
        } catch (Exception e) {
            e.printStackTrace();
            return defaultValue;
        }
    }
}

五、调试技巧与注意事项

5.1 调试技巧

  1. 批量导出设置

    # 导出所有系统设置到文件
    adb shell settings list system > system_settings.txt
    adb shell settings list global > global_settings.txt
    adb shell settings list secure > secure_settings.txt
    
  2. 批量导出系统属性

    # 导出所有系统属性到文件
    adb shell getprop > all_properties.txt
    
    # 导出特定类型的属性
    adb shell getprop | grep ro.product > product_properties.txt
    adb shell getprop | grep persist > persistent_properties.txt
    adb shell getprop | grep debug > debug_properties.txt
    
  3. 对比设置变化

    # 修改设置前备份
    adb shell settings list system > before.txt
    
    # 进行操作...
    
    # 修改后对比
    adb shell settings list system > after.txt
    diff before.txt after.txt
    
  4. 通过adb快速测试

    # 测试亮度调整
    adb shell settings put system screen_brightness 100
    adb shell settings put system screen_brightness_mode 0
    
    # 测试飞行模式
    adb shell settings put global airplane_mode_on 1
    adb shell am broadcast -a android.intent.action.AIRPLANE_MODE
    
    # 测试系统属性
    adb shell setprop debug.layout true
    adb shell getprop debug.layout
    
  5. 动态观察属性变化

    # 持续监控属性变化
    adb shell watchprops
    
    # 监控特定属性
    adb shell watchprop | grep debug
    

5.2 系统属性调试技巧

  1. 临时修改属性进行调试

    # 开启布局边界显示
    adb shell setprop debug.layout true
    
    # 开启过度绘制显示
    adb shell setprop debug.hwui.overdraw show
    
    # 开启GPU呈现模式分析
    adb shell setprop debug.hwui.profile visual_bars
    
    # 设置日志级别
    adb shell setprop log.tag.MyApp VERBOSE
    adb shell setprop log.tag.System.err ERROR
    
  2. 通过属性控制服务行为

    # 重启SurfaceFlinger(图形服务)
    adb shell setprop ctl.restart surfaceflinger
    
    # 重启Zygote(应用进程孵化器)
    adb shell setprop ctl.restart zygote
    
    # 启动/停止服务
    adb shell setprop ctl.start [service_name]
    adb shell setprop ctl.stop [service_name]
    
  3. 查看运行时信息

    # 查看当前活动的属性
    adb shell getprop | grep running
    
    # 查看内存相关属性
    adb shell getprop | grep memory
    adb shell getprop | grep heap
    
    # 查看性能相关属性
    adb shell getprop | grep perf
    adb shell getprop | grep debug.sf
    

5.3 注意事项

  1. 权限限制

    • secure 命名空间需要系统级权限
    • WRITE_SETTINGS 权限需要动态申请(Android 6.0+)
    • 某些设置只能在系统应用或具有特定权限的应用中修改
    • 系统属性修改通常需要root权限
  2. 版本兼容性

    // 检查设置是否存在
    public boolean isSettingAvailable(String settingName) {
        try {
            // 尝试读取设置,如果抛出异常则说明不存在
            Settings.System.getInt(mContentResolver, settingName);
            return true;
        } catch (Settings.SettingNotFoundException e) {
            return false;
        }
    }
    
    // 检查属性是否存在
    public boolean isPropertyAvailable(String propName) {
        String value = SystemProperties.get(propName, null);
        return value != null && !value.isEmpty();
    }
    
  3. 线程安全

    • ContentResolver 操作应在工作线程执行
    • UI 更新应在主线程进行
    • 系统属性操作需要注意同步问题
  4. 属性持久化问题

    # 注意:setprop设置的属性默认不会持久化,重启后丢失
    adb shell setprop my.custom.property "test"
    
    # 要持久化属性,需要使用persist.前缀
    adb shell setprop persist.my.custom.property "test"
    
    # 或者修改属性文件(需要root)
    adb shell su -c "echo 'my.custom.property=test' >> /system/build.prop"
    
  5. 设置变更监听最佳实践

    public class SettingsMonitor {
        private ContentResolver mResolver;
        private Map<String, ContentObserver> mObservers = new HashMap<>();
        
        public void observeSetting(String key, Consumer<String> callback) {
            Uri uri = Settings.System.getUriFor(key);
            ContentObserver observer = new ContentObserver(new Handler()) {
                @Override
                public void onChange(boolean selfChange) {
                    callback.accept(key);
                }
            };
            
            mResolver.registerContentObserver(uri, false, observer);
            mObservers.put(key, observer);
        }
        
        public void stopObserving() {
            for (ContentObserver observer : mObservers.values()) {
                mResolver.unregisterContentObserver(observer);
            }
            mObservers.clear();
        }
    }
    

六、常见问题与解决方案

6.1 设置修改不生效

问题:通过代码修改了设置,但系统没有立即响应。

解决方案

// 1. 发送广播通知系统
public static void setAirplaneMode(Context context, boolean enabled) {
    Settings.Global.putInt(
        context.getContentResolver(),
        Settings.Global.AIRPLANE_MODE_ON,
        enabled ? 1 : 0
    );
    
    // 发送广播使设置生效
    Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
    intent.putExtra("state", enabled);
    context.sendBroadcast(intent);
}

// 2. 对于亮度等设置,需要同时更新窗口属性
private void applyBrightnessImmediately(int brightness) {
    if (getActivity() != null) {
        Window window = getActivity().getWindow();
        WindowManager.LayoutParams layoutParams = window.getAttributes();
        layoutParams.screenBrightness = brightness / 255f;
        window.setAttributes(layoutParams);
    }
}

6.2 权限不足问题

问题:无法修改某些系统设置。

解决方案

  1. 检查应用是否具有相应权限
  2. 检查应用是否被授予特殊权限(系统应用)
  3. 使用 fallback 方案:
public boolean trySetBrightness(int brightness) {
    // 方法1:尝试通过系统API设置
    if (hasWriteSettingsPermission()) {
        return Settings.System.putInt(
            mContentResolver,
            Settings.System.SCREEN_BRIGHTNESS,
            brightness
        );
    }
    
    // 方法2:尝试通过无障碍服务(如果需要)
    if (isAccessibilityServiceEnabled()) {
        return setBrightnessViaAccessibility(brightness);
    }
    
    // 方法3:显示系统设置页面让用户手动调整
    showSystemSettingsPage();
    return false;
}

6.3 属性设置相关问题

问题:通过 setprop 设置的属性重启后丢失。

解决方案

  1. 使用 persist. 前缀的属性名,这样设置后会被保存到持久化存储中。
    adb shell setprop persist.debug.layout true
    
  2. 如果没有使用 persist. 前缀,可以将其添加到 /data/local.prop/system/build.prop 文件中(需要root权限)。

问题:无法设置属性,提示权限不足。

解决方案

  1. 确保设备已 root。
  2. 使用 su 命令提升权限:
    adb shell su -c setprop debug.layout true
    
  3. 如果是系统应用,确保在 AndroidManifest.xml 中声明了 android:sharedUserId="android.uid.system" 并使用系统签名。

6.4 安全限制问题

问题:某些安全设置无法在非系统应用中修改。

解决方案

// 1. 使用Settings.Secure.ACTION_REQUEST_SET_AUTOFILL_SERVICE等系统提供的Intent
public void requestSecureSettingChange() {
    // 对于某些安全设置,系统提供了专门的请求方式
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        Intent intent = new Intent(Settings.ACTION_REQUEST_SET_AUTOFILL_SERVICE);
        intent.setData(Uri.parse("package:com.example.myapp"));
        startActivity(intent);
    }
}

// 2. 引导用户到系统设置页面手动修改
public void navigateToSystemSettings(String setting) {
    Intent intent = new Intent();
    
    switch (setting) {
        case "location":
            intent.setAction(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            break;
        case "wifi":
            intent.setAction(Settings.ACTION_WIFI_SETTINGS);
            break;
        case "bluetooth":
            intent.setAction(Settings.ACTION_BLUETOOTH_SETTINGS);
            break;
        default:
            intent.setAction(Settings.ACTION_SETTINGS);
    }
    
    startActivity(intent);
}

七、高级用法

7.1 自动化测试中的设置管理

public class TestSettingsManager {
    
    private Map<String, String> originalSettings = new HashMap<>();
    private Map<String, String> originalProperties = new HashMap<>();
    
    /**
     * 备份并修改测试所需的设置
     */
    public void setupTestEnvironment(Context context) {
        backupSettings(context);
        backupProperties();
        
        // 设置测试环境
        Settings.System.putInt(context.getContentResolver(), 
            Settings.System.SCREEN_BRIGHTNESS, 255);
        Settings.Global.putInt(context.getContentResolver(),
            Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 7);
        
        // 设置测试属性
        executeShellCommand("setprop debug.layout false");
        executeShellCommand("setprop debug.hwui.overdraw false");
    }
    
    /**
     * 恢复原始设置
     */
    public void restoreEnvironment(Context context) {
        restoreSettings(context);
        restoreProperties();
    }
    
    private void backupSettings(Context context) {
        ContentResolver resolver = context.getContentResolver();
        
        try {
            originalSettings.put("screen_brightness",
                String.valueOf(Settings.System.getInt(resolver, 
                    Settings.System.SCREEN_BRIGHTNESS)));
        } catch (Settings.SettingNotFoundException e) {
            e.printStackTrace();
        }
        
        // 备份其他设置...
    }
    
    private void backupProperties() {
        originalProperties.put("debug.layout", 
            executeShellCommand("getprop debug.layout"));
        // 备份其他属性...
    }
    
    private void restoreSettings(Context context) {
        ContentResolver resolver = context.getContentResolver();
        
        for (Map.Entry<String, String> entry : originalSettings.entrySet()) {
            if (entry.getKey().equals("screen_brightness")) {
                Settings.System.putInt(resolver,
                    Settings.System.SCREEN_BRIGHTNESS,
                    Integer.parseInt(entry.getValue()));
            }
            // 恢复其他设置...
        }
    }
    
    private void restoreProperties() {
        for (Map.Entry<String, String> entry : originalProperties.entrySet()) {
            executeShellCommand("setprop " + entry.getKey() + " " + entry.getValue());
        }
    }
    
    private String executeShellCommand(String command) {
        try {
            Process process = Runtime.getRuntime().exec(command);
            BufferedReader reader = new BufferedReader(
                new InputStreamReader(process.getInputStream()));
            StringBuilder output = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                output.append(line);
            }
            process.waitFor();
            return output.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }
}

7.2 系统属性监控工具

public class PropertyMonitor {
    
    private static final String TAG = "PropertyMonitor";
    private ExecutorService executorService = Executors.newSingleThreadExecutor();
    private volatile boolean isMonitoring = false;
    
    /**
     * 开始监控属性变化
     */
    public void startMonitoring(String propertyName, PropertyChangeListener listener) {
        isMonitoring = true;
        executorService.execute(() -> {
            String lastValue = getPropertyValue(propertyName);
            
            while (isMonitoring) {
                try {
                    Thread.sleep(1000); // 每秒检查一次
                    
                    String currentValue = getPropertyValue(propertyName);
                    if (!currentValue.equals(lastValue)) {
                        lastValue = currentValue;
                        listener.onPropertyChanged(propertyName, currentValue);
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
        });
    }
    
    /**
     * 停止监控
     */
    public void stopMonitoring() {
        isMonitoring = false;
        executorService.shutdownNow();
    }
    
    /**
     * 获取属性值
     */
    private String getPropertyValue(String propertyName) {
        try {
            Class<?> systemProperties = Class.forName("android.os.SystemProperties");
            Method getMethod = systemProperties.getMethod("get", String.class);
            return (String) getMethod.invoke(null, propertyName);
        } catch (Exception e) {
            Log.e(TAG, "获取属性失败: " + propertyName, e);
            return "";
        }
    }
    
    /**
     * 监控多个属性
     */
    public void monitorMultipleProperties(List<String> properties, 
                                         PropertyChangeListener listener) {
        for (String property : properties) {
            startMonitoring(property, listener);
        }
    }
    
    public interface PropertyChangeListener {
        void onPropertyChanged(String propertyName, String newValue);
    }
}

八、总结

通过 adb shell settings 命令、adb shell getprop/setprop 命令和相应的代码 API,开发者可以有效地访问和控制系统设置与属性。关键点包括:

  1. 理解系统设置的三个命名空间:system、global、secure 的不同用途和权限要求
  2. 掌握系统属性的访问:通过 getprop/setprop 命令访问和修改系统底层属性
  3. 正确使用API:通过 ContentResolver、Settings 类和 SystemProperties 类访问设置和属性
  4. 处理权限问题:了解不同设置和属性所需的权限级别
  5. 监控设置变化:使用 ContentObserver 监听设置变更
  6. 考虑兼容性:处理不同 Android 版本的差异
  7. 理解设置与属性的区别:根据需求选择合适的方式

8.1 选择使用场景

  1. 使用系统设置(Settings)的场景

    • 修改用户界面相关的配置(亮度、音量、显示设置等)
    • 访问应用层配置(输入法、默认应用等)
    • 需要持久化且跨应用共享的配置
    • 用户可通过系统设置UI修改的选项
  2. 使用系统属性(Properties)的场景

    • 系统底层调试和调优
    • 控制系统服务行为
    • 设备硬件信息获取
    • 运行时系统参数调整
    • 开发阶段的功能开关

8.2 最佳实践建议

  1. 权限最小化原则:只申请必要的权限,避免过度申请敏感权限
  2. 异常处理:对可能失败的操作进行适当的异常处理
  3. 版本兼容性检查:在使用新API前检查Android版本
  4. 用户透明度:对于需要修改系统设置的功能,应明确告知用户
  5. 回退方案:当无法直接修改设置时,提供替代方案(如引导到系统设置页面)

这些工具和 API 为系统定制、自动化测试、性能调优和高级功能开发提供了强大的支持。在实际使用中,应根据具体需求、权限限制和设备特性选择合适的访问方式,并遵循最佳实践以确保应用的稳定性和安全性。