Android 5.1 Ubuntu14.04 SourceInsigh
電量已滿,插着USB頭,觀察Settings - Battery,電量為100%,狀態為full,但仍有充電圖標rust
之前有讀過關於StatusBar的代碼。這次直接用SourceInsight找到 StatusBarHeaderView.java
里面關於電池的方法有
@Override public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0); mBatteryLevel.setText(percentage); }
似乎沒什么幫助,我們找的是圖標,不是數字
猜測一下,電池狀態變化的時候,肯定會發出通知,十有八九是用廣播發出的
用SourceInsight直接搜索battery,搜到關於Battery的一些文件
/** BatteryManager.java (base/core/java/android/os)*/ // values for "status" field in the ACTION_BATTERY_CHANGED Intent public static final int BATTERY_STATUS_FULL = 5; // 定義了狀態值
在 BatteryService.java 中,可以發現一個獲取icon的方法
/** BatteryService.java (base/services/core/java/com/android/server) */ private int getIconLocked(int level) { if (mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_CHARGING) { return com.android.internal.R.drawable.stat_sys_battery_charge; ......
根據stat_sys_battery_charge,可以找到 Stat_sys_battery_charge.xml (framework/base/core/res/res/drawable)
find一下就能值得圖標存放在frameworks/base/core/res/res/drawable-mdpi/ 等目錄下
修改 BatteryService.java getIconLocked中的判斷條件或返回值
找到了很多資源文件,修改一下返回值。比如:
if (mBatteryProps.batteryStatus == BatteryManager.BATTERY_STATUS_CHARGING) { return com.android.internal.R.drawable.stat_sys_battery; // 顯示未充電的圖標
編譯后push進去,發現沒效果
不成功,為何?發出的廣播沒有人接收?icon被塞進了 BatteryManager.EXTRA_ICON_SMALL
int icon = getIconLocked(mBatteryProps.batteryLevel); intent.putExtra(BatteryManager.EXTRA_ICON_SMALL, icon);
grep一下EXTRA_ICON_SMALL,發現沒地方接收。發出的廣播沒人收,那電池圖標rust是怎么放上去的?
換一個尋找思路
我知道狀態欄屬於SystemUI,觀察SystemUI的文件目錄;打開 AndroidManifest.xml 看到
<service android:name="SystemUIService" android:exported="true"/>
接下來找到並打開 SystemUIService.java ;在onCreate()中提到了SystemUIApplication
SystemUIApplication.java 里啟動了一系列的服務,其中就包括
com.android.systemui.statusbar.SystemBars.class
打開 SystemBars.java frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar
可以看到BaseStatusBar
mStatusBar = (BaseStatusBar) cls.newInstance();
順藤摸瓜
在 BaseStatusBar.java 中搜索R.layout,卻只找到notification相關的
BaseStatusBar是基礎狀態欄的意思,會不會有別的類來繼承它?grep一下發現
TvStatusBar和PhoneStatusBar繼承自BaseStatusBar
在 PhoneStatusBar.java 中搜索“R.layout.”,得到幾個layout:
R.layout.super_status_bar
R.layout.heads_up
R.layout.navigation_bar
R.layout.status_bar_notification_keyguard_overflow 等等
mStatusBarWindow = (StatusBarWindowView) View.inflate(context, R.layout.super_status_bar, null);
重點關注一下super_status_bar,里面裝載了很多子布局,比如status_bar
打開 status_bar.xml ,找到system_icon_area;它include了system_icons
打開 system_icons.xml 我們發現,有一個自定義控件com.android.systemui.BatteryMeterView
現在知道電池圖標是畫出來的了
//BatteryMeterView.java (framework/base/packages/systemui/src/com/android/systemui) public class BatteryMeterView extends View implements DemoMode, BatteryController.BatteryStateChangeCallback
實現了BatteryController.BatteryStateChangeCallback接口,電池狀態改變,電池圖標會更新
private class BatteryTracker extends BroadcastReceiver {
接收廣播,取出電池各項信息;得到電池信息要更新圖標
觀察draw方法,里面有用tracker來進行判斷
if (tracker.plugged) { // define the bolt shape
如果插上了USB頭,就畫出閃電標志;我們的要求是充電狀態下才能有閃電標志
那么多加入一個判斷,當充滿電的時候,不要畫閃電標志
if (tracker.plugged && (batteryStatus != BatteryManager.BATTERY_STATUS_FULL)) { // define the bolt shape
batteryStatus是rust自行定義的int變量,從BatteryTracker中取出電池status,再用來判斷
重新編譯燒寫,發現充滿電后,無充電標志
原來充電的標志rust是畫上去的。