栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Android系统App之SettingsProvider

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android系统App之SettingsProvider

(1)概述

(A)

SettingsProvider顾名思义是一个提供设置数据共享的Provider,SettingsProvider和Android系统其它Provider有很多不一样的地方,如:

  • SettingsProvider只接受int、float、string等基本类型的数据;
  • SettingsProvider由Android系统framework进行了封装,使用更加快捷方便;
  • SettingsProvider的数据由键值对组成;

(B)

SettingsProvider有点类似Android的SystemProperties。SystemProperties除具有SettingsProvider以上的三个特性,SettingsProvider和SystemProperties的不同点在于:

  • 数据保存方式不同:SystemProperties的数据保存属性文件中(/system/build.prop等),开机后会被加载到system properties store,SettingsProvider的数据保存在文件/data/system/users/0/settings_***.xml和数据库settings.db中;
  • 作用范围不同:SystemProperties可以实现跨进程、跨层次调用,即底层的c/c++可以调用,java层也可以调用,SettingProvider只能在java层(APP)使用;

在Android 6.0版本时,SettingsProvider被重构,Android从性能、安全等方面考虑,把SettingsProvider中原本保存在settings.db中的数据,目前全部保存在XML文件中。

(C)

SettingsProvider对数据进行了分类,分别是Global、System、Secure三种类型,它们的区别如下:

  • Global:所有的偏好设置对系统的所有用户公开,第三方APP有读没有写的权限;
  • System:包含各种各样的用户偏好系统设置;
  • Secure:安全性的用户偏好系统设置,第三方APP有读没有写的权限;

上面对Global、System、Secure分别生成一个File对象实例,它们的File对象分别对应的文件是:

/data/system/users/0/settings_global.xml
/data/system/users/0/settings_system.xml
/data/system/users/0/settings_secure.xml

也就是说,Global类型的数据保存在文件settings_global.xml中,System类型的数据保存在文件settings_system.xml中,Secure类型的数据保存在文件settings_secure.xml中。

(2)AndroidManifest.xml

//frameworks/base/packages/SettingsProvider/AndroidManifest.xml


    

        

    

由上面Manifest配置的sharedUserId可知,SettingsProvider运行在系统进程中,定义的ContentProvider实现类是SettingsProvider。

(3)Code位置

在frameworks中跟Setting默认值相关的几个文件:

  • /frameworks/base/packages/SettingsProvider/res/values/defaults.xml
  • /frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
  • /frameworks/base/core/java/android/provider/Settings.java

(4)defaults.xml
在defaults.xml文件中定义了相关的值,DatabaseHelper.java会把相应的值读取出来保存到ContentProvider。

//frameworks/base/packages/SettingsProvider/res/values/defaults.xml

    true
    60000
    -1
    false
    false
    
    cell,bluetooth,wifi,nfc,wimax
    bluetooth,wifi,nfc
    0
    true
    true
    false
    
    102
    false
    100%
    100%
    true

    true
    false
    false
    
    3
    true
    true
    true
    false
    
    2
    true
    true

    false
    com.android.localtransport/.LocalTransport

    
    true

    true
    false
    true
    true

    
    1
    /product/media/audio/ui/LowBattery.ogg
    0
    0
    /product/media/audio/ui/Dock.ogg
    /product/media/audio/ui/Undock.ogg
    /product/media/audio/ui/Dock.ogg
    /product/media/audio/ui/Undock.ogg
    1
    /product/media/audio/ui/Lock.ogg
    /product/media/audio/ui/Unlock.ogg
    /product/media/audio/ui/Trusted.ogg
    /product/media/audio/ui/WirelessChargingStarted.ogg
    /product/media/audio/ui/ChargingStarted.ogg

    
    1000
    15000

    false
    false
    1

    
    true

    
    true

    
    true

    
    true

    
    false

    
    200%

    
    false

    
    true

    
    0

    
    -1
    
    -1

    
    400

    
    300

    
    false

    
    0

    
    true
    
    true

    
    false

    
    9

    
    false

    
    0

    
    

    
    0

    
    1

    
    true

    
    1

    
    %1$s %2$s

    
    %1$s

    
    true

    
    true

    
    

    
    false

    
    0x2

    
    false

    
    

    
    true

    
    

    
    0

    
    

    
    false

    
    false

    
    true

    
    true

    
    true

    
    false

    
    false

    
    false

    
    false

    
    false

(5)DatabaseHelper.java

//frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java

class DatabaseHelper extends SQLiteOpenHelper {
    private static final String TAG = "SettingsProvider";
    private static final String DATAbase_NAME = "settings.db";

	private static final int DATAbase_VERSION = 118;
	private static final String DATAbase_BACKUP_SUFFIX = "-backup";

    private static final String TABLE_SYSTEM = "system";
    private static final String TABLE_SECURE = "secure";
    private static final String TABLE_GLOBAL = "global";


	private void createSecureTable(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE secure (" +
                "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
                "name TEXT UNIQUE ON ConFLICT REPLACE," +
                "value TEXT" +
                ");");
        db.execSQL("CREATE INDEX secureIndex1 ON secure (name);");
    }

