Android 效能優化(九)之不可忽視的電量

貌似許亞軍發表於2017-05-04

1、 前言

移動網際網路的大潮到來之後,我們都變身好男人:“用智慧手機的男人都是好男人,因為晚上必須回家充電。”一句笑言,但也可以看得出來目前使用智慧裝置電量方面的問題

而開發者在電量消耗方面也起到了推波助瀾的作用:相比於卡頓、記憶體洩漏等問題,開發者對電量消耗的重視程度極低;

  1. 開發者和QA工作時,會習慣性的連線電腦或者電源隨時充電,電量問題根本暴露不出來;
  2. 開發者和QA的工作重點主要放在業務功能完成度上,類似卡頓、記憶體洩漏等效能問題直到暴露出來才會去解決,更何況不影響開發者和QA的電量消耗。

然而開發者的不關注並不代表使用者的忽視,Android裝置使用者會普遍裝載管家類App,通過這些管家App,使用者可以輕鬆找到那些“電池殺手”應用,然後就是刪除————》差評————》轉向競爭對手應用一條龍。因此對於開發者而言要儘量少用電量,合理使用電池。本節就來一起探索既可以省電,又不影響使用者體驗的方法。

2、 電量測試

Android4.1版本之後在系統增加了battery info模組,記錄一定時間週期內整機及單個App的電量消耗。

2.1 註冊廣播

ACTION_BATTERY_CHANGED

IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(filter,receiver);複製程式碼

然後就可以獲取電池電量、充電狀態、電池狀態等資訊。具體參考BatteryManager
缺點:

  1. 獲取到的是手機整體的耗電量,而不是特定App的耗電量;
  2. 實時性差,精度較低,只能接受被動通知電量餘量以及跳變。

2.2 Battery Historian

最強大、最推薦的工具:Battery Historian是Android5.0之後Google開源的一款用於檢測與電池有關的資訊和事件的工具,從裝置中收集電池資料,然後使用Battery Historian可以視覺化分析相關指標如耗電比例、Wifi、蜂窩資料量、WakeLock喚醒次數。隨著Android6.0更新了Battery Historian 2.0加入引起手機狀態變化的應用。

通過Battery Historian可以方便的看到各耗電模組隨著時間的耗電情況:包含操作型別、執行時間、對應App等;還可以進行篩選特定的App,給出一個總結性的說明,包括:Network Information、 Syncs、WakeLock、Services、Process info、Scheduled Job、Sensor Use等,檢視每一個模組的總結,可以看出來每一項的耗時以及執行次數。當發現異常的時候可以針對性的進行排查。總之:Battery Historian真的很強大。

adb命令匯出電量資訊:

adb shell dumpsys batterystats --reset(Android4.14.3 adb shell dumpsys batteryinfo)
adb bugreport > bugreport.txt(Android7.0以上 adb bugreport bugreport.zip)複製程式碼

安裝Battery Historian後開啟:http: //localhost:9999/, 上傳bugreport.txt檔案開始分析,下圖分析360手機助手為例;

Android 效能優化(九)之不可忽視的電量
11點44分06秒和11點55分10秒發生兩次JobScheduler操作,圖有木有很像TraceView

Android 效能優化(九)之不可忽視的電量
單獨檢視360手機助手,此處顯示WakeLock的使用

可以看出:360手機助手使用WakeLock的場景有:推送、定時任務、利用系統賬號同步、服務等。

悄悄的告訴你:360手機助手相比於一般應用耗電的場景更多哦,當然對於一個超級App,也不能過多要求。

安裝過程可以參考Github:battery-historian。備註:我使用Docker的方式並沒有執行成功,通過Go的方式完成的。

3、 電量優化

Android系統上App的電量消耗主要由cpu、wakelock、資料傳輸(流量和wifi)、wifi執行、gps、other senior組成,而耗電異常也是由於這幾個模組的使用不當。

3.1 CPU時間片優化

當檢測到CPU時間片消耗異常時,需要使用TraceView,獲取程式執行資訊,定位CPU佔用率異常的問題,關於CPU的使用可以參照《Android效能優化(一)之啟動加速35%
一文。

3.2 網路傳輸

Android 效能優化(九)之不可忽視的電量

通常情況下,使用3G行動網路傳輸資料,電量的消耗有三種狀態:

Full power: 能量最高的狀態,行動網路連線被啟用,允許裝置以最大的傳輸速率進行操作。
Low power: 一種中間狀態,對電量的消耗差不多是Full power狀態下的50%。
Standby: 最低的狀態,沒有資料連線需要傳輸,電量消耗最少。

3.2.1 資料壓縮

通過資料壓縮等方式縮減傳輸時間,降低電量消耗,此章節可以參考《Android 效能優化(八)之網路優化》

3.2.2 選擇更快的傳輸方式

雖然3G晶片比Wifi晶片耗電低,但Wifi的速率可以讓資料在較短時間內完成傳輸,從而降低電量消耗。

3.2.3 請求集中傳送

分析和統計之類的非重要操作,可以在合適狀態(電量充足或Wifi狀態)下傳送。參見3.6節JobScheduler。

3.2.4 無網狀態避免網路請求

之前在網路優化的文章裡寫過,網路請求失敗之後的重試機制,但是要注意這個重試是在有網狀態下的重試。否則無網狀態下重試不會請求成功,只會消耗電量。尤其是與AlarmManager或者WakeLock連用的場景下,耗電量會更多。

