App優化之電池省著用

star87826 8年前發布 | 8K 次閱讀 安卓開發 Android開發 移動開發

引言

電量使用優化, 基本上是我們最不怎么關注的一項優化. 可能很多公司連QA/Tester也不會關注測試App電量的使用. 一般來說開發和測試的測試設備也一直是連著USB處于充電狀態的, 感官上也體會不到電量的損耗.

然而, 對于用戶來說, 實際上App的電量損耗也是用戶體驗的一個方面. 特別是當今人們對移動設備的依賴度越來越高, 電量也是用戶特別關注的.

今天我們就來聊聊Android App的電量優化.

1, 分析電量的使用情況

老套路, 上來還是先介紹下我們使用什么工具來做電量分析.

1.1 Batterystats & bugreport

Android 5.0及以上的設備, 允許我們通過adb命令dump出電量使用統計信息.

1, 因為電量統計數據是持續的, 會非常大, 統計我們的待測試App之前先reset下, 連上設備, 命令行執行:

$ adb shell dumpsys batterystats --reset
Battery stats reset.

2, 斷開測試設備, 操作我們的待測試App.

3, 重新連接設備, 使用adb命令導出相關統計數據:

// 此命令持續記錄輸出, 想要停止記錄時按Ctrl+C退出.
$ adb bugreport > bugreport.txt

導出的統計數據存儲到bugreport.txt, 此時我們可以借助如下工具來圖形化展示電池的消耗情況.

注意, 官方SDK文檔 導出文件方式為:

adb shell dumpsys batterystats > batterystats.txt

使用python historian.py batterystats.txt > batterystats.html查看數據

是battery-historian老版本的使用方式. 目前Battery Historian已更新2.0版本, 推薦使用bugreport方式導出數據分析, 可以看到更多信息.

1.2 Battery Historian

Google提供了一個開源的電池歷史數據分析工具 -- Battery Historian .

1.2.1 安裝

按照 Battery Historian 在github上的readme, 一步步安裝即可.

需要注意的是, Battery Historian是Go語言的, 安裝Go的時候需要配置其bin的環境變量.

Python環境需要是2.7的(3.x不行), 建議使用pyenv管理本地的python環境.

另外, 因為Battery Historian是一個網頁版工具, 涉及一些JS引用, 有時需國內或許不能訪問.

安裝完成后, 執行:

cd $GOPATH/src/github.com/google/battery-historian
go run cmd/battery-historian/battery-historian.go [--port <default:9999>]

程序運行在 http://localhost:9999 , 如下:

battery historian running web

1.2.2 界面

導入我們在第一步通過adb bugreport生成的bugreport.txt文件:

battery historian

2, 主要的耗電因素

battery usage

從手機的電池詳情統計可以簡單看出, 手機中最耗電的模塊肯定是屏幕了, 接著就是網絡相關, 另外可能的耗電大戶還有GPS芯片, Camera等.

對于一個App, 對應因素主要有:

2.1 網絡請求

我們可能會有發現:

  • 測試用的手機充滿電放了一個十一假期還有電, 是因為測試手機沒有上SIM卡.
  • 飛行模式下的手機滅屏下, 可能可以放一個月都還有電.

這是因為:

  • 手機的通過內置的射頻模塊和基站幾乎, 從而鏈接上網的, 而這個射頻模塊(radio)是非常耗電的.
  • 為了控制這個射頻模塊的耗電, 硬件驅動及Android RIL層做了很多處理. 例如可以單獨關閉radio(飛行模式), 間歇性假休眠radio(有數據發生時才上電, 保持一個頻率的與基站交互)等等.

現如今App都是移動互聯網App, 不可避免的會有大量的網絡請求, 會導致radio一直處于活躍狀態, 從而耗電量增加.

2.2 WakeLock

