最近在项目中遇到要设置默认值的。就拿它举个例子吧。
假设我们要把Settings->Display->Daydream->menu->When to daydream-> 弹出菜单的默认值从While docked改为While charging.
OK, let's begin.
首先找到DreamSettings类的createWhenToDreamDialog方法。发现默认选定值来自于initialSelection这个变量,它作为下标,而它的取值是通过
int initialSelection = mBackend.isActivatedOnDock() && mBackend.isActivatedOnSleep() ? 2 : mBackend.isActivatedOnDock() ? 0 : mBackend.isActivatedOnSleep() ? 1 : -1;
这样判断的。
继续追踪到DreamBackend类的
isActivatedOnDock
方法,记下key值
SCREENSAVER_ACTIVATE_ON_DOCK
然后走到getBoolean方法,由
return Settings.Secure.getInt(mContext.getContentResolver(), key, def ? 1 : 0) == 1;
发现是从数据库取值。于是我们搜索之前记下的key值,迅速找到DatabaseHelper类,从
loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault);
发现默认值是从一个布尔值中得到的,于是我们搜config_dreamsActivatedOnDockByDefault找到一个frameworks/base/core/res...底下的一个config.xml文件。
其中有这样两项
false true
OK!这正是我们要找的地方。我把上面的false和true交换掉。mmm编译frameworks/base/core/res/生成frameworks-res.apk.把它push进手机重启。验证发现并没有效果。
那么我们的问题来了!
于是我查找数据库,用sqlite3工具在 data/data/com.android.providers.settings/databases/settings.db中的secure表里面找到两项(这种查找数据库的方法很重要!!!)
17|screensaver_activate_on_dock|1 18|screensaver_activate_on_sleep|0
他们的值并没有变过来。
然后,我在单编frameworks/base/core/res/之后进行打包,如下
mmm frameworks/base/core/res/ snod
生成system.img镜像,全擦手机并刷入。启动以后发现数据库中的值成功的变成了
17|screensaver_activate_on_dock|0 18|screensaver_activate_on_sleep|1
我进入Setting目录查看,也确实默认勾选了While charging.问题成功解决!!
那么我们可以总结以下原因:
手机在烧写版本之后第一次开机,会把形如config.xml/defaults.xml等我们的默认值一次性写到数据库里。然后像Settings这些应用再从这些数据库中取值。我们
所以以后要是修改了这些默认值,验证的时候需要通过单编打包的方式验证。简单的单编这个模块并push并不能影响到数据库,所以没用。
今天是帮一个同事走读代码的时候发现在布局上简单的删去一个item是没用的,需要深追下去,找到item对应的功能的默认值。引起了我的兴趣,然后,用我的方法成功解决问题并成功验证。也让我搞通了android数据库与默认值这块。收获颇丰,大快人心!