3.3 GPS

定位是App中常用的功能,但是定位不能千篇一律,不同的場景以及不同型別的App對定位更加需要個性化的區分。

3.3.1 選擇合適的Location Provider

Android系統支援多個Location Provider:

  • GPS_PROVIDER:
    GPS定位,利用GPS晶片通過衛星獲得自己的位置資訊。定位精準度高,一般在10米左右,耗電量大;但是在室內,GPS定位基本沒用。

  • NETWORK_PROVIDER
    網路定位,利用手機基站和WIFI節點的地址來大致定位位置,這種定位方式取決於伺服器,即取決於將基站或WIF節點資訊翻譯成位置資訊的伺服器的能力。

  • PASSIVE_PROVIDER:
    被動定位,就是用現成的,當其他應用使用定位更新了定位資訊,系統會儲存下來,該應用接收到訊息後直接讀取就可以了。比如如果系統中已經安裝了百度地圖,高德地圖(室內可以實現精確定位),你只要使用它們定位過後,再使用這種方法在你的程式肯定是可以拿到比較精確的定位資訊。

使用Criteria,設定合適的模式、功耗、海拔、速度等需求,系統會返回合適的Location Provider。

例如你的App只是需要一個粗略的定位那麼就不需要使用GPS進行定位,既耗費電量,定位的耗時也久。

3.3.2 及時登出定位監聽

在獲取到定位之後或者程式處於後臺時,登出定位監聽,此時監聽GPS感測器相當於執行no-op(無操作指令),使用者不會有感知但是卻耗電。

    public void onPause() {
        super.onPause();
        locationManager.removeListener(locationListener);
    }

    public void onResume(){
        super.onResume();
        locationManager.requestLocationUpdates(locationManager.getBestProvider(criteria, true),6000,100,locationListener);
    }複製程式碼
3.3.3 多模組使用定位儘量複用

多個模組使用定位,儘量複用上一次的結果,而不是都重新走定位的過程,節省電量損耗;例如:在應用啟動的時候獲取一次定位,儲存結果,之後再用到定位的地方都直接去取。

3.4 謹慎使用WakeLock

Android為了節省電量,會在使用者無操作一段時間之後進入休眠狀態。Wake Lock是一種鎖的機制,只要有人拿著這個鎖,系統就無法進入休眠。一些App為了能在後臺持續做事情,就會持有一個WakeLock,那麼手機就不會進入休眠狀態,App要做的事情能做了,但是也更加耗電。

  • App在前臺不要申請WakeLock,此時無需申請,申請的話會計算到應用電量消耗;
  • App在後臺由於業務需要必須要申請WakeLock時使用帶有超時引數的方法,防止由於忘記或者異常情況下沒有釋放;
  • App申請使用WakeLock,任務結束之後及時釋放,讓系統再次進入休眠狀態。
    PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
    PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK| PowerManager.ON_AFTER_RELEASE,TAG);
    wl.acquire(TIMEOUT);// 使用帶有超時引數的acquire方法
    // ... do work...
    wl.release();複製程式碼
    備註:如果只是需要螢幕常亮的話,可以使用FLAG_KEEP_SCREEN_ON,無需考慮釋放WakeLock的問題。

3.5 感測器使用

  • 使用感測器,選擇合適的取樣率,越高的取樣率型別則越費電;

    • SENSOR_DELAY_NOMAL (200000微秒)

    • SENSOR_DELAY_UI (60000微秒)

    • SENSOR_DELAY_GAME (20000微秒)

    • SENSOR_DELAY_FASTEST (0微秒)

  • 在後臺時注意及時登出感測器監聽;

3.6 JobScheduler

使用JobScheduler,一些任務通過JobScheduler來觸發,例如可推遲的網路請求、下載、GPS等,可以在特定場景:連線Wifi、連線電源等場景觸發。既完成了任務,也無需考慮由於一些任務導致的電量消耗。

4、 後記

4.1 電量優化的一般套路

  1. 在設定-電量裡檢視App的耗電情況;
  2. 使用Battery Historian進行分析,這是分析裡最重要的一步;
  3. 針對分析結果,參照第三章節的優化方式進行優化。

4.2 Android系統費電嗎?

一直有一種傳言:Android系統比較費電,然而真相不是這樣,請不要把鍋甩給Android系統:

  • 原生的Android手機其實並不耗電,不安裝App的Android手機放置一週仍然是電量充足,而且對功耗的控制在Android每次版本更新都會有所補強。
  • 耗電的原因在於手機ROM以及安裝的軟體,手機ROM會針對原生的Android做各種各樣的定製(免費贈送各種“親情軟體”,各種系統級應用)。安裝軟體的開發者不考慮電量損耗,以及都希望千方百計佔用系統資源(例如保活、互拉)等。

電量優化可以說是開發者和QA最不關注的一個方面了,但是如果任而由之,變成“電量殺手”不僅僅是傷害使用者的體驗,也是對自己的放縱。效能問題不僅僅在於發現之後的優化更改,更在平時的防微杜漸。

參考:

歡迎關注微信公眾號:定期分享Java、Android乾貨!

Android 效能優化(九)之不可忽視的電量
歡迎關注

相關文章