Android 優(yōu)化——電量優(yōu)化

Android 優(yōu)化目錄


Android 5.0 后用 Battery Historian 工具分析電量拗窃。

耗電因素

  1. 移動網(wǎng)絡(luò)請求

    手機通過內(nèi)置的射頻模塊和基站聯(lián)系,從而鏈接上網(wǎng)的耻矮,而這個射頻模塊(radio)是非常耗電的,為了控制這個射頻模塊的耗電,硬件驅(qū)動及 Android RIL 層做了很多處理高蜂。例如可以單獨關(guān)閉 radio(飛行模式)俯萌,間歇性假休眠 radio(有數(shù)據(jù)發(fā)生時才上電果录,保持一個頻率的與基站交互)等等。如今的 App 都是移動互聯(lián)網(wǎng) App咐熙,不可避免的會有大量的網(wǎng)絡(luò)請求弱恒,會導致 radio 一直處于活躍狀態(tài),從而耗電量增加棋恼。

    使用移動網(wǎng)絡(luò)傳輸數(shù)據(jù)返弹,電量的消耗有以下 3 種狀態(tài):

    • Full power:高功率狀態(tài),移動網(wǎng)絡(luò)連接被激活爪飘,允許設(shè)備以最大 的傳輸速率進行操作义起。
    • Low power:低功耗狀態(tài),對電量的消耗差不多是 Full power 狀態(tài)下的 50%师崎。
    • Standby:空閑態(tài)默终,沒有數(shù)據(jù)連接需要傳輸,耗電最少。

    從低功率到高功率大約 1.5s齐蔽,從空閑態(tài)到高功率大約 2s两疚,秒。在應(yīng)用中每創(chuàng)建一個新的網(wǎng)絡(luò)連接含滴,網(wǎng)絡(luò)(射頻)模塊都會轉(zhuǎn)換到高功率狀態(tài)(Radio Full Power)诱渤,在數(shù)據(jù)傳輸完后再轉(zhuǎn)回低功耗狀態(tài)(Radio Low Power),轉(zhuǎn)換的過程需要 5 秒谈况,這 5 秒的耗電量保持在高功率狀態(tài)勺美,最后再轉(zhuǎn)換空閑態(tài)需要 12 秒。因此碑韵,對于一個典型的移動網(wǎng)絡(luò)設(shè)備赡茸,每個數(shù)據(jù)傳輸都會導致網(wǎng)絡(luò)模塊消耗 20 秒的電量。

  2. WakeLock

    Android 系統(tǒng)本身為了優(yōu)化電量的使用祝闻,會在沒有操作時進入休眠狀態(tài)坛掠,來節(jié)省電量。當然治筒,為了便于開發(fā)(很多應(yīng)用不可避免的希望在滅屏后還能運行一些事兒屉栓,或是要保持屏幕一直亮著--比如播放視頻),Android 提供了一個 PowerManager.WakeLock 的東西.

    我們可以用 WakeLock 來保持 CPU 運行耸袜,或是防止屏幕變暗/關(guān)閉友多,讓手機可以在用戶不操作時依然可以做一些事兒。然而堤框,獲取 WakeLock 很容易域滥,釋放不好就會成為難題,消耗電量蜈抓。例如獲取了一個 WakeLock 來保持 CPU 運轉(zhuǎn)启绰,做一個復雜運算并將數(shù)據(jù)上傳到后臺服務(wù)器,然后釋放該 WakeLock沟使。然而這個過程可能并不像我們想象的那么快委可,可能因為比如服務(wù)器掛掉,計算出了異常等等導致 WakeLock 沒有釋放腊嗡,CPU 會一直得不到休眠着倾,而大大增加耗電。

    另外燕少,WakeLock 還有 android:keepScreenOn 屬性卡者,還可以讓屏幕常量,這也是耗電大戶客们。

    private void acquireWakeLock(Context ctx) { 
        if (null == mWakeLock) { 
            PowerManager pm = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE); 
            mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE, "TestLocknService"); 
            if (null != mWakeLock) { 
                mWakeLock. acquire(); 
            } 
        } 
    } 
    
    • PARTIAL_WAKE_LOCK:保持 CPU 正常運轉(zhuǎn)崇决,屏幕和鍵盤燈有可能 會關(guān)閉材诽。
    • SCREEN_DIM_WAKE_LOCK:保持 CPU 運轉(zhuǎn),允許保持屏幕顯示恒傻,但有可能變暗岳守,允許關(guān)閉鍵盤燈。
    • SCREEN_BRIGHT_WAKE_LOCK:保持 CPU 運轉(zhuǎn)碌冶,允許保持屏幕高亮顯示,允許關(guān)閉鍵盤燈涝缝。
    • FULL_WAKE_LOCK:保持 CPU 運轉(zhuǎn)扑庞,保持屏幕高亮顯示,鍵盤燈也保持亮度拒逮。
    • ACQUIRE_CAUSES_ WAKEUP:強制使屏幕亮起罐氨,這種鎖主要用于一些必須通知用戶的操作。
    • ON_AFTER_RELEASE:當鎖被釋放時滩援,保持屏幕亮起一段時間栅隐。

    需要注冊權(quán)限

    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <uses-permission android:name="android.permission.DEVICE_POWER"/>
    
  3. GPS

    應(yīng)用中經(jīng)常會用到定位服務(wù),Android 提供了 Network 定位和 GPS 定位玩徊。相對來說租悄,GPS 會精確得多,對于一些諸如跑步恩袱,導航類的應(yīng)用基本會使用 GPS 定位泣棋。然而,GPS 定位也會消耗大量的電量畔塔。

  4. AlarmManager

    間隔不能太短潭辈。

