admin管理员组文章数量:1567739
文章目录
- 反编译定制安卓默认使用24H格式显示时间
- 警告
- AOSP
- 分析流程:
- 1. 首先,分析状态栏时间是如何显示的,格式是如何设置的,是由谁负责初始化的
- 2. 反编译Settings验证AOSP梳理出来的过程
- 3. 反编译SettingProvider完成此前分析应该添加的修改
- 4. 回编译SettingProvider
- 结语
反编译定制安卓默认使用24H格式显示时间
该文编写的目的一是作为个人的学习笔记,二是希望对各位技术同事有所启发,整个过程也可加深对部分系统流程的理解。以前个人笔记都是比较简单的,第一次写成这种可分享的形式,若有不合理之处敬请谅解。
这个过程中,会涉及到简单的反编译知识与需要一点点阅读代码的能力,刚开始接触可能会有些困难,但成功的喜悦会让你觉得是值得的。
警告
反编译定制属于高风险的方法,并不一定适用于任何地方,若不清楚被修改目标的流程,则该过程有可能带来未知的风险!该方法不应该被当做优先使用的方法,若已有现成的系统属性请首先依照系统属性修改!!
AOSP
下面会提到安卓开放源代码计划(ASOP, Android Open Source Project)
,因为反编译smali
代码较难读懂,但正因为安卓本身开源,所以可以查看开源项目的源码来辅助跟踪这一个过程(请千万不要将AOSP
的内容就认为与我们主板的内容完全一致,定制化程度是不一样的)
若你掌握科学上网的方法,AOSP
可以从 https://android.googlesource/ 处在线查看源码,但请注意查看git仓库时查看对应系统版本的TAG。
若没有科学上网那么你就需要安装一个ubuntu
系统来利用repo
在 https://mirrors.tuna.tsinghua.edu/help/AOSP/取得所有的代码,但这一过程有个好处,你可以编译自己的安卓系统!
分析流程:
1. 首先,分析状态栏时间是如何显示的,格式是如何设置的,是由谁负责初始化的
可能会有点奇怪,为什么要关注状态栏显示,但之所以要知道状态栏是如何显示的,是因为我们需要知道在没有涉及设置的情况下,其默认值来源是什么,即一开机的状态,这也是修改的目的。
顶部状态栏是被SystemUI
所控制的;另外,24小时制是在系统设置Settings
中更改的;那么,先看一下保存流程,在这里,我们需要利用AOSP
源码来辅助跟踪这一流程。
在执行这一步之前,解包要修改的目标固件可以很简单的获得整个System分区,下面所有路径都是指对应的目录,不再赘述。
-
先于
AOSP
查看这一流程//首先找到Settings看一下正常情况下是如何保存修改24小时显示的,至于如何知道这个是设置时间相关的,简单粗暴的看名字猜测往往有效,实在不行还可以网上搜索一下 //Home/Garfield/Android/source/packages/apps/Settings/src/com/android/settings/DateTimeSettings.java public boolean onPreferenceTreeClick(Preference preference) { if (preference == mDatePref) { //...... } else if (preference == mTimePref) { //...... } else if (preference == mTime24Pref) { //这里可以看出来,通过set24Hour方法来设置这一过程,继续跟踪 final boolean is24Hour = ((SwitchPreference)mTime24Pref).isChecked(); set24Hour(is24Hour); //...... } return super.onPreferenceTreeClick(preference); } //继续跟踪发现设置保存的真正方法 private void set24Hour(boolean is24Hour) { //首先这一个java类里,能看到HOURS_24与HOURS_12是两个常量,分别是字符串"24"与"12" //然后有一个Settings.System.putString,搜索便知道这是安卓用于写系统属性的方法。 Settings.System.putString(getContentResolver(), Settings.System.TIME_12_24, is24Hour? HOURS_24 : HOURS_12); } //然后在安卓开发者网站搜索Settings.System.TIME_12_24相关资料,就可以找到他的描述:https://developer.android/reference/android/provider/Settings.System#TIME_12_24 //该值本质上也是一个常量,是字符串"time_12_24",即写系统属性"time_12_24"的值为"12"或者"24"
经过这一流程,就可以发现,真正保存显示时间格式的是系统属性
"time_12_24"
,那么只要我们找到办法让其默认值是"24"
理论上就可以实现了。 -
了解安卓是怎么初始化默认系统属性的
通过简单的搜索就知道,安卓系统的第一次开机各种设置的默认值基本上都来自
frameworks/base/packages/SettingsProvider/res/values/defaults.xml
,即SettingsProvider
来初始化,那么下一步就是找到它是如何提供设置的默认值的。 根据搜索可知,该过程在
DatabaseHelper.java
完成,那么直接看这部分的源码//Settings/DatabaseHelper.java 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); } } //往下跟踪loadSystemSettings()这个流程 private void loadSystemSettings(SQLiteDatabase db) { SQLiteStatement stmt = null; try { //....... //这里发现了Settings.System.SCREEN_BRIGHTNESS这样类似命名的参数,和之前发现的Settings.System.TIME_12_24十分类似,那么我们就应该找对了地方 //但是根据名字判断,这里加载的是整数、布尔值等,且资源文件应用的是R.bool.def_开头命名的内容 //那么def_开头就应该是对应属性的默认值 loadIntegerSetting(stmt, Settings.System.SCREEN_BRIGHTNESS, R.integer.def_screen_brightness); loadBooleanSetting(stmt, Settings.System.SCREEN_BRIGHTNESS_MODE, R.bool.def_screen_brightness_automatic_mode); loadDefaultAnimationSettings(stmt); 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(); } }
上面提到
def_
开头的参数有很多,而R.
开头的是应用的资源,安卓应用资源文件都单独都位于/res/
目录下,那么我们就可以进来看看<!--查看/res/values/defaults.xml文件可以发现很多这种键值对,有bool,有interger,有string,这正对应上方不同的load方法--> <!--上面提到,12还是24小时制保存的是"time_12_24"这条属性,但是搜索没有发现,即默认是没有的--> <resources> <bool name="def_dim_screen">true</bool> <integer name="def_screen_off_timeout">60000</integer> <integer name="def_sleep_timeout">-1</integer> <bool name="def_airplane_mode_on">false</bool> <bool name="def_theater_mode_on">false</bool> <!-- Comma-separated list of bluetooth, wifi, and cell. --> <string name="def_airplane_mode_radios" translatable="false">cell,bluetooth,wifi,nfc,wimax</string> <string name="airplane_mode_toggleable_radios" translatable="false">bluetooth,wifi,nfc</string> <string name="def_bluetooth_disabled_profiles" translatable="false">0</string>
综上所述,我们需要让
SettingProvider
的default.xml
加入<string name="def_time_12_24">24</string>
,并且在loadSettings
的某一部分加入loadStringSetting(stmt, Settings.System.TIME_12_24, R.string.def_time_12_24)
让其加载加入的属性。 后面完成后我也好奇在
SettingProvider
没有写入初始参数时是由谁提供默认值的,后面发掘了一下可能是framework
层提供,即/system/framework.jar
文件,其具体流程待各位挖掘啦。
2. 反编译Settings验证AOSP梳理出来的过程
apktool if /System/framework/framework-res.apk
#第一步对于反编译任何与系统高度相关的apk至关重要,若不先将框架安装(if命令),则后续会无法回编译。另外,-p可以指定安装的路径,这样可以同时反编译多个不同的系统版本不印发冲突
apktool d /System/priv-app/Settings/Settings.apk
apktool d /System/priv-app/SettingProvider/SettingProvider.apk
#完成后反编译目标所在目录会多出一个同名文件夹(不包括后缀)
下面查看反编译出来的Settings
,查看其流程是否和此前提到的源码类似。
//System\priv-app\Settings\Settings\smali\com\android\settings
.method private set24Hour(Z)V //找到set24Hour这个方法
.locals 3
.param p1, "is24Hour" # Z
.prologue
.line 311
invoke-virtual {p0}, Lcom/android/settings/DateTimeSettings;->getContentResolver()Landroid/content/ContentResolver;
move-result-object v1
.line 312
const-string/jumbo v2, "time_12_24" //系统属性名,在源码里是常量,但背后本质上也是该字符串
.line 313
if-eqz p1, :cond_0
const-string/jumbo v0, "24"
.line 311
:goto_0
//关键的地方,可以看到与AOSP源码的流程是可以互相印证的,即我们板卡的settings也是写该参数
invoke-static {v1, v2, v0}, Landroid/provider/Settings$System;->putString(Landroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;)Z
.line 310
return-void
.line 313
:cond_0
const-string/jumbo v0, "12"
goto :goto_0
.end method
那么我们到这里就验证了Settings
保存该属性的方法与AOSP
是一样的,那么理论上我们也可以通过修改SettingProvider
来实现初始化为24小时格式。
3. 反编译SettingProvider完成此前分析应该添加的修改
首先要在资源文件中添加这个属性,但这里有个地方要注意,资源文件在编译后不同属性的资源会分开存放,另外会有资源表,因此对应的两者都要添加:
<!--SettingProvider/res/values/string.xml中加入下面行-->
<string name="def_time_12_24">24</string>
<!--SettingProvider/res/values/public.xml中string部分最后面加入下面行,注意id不可重复,且应按合理规则添加-->
<public type="string" name="def_time_12_24" id="0x7f060016" />
这样一来,就完成了约等于源码里添加到default.xml
这一步,接下来是修改DatabaseHelper.java
//smali/com/android/providers/seetings/DatabaseHelper.smali
//找到loadSystemSettings这一方法,并找到里面加载起来string类型的地方方便参照修改
.method private loadSystemSettings(Landroid/database/sqlite/SQLiteDatabase;)V
//....
.line 2407
const-string/jumbo v1, "screenshot_location"
const v2, 0x7f060014
invoke-direct {p0, v0, v1, v2}, Lcom/android/providers/settings/DatabaseHelper;->loadStringSetting(Landroid/database/sqlite/SQLiteStatement;Ljava/lang/String;I)V
//仿照上面的smali写一个类似的过程
const-string/jumbo v1, "time_12_24" //系统属性名"time_12_24"
const v2, 0x7f060016 //资源表中对应的id号
invoke-direct {p0, v0, v1, v2}, Lcom/android/providers/settings/DatabaseHelper;->loadStringSetting(Landroid/database/sqlite/SQLiteStatement;Ljava/lang/String;I)
//...
这样一来,理论上就应该完成了修改,最后就是回编译并测试了。
4. 回编译SettingProvider
apktool b /System/priv-app/SettingProvider/SettingProvider.apk
#完成后回编译后,反编译所在目录会多出dist,里面存放回编译的apk,对其应用系统签名即可
将其替换同名文件后,恢复出厂设置即可观察到效果,或将其用固件修改工具做进固件中。
结语
至此,这一流程就走完了,希望能给大家带来一点启发,谢谢阅读。
apktool b /System/priv-app/SettingProvider/SettingProvider.apk
#完成后回编译后,反编译所在目录会多出dist,里面存放回编译的apk,对其应用系统签名即可
将其替换同名文件后,恢复出厂设置即可观察到效果,或将其用固件修改工具做进固件中。
## 结语
至此,这一流程就走完了,希望能给大家带来一点启发,谢谢阅读。
版权声明:本文标题:反编译定制安卓默认使用24H格式显示时间 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/dongtai/1725652052a1034589.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论