Android系統本身為了優化電量的使用, 會在沒有操作時進入休眠狀態, 來節省電量. 當然, 為了便于開發(很多應用不可避免的希望在滅屏后還能運行一些事兒, 或是要保持屏幕一直亮著--比如播放視頻), Android提供了一個PowerManager.WakeLock的東西.

我們可以用WakeLock來保持CPU運行, 或是防止屏幕變暗/關閉, 讓手機可以在用戶不操作時依然可以做一些事兒. 然而, 獲取WakeLock很容易, 釋放不好就會成為難題, 消耗電量.

例如我們獲取了一個WakeLock來保持CPU運轉, 做一個復雜運算并將數據上傳到后臺服務器, 然后釋放該WakeLock. 然而這個過程可能并不像我們想象的那么快, 可能因為比如服務器掛掉, 計算出了異常等等WakeLock沒有釋放. 問題就來了, CPU會一直得不到休眠, 而大大增加耗電.

另外, WakeLock還有android:keepScreenOn屬性, 還可以讓屏幕常量, 這可是耗電大戶.

2.3 GPS

應用中經常會用到定位服務, Android提供了Network定位和GPS定位. 相對來說, GPS會精確得多, 對于一些諸如跑步, 導航類的應用基本會使用GPS定位. 然而, GPS定位也會消耗大量的電量.

3, 盡可能減少App的電量消耗的建議

了解了上述的主要的耗電因素, 還有一些程序的耗電問題, 我們通過Battery Historian也可以分析.

針對這些耗電情況, 給出如下優化建議:

3.1 優化網絡請求

這個會在網絡優化那篇中細聊, 在此略過.

3.2 謹慎使用WakeLock

  1. WakeLock獲取釋放成對出現.
  2. 使用超時WakeLock, 以防出異常導致沒有釋放.
// Acquires the wake lock with a timeout.
acquire(long timeout)

3.3 監聽手機充電狀態

BatteryManager會發送一個包含充電狀態的持續廣播, 我們可以通過此廣播獲取充電狀態和電量詳情:

IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = context.registerReceiver(null, ifilter);

注意: 因為這是一個持續廣播, 我們無需寫receiver, 可以直接通過intent獲取相關數據.

例如, 如果設備正在充電:

// Are we charging / charged?
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
                     status == BatteryManager.BATTERY_STATUS_FULL;

// How are we charging?
int chargePlug = battery.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean usbCharge = chargePlug == BATTERY_PLUGGED_USB;
boolean acCharge = chargePlug == BATTERY_PLUGGED_AC;

另外我們也可以監聽充電狀態的變化, 只要設備連接或斷開電源, BatteryManager就會廣播相應的操作, 我們可以注冊receiver來監聽:

<receiver android:name=".PowerConnectionReceiver">
  <intent-filter>
    <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
    <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
  </intent-filter>
</receiver>

監聽電池狀態, 可以讓我們將一些操作放在充電或是電量足夠的情況下進行, 以提升用戶體驗. 例如用戶數據同步, Log上傳等.

3.4 Doze and App Standby

Android 6.0提供了兩個用來節省電量的技術Doze和App Standby.

  • Doze

    瞌睡. 如果設備閑置了一段較長時間, Doze技術將通過延遲后臺網絡活動, CPU運行等來減少電量損耗.

  • App Standy

    應用待機. 不是最近得到過用戶"寵幸"的App, App Standy將延緩這個應用的后臺網絡活動.

因為所有Android 6.0及以上的設備上, Doze and App Standby都會運行. 可能會影響你的App的運行, 具體的適配請參考 官方文檔 .

3.5 關于定位

  • 定位中使用GPS, 請記得及時關閉

// Remove the listener you previously added
locationManager.removeUpdates(locationListener);
  • 減少更新頻率

  • 根據實際情況選擇GPS或網絡或兩者. 只使用一個會降低電量損耗.

 

來自:http://www.jianshu.com/p/c55ef05c0047

 

 本文由用戶 star87826 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!