旧版是使用数据库管理,数据库的名字是settings.db。而在新版本上,不知道是哪个版本开始的,至少Android6.0已经是这样了,键值对放到xml文件中管理了。分别是:
private static final String SETTINGS_FILE_GLOBAL = "settings_global.xml";
private static final String SETTINGS_FILE_SYSTEM = "settings_system.xml";
private static final String SETTINGS_FILE_SECURE = "settings_secure.xml";
他们所在的路径:
new File(Environment.getUserSystemDirectory(userId),
SETTINGS_FILE_GLOBAL);
public static File getSystemSecureDirectory() {
if (isEncryptedFilesystemEnabled()) {
return new File(SECURE_DATA_DIRECTORY, "system");
} else {
return new File(DATA_DIRECTORY, "system");
}
}
例如我测试的手机上是/data/system/users/0,该目录的settings_global.xml,settings_secure.xml和settings_system.xml三个xml文件就是SettingsProvider中的数据文件。
那么旧版本升级时,怎么处理database和xml文件同时存在呢。
如果存在settings_global.xml存在,那么就不去把database中global表中的数据拷贝到xml中,如果是不存在那么就拷贝到xml中。所以如果一个版本已经升级到新版本了,如果在下一个版本中,继续向database插入数据,即新的键值对,那么这些值是无法被读取到的。因为SettingsProvider提供的读写接口,都是针对xml中的。
关于迁移旧版本数据库中的内容到xml中,可看下面方法:
private void migrateAllLegacySettingsIfNeeded() {
synchronized (mLock) {
final int key = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_OWNER);
File globalFile = getSettingsFile(key);
if (globalFile.exists()) {//如果settings_global.xml存在,则不去迁移了
return;
}
final long identity = Binder.clearCallingIdentity();
try {
List<UserInfo> users = mUserManager.getUsers(true);
final int userCount = users.size();
//迁移database中所有数据到xml中
for (int i = 0; i < userCount; i++) {
final int userId = users.get(i).id;
DatabaseHelper dbHelper = new DatabaseHelper(getContext(), userId);
SQLiteDatabase database = dbHelper.getWritableDatabase();
migrateLegacySettingsForUserLocked(dbHelper, database, userId);
// Upgrade to the latest version.
UpgradeController upgrader = new UpgradeController(userId);
upgrader.upgradeIfNeededLocked();
// Drop from memory if not a running user.
if (!mUserManager.isUserRunning(new UserHandle(userId))) {
removeUserStateLocked(userId, false);
}
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
}
旧版本中修改数据库的途径是:在DatabaseOpenHelper.java中的onUpgrade()中加入如:
if (upgradeVersion < 113) {
db.beginTransaction();
SQLiteStatement stmt = null;
try {
stmt = db.compileStatement("INSERT OR IGNORE INTO secure(name,value)"
+ " VALUES(?,?);");
loadIntegerSetting(stmt, Settings.Secure.SLEEP_TIMEOUT,
R.integer.def_sleep_timeout);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
if (stmt != null) stmt.close();
}
upgradeVersion = 113;
}
在onUpgrade中加入这个操作,是用于在升级系统的时候,再去升级数据库。如果是全刷系统,则不会执行到。
还要在另外一个地方加入:loadGlobalSettings、loadSecureSettings、loadSystemSettings,这几个方法是在DatabaseOpenHelper#onCreate()中调用的,就是首次建立数据库的时候用到。如:
loadIntegerSetting(stmt, Settings.Secure.SLEEP_TIMEOUT,
R.integer.def_sleep_timeout);
也就是会所要修改数据库,代码就要一式两份在两个方法中添加。
在新版本中修改:
只需在SettingsProvider.SettingsRegistry.UpgradeController#onUpgradeLocked()中加入的操作就行,如:
if (currentVersion == 118) {
if (userId == UserHandle.USER_OWNER) {
final SettingsState globalSettings = getGlobalSettingsLocked();
globalSettings.updateSettingLocked(Settings.Global.ZEN_MODE,
Integer.toString(Settings.Global.ZEN_MODE_OFF),
SettingsState.SYSTEM_PACKAGE_NAME);
globalSettings.updateSettingLocked(Settings.Global.MODE_RINGER,
Integer.toString(AudioManager.RINGER_MODE_NORMAL),
SettingsState.SYSTEM_PACKAGE_NAME);
}
currentVersion = 119;
}
/**
* You must perform all necessary mutations to bring the settings
* for this user from the old to the new version. When you add a new
* upgrade step you *must* update SETTINGS_VERSION.
*
* This is an example of moving a setting from secure to global.
*
* // v119: Example settings changes.
* if (currentVersion == 118) {
* if (userId == UserHandle.USER_OWNER) {
* // Remove from the secure settings.
* SettingsState secureSettings = getSecureSettingsLocked(userId);
* String name = "example_setting_to_move";
* String value = secureSettings.getSetting(name);
* secureSettings.deleteSetting(name);
*
* // Add to the global settings.
* SettingsState globalSettings = getGlobalSettingsLocked();
* globalSettings.insertSetting(name, value, SettingsState.SYSTEM_PACKAGE_NAME);
* }
*
* // Update the current version.
* currentVersion = 119;
* }
*/
private int onUpgradeLocked(int userId, int oldVersion, int newVersion)
然后还要修改SettingsProvider.SettingsRegistry.UpgradeController#SETTINGS_VERSION
Settings共有三种分类,分别如下:
- Global:所有的偏好设置对系统的所有用户公开,第三方APP有读没有写的权限;
- System:包含各种各样的用户偏好系统设置;
- Secure:安全性的用户偏好系统设置,第三方APP有读没有写的权限。
修改原因主要是:
- 修改持久化方案是因为写入的速率是400ms:10ms。
- xml异步性能更加优良的
欲知Google修改的原因可参考这篇文章:https://blog.csdn.net/peng_cao/article/details/50594958