Android電量優化

電量消耗的全過程分析

1.喚醒CPU
耗電情況,例如:打開屏幕,所有要使用CPU/GPU工作的動作都會喚醒屏幕,都會消耗電量。這和應用程序喚醒設備還不一樣。
比如使用叫醒鬧鐘(wake clock)、AlarmManager、JobSchedulerAPI。


使用和喚醒屏幕后

當設備從休眠狀態中,被應用程序假面喚醒時,你會看到在第一次喚醒時,這里有一條電量使用高峰線
值得注意的是當工作完成后,設備會主動進行休眠,這非常重要,在不使用或者很少使用的情況下,長時間保持屏幕喚醒會迅速消耗電池的電量。

2.蜂窩式無線耗電

我出門就經常這樣干,當我發現手機快沒電的時候,
我把蜂窩無線關了,留著緊急情況自己可以主動打電話,這個很有用 可以延長2小時的使用哦

電量使用記錄分析工具

Battery Historian
電量使用記錄分析工具。
通過ADB獲取的數據,通過使用Battery Historian工具分析處理后,得到的html結果文件,用瀏覽器可以直接查看的。
Battery Historian工具是一個獨立的Python開源腳本,可以從gitbub上下載。

數據準備

battery-historian工具需要使用bugreport中的Battery History

  1. 先斷開adb服務,然后開啟adb服務
    adb kill-server 這一步很重要,因為當我們開發時做電量記錄時會打開很多可能造成沖突的東西。為了保險起見我們重啟adb。
    adb devices就會自動連接查找手機。當然也可以adb start-server
  2. 重置電池數據收集
    數據,我們在開始的時候需要通過以下命令來打開電池數據的獲取以及重置:
    adb shell dumpsys batterystats --enable full-wake-history
    adb shell dumpsys batterystats --reset
    執行的效果如下:


    image.png

上面的操作相當于初始化操作,如果不這么做會有一大堆的干擾的數據,看起來會比較痛苦。然后把數據線直接拔掉(防止數據線造成充放電數據干擾),現在做一些測試,手動或者跑一些自動化的case都行。經過一段時間后,我們重新連接手機確認adb連上了,運行下面這條命令來將bugreport的信息保存到txt文檔中,adb bugreport > bugreport.txt。
或者用下面的命令也可以:
adb shell dumpsys batterystats > batterystats.txt
adb shell dumpsys batterystats > com.example.android.sunshine.app > batterystats.txt
加上包名可以限制輸出的數據是我們要檢測的。
但是這個txt的數據可讀性不強。接下來我們就要用到這個battery-historian工具了。

到此我們有兩種方式分析這個文件:(historian-V1之前的版本 和historian-V2最新的版本)

將txt文檔轉化為html文件,命令如下。

python historian.py -a bugreport.txt > battery.html

上面的historian.py腳本是Python寫的,所以需要python環境,然后從github上下載這個腳本。文件在github上面的scripts目錄下面,需要下載到命令行所在的目錄

image.png

上面兩條命令執行成功后,會在目錄下發現兩個文件
bugreport.txt和battery.html,這個時候我們用google瀏覽器打開html文件,可以看到如下信息:


image.png

現在來分析各個指標代表的意義:

橫坐標
image.png

上面的10,20代表的就是秒的意思,它是以一分鐘為周期,到第60秒的時候變為0。橫坐標就是一個時間范圍,咱們的例子中統計的數據是以重置為起點,獲取bugreport內容時刻為終點。我們一共采集了多長時間的數據,圖表下也有信息說明。(經其他人的反饋,這個坐標間隔是會隨著時間的長度發生改變,所以要以你的實際情況為準。這個縮放級別可以調整的,如下圖:)


image.png
縱坐標

1.battery_level

電量,可以看出電量的變化。比如上圖中的數據顯示剛開始電量是100%,然后在第11秒-12秒中間的某個時刻降到了99%。

2.plugged
充電狀態,這一欄顯示是否進行了充電,以及充電的時間范圍。例如上圖反映了我們在第22s插入了數據線,然后一直持續了數據采集結束

3.screen
屏幕是否點亮,這一點可以考慮到睡眠狀態和點亮狀態下電量的使用信息。

