SettingsProvider存储键值对的地方和新老版本的区别和就兼容方式

旧版是使用数据库管理,数据库的名字是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共有三种分类,分别如下:

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

修改原因主要是:

  1. 修改持久化方案是因为写入的速率是400ms:10ms。
  2. xml异步性能更加优良的

欲知Google修改的原因可参考这篇文章:https://blog.csdn.net/peng_cao/article/details/50594958

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值