優(yōu)化建議

  1. 優(yōu)化網(wǎng)絡(luò)請求

    在蜂窩移動網(wǎng)絡(luò)下,最好做到批量執(zhí)行網(wǎng)絡(luò)請求澈吨,盡量避免頻繁的間隔網(wǎng)絡(luò)請求把敢,盡量多地保持在 Radio Standby 狀態(tài)。

    盡量在 Wi-Fi 環(huán)境下使用數(shù)據(jù)傳輸谅辣。

  2. 謹慎使用 WakeLock

    WakeLock 獲取釋放成對出現(xiàn)(調(diào)用 release)修赞,使用超時 WakeLock,以防出異常導致沒有釋放桑阶。

    WakeLock 有一個接口 setReferenceCounted榔组,用來設(shè)置 WakeLock 的計數(shù)機制,true 為計數(shù)联逻,false 為不計數(shù)搓扯,默認是 true。所謂計數(shù)即每一個 acquire 必須對應(yīng)一個 release包归;不計數(shù)則是無論有多少個 acquire锨推,一個 release 就可以釋放。雖然官方說默認 是計數(shù)的,但有的第三方 ROM 做了修改换可,使默認是不計數(shù)的椎椰。

    主動設(shè)置 wakeLock.setReferenceCounted(false)

  3. 監(jiān)聽手機充電狀態(tài)

    BatteryManager 會發(fā)送一個包含充電狀態(tài)的持續(xù)廣播沾鳄,我們可以通過此廣播獲取充電狀態(tài)和電量詳情慨飘。因為這是一個持續(xù)廣播,無需寫 Receiver译荞,可以直接通過 intent 獲取相關(guān)數(shù)據(jù)瓤的。

    IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
    Intent batteryStatus = context.registerReceiver(null,ifilter);
    // 設(shè)備正在充電
    int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS吞歼,-1);
    boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
                     status == BatteryManager.BATTERY_STATUS_FULL;
    // 也可以監(jiān)聽充電狀態(tài)的變化圈膏,只要設(shè)備連接或斷開電源,BatteryManager 就會廣播相應(yīng)的操作
    int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED篙骡,-1);
    boolean usbCharge = chargePlug == BATTERY_PLUGGED_USB;
    boolean acCharge = chargePlug == BATTERY_PLUGGED_AC;
    

    另外頁可以注冊 Receiver來監(jiān)聽

    <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>
    
  4. Doze and App Standby

    Android 6.0 提供了兩個用來節(jié)省電量的技術(shù) Doze 和 App Standby稽坤。

    • Doze 瞌睡。如果設(shè)備閑置了一段較長時間糯俗,Doze 技術(shù)將通過延遲后臺網(wǎng)絡(luò)活動尿褪,CPU 運行等來減少電量損耗。
    • App Standy 應(yīng)用待機得湘。不是最近得到過用戶使用的 App茫多,App Standy 將延緩這個應(yīng)用的后臺網(wǎng)絡(luò)活動。

    所有 Android 6.0 及以上的設(shè)備上忽刽,Doze and App Standby 都會運行天揖。可能會影響 App 的運行跪帝,可以根據(jù)官方文檔適配今膊。

    可以在代碼中調(diào)起電量優(yōu)化的設(shè)計頁面,讓用戶選擇是否將應(yīng)用加入白名單伞剑,以在 Doze 模式下能夠做一些事情斑唬。

  5. 定位

    定位中使用 GPS,及時關(guān)閉

    // Remove the listener you previously added
    locationManager.removeUpdates(locationListener);
    
  6. 計算優(yōu)化

    縮短代碼產(chǎn)生指令運行的時間黎泣,進而減少某個應(yīng)用程序?qū)?CPU 時間片 的總占用時間恕刘,進而減少單位時間內(nèi)該應(yīng)用程序占整個系統(tǒng)耗電的百分比。

    浮點運算比整數(shù)運算更消耗 CPU 時間片抒倚,因此耗電也會增加褐着,在編寫 代碼的過程中應(yīng)該盡量減少浮點運算。

    • 除法變乘法托呕。
    • 充分利用移位含蓉。
    • 查表法频敛,直接使用映射關(guān)系,但這會增加內(nèi)存占用馅扣,視情況而定斟赚。
  7. 熄屏后停止一些和 UI 效果有關(guān)的操作,比如動畫差油。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拗军,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蓄喇,更是在濱河造成了極大的恐慌发侵,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件公罕,死亡現(xiàn)場離奇詭異,居然都是意外死亡耀销,警方通過查閱死者的電腦和手機楼眷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來熊尉,“玉大人罐柳,你說我怎么就攤上這事≌。” “怎么了张吉?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長催植。 經(jīng)常有香客問我肮蛹,道長,這世上最難降的妖魔是什么创南? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任伦忠,我火速辦了婚禮,結(jié)果婚禮上稿辙,老公的妹妹穿的比我還像新娘昆码。我一直安慰自己,他們只是感情好邻储,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布赋咽。 她就那樣靜靜地躺著,像睡著了一般吨娜。 火紅的嫁衣襯著肌膚如雪脓匿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天宦赠,我揣著相機與錄音亦镶,去河邊找鬼日月。 笑死,一個胖子當著我的面吹牛缤骨,可吹牛的內(nèi)容都是我干的爱咬。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼绊起,長吁一口氣:“原來是場噩夢啊……” “哼精拟!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起虱歪,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤蜂绎,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后笋鄙,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體师枣,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年萧落,在試婚紗的時候發(fā)現(xiàn)自己被綠了践美。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡找岖,死狀恐怖陨倡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情许布,我是刑警寧澤兴革,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站蜜唾,受9級特大地震影響杂曲,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜袁余,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一解阅、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧泌霍,春花似錦货抄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至藤为,卻和暖如春怪与,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背缅疟。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工分别, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留遍愿,地道東北人。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓耘斩,卻偏偏與公主長得像沼填,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子括授,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容