4.top
該欄顯示當前時刻哪個app處于最上層,就是當前手機運行的app,用來判斷某個app對手機電量的影響,這樣也能判斷出該app的耗電量信息。該欄記錄了應用在某一個時刻啟動,以及運行的時間,這對我們比對不同應用對性能的影響有很大的幫助。

5.wake_lock
wake_lock該屬性是記錄wake_lock模塊的工作時間。是否有停止的時候等

6.running
界面的狀態,主要判斷是否處于idle的狀態。用來判斷無操作狀態下電量的消耗

7.wake_lock_in
wake_lock有不同的組件,這個地方記錄在某一個時刻,有哪些部件開始工作,以及工作的時間。

8.gps
gps是否開啟

9.phone_in_call
是否進行通話

10.Sync
是否跟后臺同步.
可以把鼠標停在某一項上面。可以看到何時sync同步 啟動的,持續時間Duration多久。
電池容量不會顯示單一行為消耗的具體電量,這里只能顯示使用電池的頻率和時長,你可以看分時段的剩余電量來了解具體消耗了多少電量。


image.png

11.Job
后臺的工作,比如服務service的運行。從下面圖中可以看到qihoo的AppStore和魯大師都在運行后臺服務。


image.png

12.data_conn

數據連接方式的改變,上面的edge是說明采用的gprs的方式連接網絡的。此數據可以看出手機是使用2g,3g,4g還是wifi進行數據交換的。這一欄可以看出不同的連接方式對電量使用的影響。

13.status
電池狀態信息,有充電,放電,未充電,已充滿,未知等不同狀態。
這一欄記錄了電池狀態的改變信息。

14.phone_signal_strength

手機信號狀態的改變。
這一欄記錄手機信號的強弱變化圖,依次來判斷手機信號對電量的影響。

15.health
電池健康狀態的信息,這個信息一定程度上反映了這塊電池使用了多長時間。
這一欄記錄電池狀態在何時發生改變,上面的圖中電池狀態一直處于good狀態。

16.plug
充電方式,usb或者插座,以及顯示連接的時間。
這一欄顯示了不同的充電方式對電量使用的影響。

historian-V2最新的版本的方式:

將生成bugreport.txt文件在 [http://localhost:9999](javascript:goto();) 中上傳文件生成報告(前提在本地或者某服務器上搭好了battery-historian項目環境

電量優化的措施

1.為了省電,有些工作可以放當手機插上電源的時候去做

像這些不需要及時地和用戶交互的操作可以放到后面處理。
比如:360手機助手,當充上電的時候,才會自動清理手機垃圾,自動備份上傳圖片、聯系人等到云端。
通過監控電量狀態來進行電量管理。
我們可以通過下面的代碼來獲取手機的當前充電狀態:

// It is very easy to subscribe to changes to the battery state, but you can get the current
// state by simply passing null in as your receiver.  Nifty, isn't that?
IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = this.registerReceiver(null, filter);
int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean acCharge = (chargePlug == BatteryManager.BATTERY_PLUGGED_AC);
if (acCharge) {
    Log.v(LOG_TAG,“The phone is charging!”);
}

在上面的例子演示了如何立即獲取到手機的充電狀態,得到充電狀態信息之后,我們可以有針對性的對部分代碼做優化。比如我們可以判斷只有當前手機為AC充電狀態時 才去執行一些非常耗電的操作。

2.wake_lock

系統為了節省電量,CPU在沒有任務忙的時候就會自動進入休眠。
有任務需要喚醒CPU高效執行的時候,就會給CPU加wake_lock鎖。
大家經常犯的錯誤,我們很容易去喚醒CPU來干活,但是很容易忘記釋放wake_lock.
解決:powerManager的API
記得添加權限:

<uses-permission android:name="android.permission.INTERNET"></uses-permission>
    <uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
  PowerManager.WakeLock mWakelock = 
  pw.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"mywakelock");
   mWakelock.isHeld()

  mWakelock.acquire();//喚醒CPU
  mWakelock.release();//記得釋放CPU鎖
//判斷網絡連接
   private boolean isNetWorkConnected() {
        ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return (activeNetworkInfo!=null&&activeNetworkInfo.isConnected());
    }

3.另外WiFi連接下,網絡傳輸的電量消耗要比移動網絡少很多,應該盡量減少移動網絡下的數據傳輸,多在WiFi環境下傳輸數據。

4Job Scheduler

集中處理任務

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容