移動互聯網的大潮到來以後,咱們都變身好男人:「用智能手機的男人都是好男人,由於晚上必須回家充電。」一句笑言,但也能夠看得出來目前使用智能設備電量方面的問題。javascript
而開發者在電量消耗方面也起到了推波助瀾的做用:相比於卡頓、內存泄漏等問題,開發者對電量消耗的重視程度極低;html
然而開發者的不關注並不表明用戶的忽視,Android設備用戶會廣泛裝載管家類App,經過這些管家App,用戶能夠輕鬆找到那些「電池殺手」應用,而後就是刪除————》差評————》轉向競爭對手應用一條龍。所以對於開發者而言要儘可能少用電量,合理使用電池。本節就來一塊兒探索既能夠省電,又不影響用戶體驗的方法。java
Android4.1版本以後在系統增長了battery info模塊,記錄必定時間週期內整機及單個App的電量消耗。android
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(filter,receiver);複製代碼
而後就能夠獲取電池電量、充電狀態、電池狀態等信息。具體參考BatteryManager。
缺點:github
最強大、最推薦的工具:Battery Historian是Android5.0以後Google開源的一款用於檢測與電池有關的信息和事件的工具,從設備中收集電池數據,而後使用Battery Historian能夠可視化分析相關指標如耗電比例、Wifi、蜂窩數據量、WakeLock喚醒次數。隨着Android6.0更新了Battery Historian 2.0加入引發手機狀態變化的應用。shell
經過Battery Historian能夠方便的看到各耗電模塊隨着時間的耗電狀況:包含操做類型、執行時間、對應App等;還能夠進行篩選特定的App,給出一個總結性的說明,包括:Network Information、 Syncs、WakeLock、Services、Process info、Scheduled Job、Sensor Use等,查看每個模塊的總結,能夠看出來每一項的耗時以及執行次數。當發現異常的時候能夠針對性的進行排查。總之:Battery Historian真的很強大。性能優化
adb命令導出電量信息:服務器
adb shell dumpsys batterystats --reset(Android4.1到4.3 adb shell dumpsys batteryinfo)
adb bugreport > bugreport.txt(Android7.0以上 adb bugreport bugreport.zip)複製代碼
安裝Battery Historian後打開:http: //localhost:9999/, 上傳bugreport.txt文件開始分析,下圖分析360手機助手爲例;微信
悄悄的告訴你:360手機助手相比於通常應用耗電的場景更多哦,固然對於一個超級App,也不能過多要求。
安裝過程能夠參考Github:battery-historian。備註:我使用Docker的方式並無執行成功,經過Go的方式完成的。
Android系統上App的電量消耗主要由cpu、wakelock、數據傳輸(流量和wifi)、wifi運行、gps、other senior組成,而耗電異常也是因爲這幾個模塊的使用不當。
當檢測到CPU時間片消耗異常時,須要使用TraceView,獲取進程執行信息,定位CPU佔用率異常的問題,關於CPU的使用能夠參照《Android性能優化(一)之啓動加速35%
》一文。
Full power: 能量最高的狀態,移動網絡鏈接被激活,容許設備以最大的傳輸速率進行操做。
Low power: 一種中間狀態,對電量的消耗差很少是Full power狀態下的50%。
Standby: 最低的狀態,沒有數據鏈接須要傳輸,電量消耗最少。
經過數據壓縮等方式縮減傳輸時間,下降電量消耗,此章節能夠參考《Android 性能優化(八)之網絡優化》。
雖然3G芯片比Wifi芯片耗電低,但Wifi的速率可讓數據在較短期內完成傳輸,從而下降電量消耗。
分析和統計之類的非重要操做,能夠在合適狀態(電量充足或Wifi狀態)下發送。參見3.6節JobScheduler。
以前在網絡優化的文章裏寫過,網絡請求失敗以後的重試機制,可是要注意這個重試是在有網狀態下的重試。不然無網狀態下重試不會請求成功,只會消耗電量。尤爲是與AlarmManager或者WakeLock連用的場景下,耗電量會更多。
定位是App中經常使用的功能,可是定位不能千篇一概,不一樣的場景以及不一樣類型的App對定位更加須要個性化的區分。
Android系統支持多個Location Provider:
GPS_PROVIDER:
GPS定位,利用GPS芯片經過衛星得到本身的位置信息。定位精準度高,通常在10米左右,耗電量大;可是在室內,GPS定位基本沒用。
NETWORK_PROVIDER:
網絡定位,利用手機基站和WIFI節點的地址來大體定位位置,這種定位方式取決於服務器,即取決於將基站或WIF節點信息翻譯成位置信息的服務器的能力。
PASSIVE_PROVIDER:
被動定位,就是用現成的,當其餘應用使用定位更新了定位信息,系統會保存下來,該應用接收到消息後直接讀取就能夠了。好比若是系統中已經安裝了百度地圖,高德地圖(室內能夠實現精肯定位),你只要使用它們定位事後,再使用這種方法在你的程序確定是能夠拿到比較精確的定位信息。
使用Criteria,設置合適的模式、功耗、海拔、速度等需求,系統會返回合適的Location Provider。
例如你的App只是須要一個粗略的定位那麼就不須要使用GPS進行定位,既耗費電量,定位的耗時也久。
在獲取到定位以後或者程序處於後臺時,註銷定位監聽,此時監聽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);
}複製代碼
多個模塊使用定位,儘可能複用上一次的結果,而不是都從新走定位的過程,節省電量損耗;例如:在應用啓動的時候獲取一次定位,保存結果,以後再用到定位的地方都直接去取。
Android爲了節省電量,會在用戶無操做一段時間以後進入休眠狀態。Wake Lock是一種鎖的機制,只要有人拿着這個鎖,系統就沒法進入休眠。一些App爲了能在後臺持續作事情,就會持有一個WakeLock,那麼手機就不會進入休眠狀態,App要作的事情能作了,可是也更加耗電。
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的問題。使用傳感器,選擇合適的採樣率,越高的採樣率類型則越費電;
SENSOR_DELAY_NOMAL (200000微秒)
SENSOR_DELAY_UI (60000微秒)
SENSOR_DELAY_GAME (20000微秒)
SENSOR_DELAY_FASTEST (0微秒)
在後臺時注意及時註銷傳感器監聽;
使用JobScheduler,一些任務經過JobScheduler來觸發,例如可推遲的網絡請求、下載、GPS等,能夠在特定場景:鏈接Wifi、鏈接電源等場景觸發。既完成了任務,也無需考慮因爲一些任務致使的電量消耗。
一直有一種傳言:Android系統比較費電,然而真相不是這樣,請不要把鍋甩給Android系統:
電量優化能夠說是開發者和QA最不關注的一個方面了,可是若是任而由之,變成「電量殺手」不只僅是傷害用戶的體驗,也是對本身的放縱。性能問題不只僅在於發現以後的優化更改,更在平時的防微杜漸。
參考:
歡迎關注微信公衆號:按期分享Java、Android乾貨!