    private void createGlobalTable(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE global (" +
                "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
                "name TEXT UNIQUE ON ConFLICT REPLACE," +
                "value TEXT" +
                ");");
        db.execSQL("CREATE INDEX globalIndex1 ON global (name);");
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE system (" +
                    "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
                    "name TEXT UNIQUE ON ConFLICT REPLACE," +
                    "value TEXT" +
                    ");");
        db.execSQL("CREATE INDEX systemIndex1 ON system (name);");

        createSecureTable(db);

        // only create the global table for the singleton 'owner/system' user
        if (mUserHandle == UserHandle.USER_SYSTEM) {
            createGlobalTable(db);
        }

        db.execSQL("CREATE TABLE bluetooth_devices (" +
                    "_id INTEGER PRIMARY KEY," +
                    "name TEXT," +
                    "addr TEXT," +
                    "channel INTEGER," +
                    "type INTEGER" +
                    ");");

        db.execSQL("CREATE TABLE bookmarks (" +
                    "_id INTEGER PRIMARY KEY," +
                    "title TEXT," +
                    "folder TEXT," +
                    "intent TEXT," +
                    "shortcut INTEGER," +
                    "ordering INTEGER" +
                    ");");

        db.execSQL("CREATE INDEX bookmarksIndex1 ON bookmarks (folder);");
        db.execSQL("CREATE INDEX bookmarksIndex2 ON bookmarks (shortcut);");

        // Populate bookmarks table with initial bookmarks
        boolean onlyCore = false;
        try {
            onlyCore = IPackageManager.Stub.asInterface(ServiceManager.getService(
                    "package")).isOnlyCoreApps();
        } catch (RemoteException e) {
        }
        if (!onlyCore) {
            loadBookmarks(db);
        }

        // Load initial volume levels into DB
        loadVolumeLevels(db);

        // Load inital settings values
        loadSettings(db);
    }

	//...
	private void loadSettings(SQLiteDatabase db) {
        loadSystemSettings(db);
        loadSecureSettings(db);
        // The global table only exists for the 'owner/system' user
        if (mUserHandle == UserHandle.USER_SYSTEM) {
            loadGlobalSettings(db);
        }
    }

private void loadSystemSettings(SQLiteDatabase db) {
        SQLiteStatement stmt = null;
        try {
            stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
                    + " VALUES(?,?);");

            loadBooleanSetting(stmt, Settings.System.DIM_SCREEN,
                    R.bool.def_dim_screen);
            loadIntegerSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT,
                    R.integer.def_screen_off_timeout);

            // Set default cdma DTMF type
            loadSetting(stmt, Settings.System.DTMF_TONE_TYPE_WHEN_DIALING, 0);

            // Set default hearing aid
            loadSetting(stmt, Settings.System.HEARING_AID, 0);

            // Set default tty mode
            loadSetting(stmt, Settings.System.TTY_MODE, 0);

            loadIntegerSetting(stmt, Settings.System.SCREEN_BRIGHTNESS,
                    R.integer.def_screen_brightness);

            loadIntegerSetting(stmt, Settings.System.SCREEN_BRIGHTNESS_FOR_VR,
                    com.android.internal.R.integer.config_screenBrightnessForVrSettingDefault);

            loadBooleanSetting(stmt, Settings.System.SCREEN_BRIGHTNESS_MODE,
                    R.bool.def_screen_brightness_automatic_mode);

            loadBooleanSetting(stmt, Settings.System.ACCELEROMETER_ROTATION,
                    R.bool.def_accelerometer_rotation);

            loadDefaultHapticSettings(stmt);

            loadBooleanSetting(stmt, Settings.System.NOTIFICATION_LIGHT_PULSE,
                    R.bool.def_notification_pulse);

            loadUISoundEffectsSettings(stmt);

            loadIntegerSetting(stmt, Settings.System.POINTER_SPEED,
                    R.integer.def_pointer_speed);

        } finally {
            if (stmt != null) stmt.close();
        }
    }
}

在DatabaseHelper.java的方法中用于加载defaults.xml定义的相关字段。

(6)封装SettingsProvider接口(Settings.java)

对ContentProvider的一些接口进行封装,以保证在整个Android的java层任何一个地方都能方便、快捷的使用SettingsProvider进行数据查询,数据更新和数据插入。所以,framework有一个类Settings.java对SettingsProvider进行了封装。如下:

//frameworks/base/core/java/android/provider/Settings.java


public final class Settings {

	@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_SETTINGS = "android.settings.SETTINGS";

	@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_USER_SETTINGS =
            "android.settings.USER_SETTINGS";

	//...
	public static final class Global extends NamevalueTable {
		
		public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/global");

		public static final String AIRPLANE_MODE_ON = "airplane_mode_on";
        public static final String THEATER_MODE_ON = "theater_mode_on";
		//...
	}

	public static final class System extends NamevalueTable {
		public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/system");
	}

	public static final class Secure extends NamevalueTable {
        public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/secure");
}

上面的代码中,分别声明了Global、Secure、System三个静态内部类,分别对应SettingsProvider中的Global、Secure、System三种数据类型。Global、Secure、System三个静态内部类会分别持有NamevalueCache的实例变量,进而通过AIDL远程调用IContentProvider。

查询数据需要经过NamevalueCache的getStringForUser()方法,插入数据需要经过putStringForUser()方法。

(7)操作SettingsProvider

由于Settings.java对SettingsProvider进行了封装,所以,使用起来相当简单简洁。Global、Secure、System三种数据类型的使用是几乎相同。

//查询数据
String globalValue = Settings.Global.getString(getContentResolver(), Settings.Global.AIRPLANE_MODE_ON);
//插入数据
boolean isSuccess = Settings.System.putInt(getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);

(8)第三方APP使用SettingsProvider

第三方APP可以通过framework的Settings.java查询SettingsProvider中的设置项,第三APP是否可以修改SettingsProvider的设置项?Android系统不允许第三方APP修改SettingsProvider中的设置项。

查阅SettingsProvider的设置项不需要声明任何权限。
修改SettingsProvider需要权限:

  • android.permission.WRITE_SETTINGS
  • android.permission.WRITE_SECURE_SETTINGS
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/275428.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号