Android Framework:系统设置项(Settings)与系统属性(System Properties)

一、核心概念与差异

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提供安全的访问控制
  • 系统属性:适用于系统启动参数、运行时状态等高性能要求的场景,通过共享内存提供快速的读写能力

在实际开发中,需要根据具体需求选择合适的机制,并注意权限管理和性能优化。同时,掌握相关的调试工具和问题排查方法,能够帮助快速定位和解决配置相关的问题。

版权声明:本文为JienDa博主的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
若内容若侵犯到您的权益,请发送邮件至:platform_service@jienda.com我们将第一时间处理!
所有资源仅限于参考和学习,版权归JienDa作者所有,更多请访问JienDa首页。

给TA赞助
共{{data.count}}人
人已赞助
后端

ThinkPHP 6.x 相比 5.x 性能提升详细报告

2025-12-3 17:16:26

阅读

【C语言】循环嵌套江湖:while小弟+for大哥带你开启封神之路

2025-12-15 16:18:38

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索