前言
成爲一名優秀的Android開發,需要一份完備的知識體系,在這裏,讓我們一起成長爲自己所想的那樣~。
本文思維導圖
一、正確認識
1、爲什麼要做電量優化?
在 Android 應用開發中,我們需要考慮的是如何優化電量使用,讓我們的 App 不會因爲電量消耗過高被用戶排斥,或者被其他安全應用報告,以此確保用戶黏性。
2、電量重視度不夠
開發中一直連接手機,不知道電量消耗有多快。
3、電量消耗線上難以量化
我們沒有辦法拿到每一個用戶手機的組件能耗,其中不同的硬件模塊使用了不同的參數,然後使用了不同的算法來進行估算。但是,具體的參數值根據手機所使用的硬件來說是不一樣的。
二、電池技術
1、電池容量
現在一般手機的電池容量會佔用內部組件將近一半的空間。
2、充電時間
1)、OPPO VOOC 閃充技術
- 1、適配器中加入 MCU 智能芯片,得益於 MCU 對電流的精準調節,VOOC 實現了分段恆流和分檔技術,起步時,VOOC 會掛上高速檔,中間時會自動掛上中速檔,讓你快速前行,結尾時又會切換成低速擋,讓你平穩到站。
- 2、從適配器到接口再到手機內部的全端式五重防護技術。
- 1)、適配器過載保護
電流進入適配器時,其中的傳感器會實時檢測電壓電流,安全時, MOSFET(保護)開關會自動打開閃充。 - 2)、閃充條件鑑定保護
電流通過適配器時,MCU 芯片會識別設備是否支持閃充,只有支持纔開啓閃充與第二級過載保護。 - 3)、接口過載保護
電流進入手機時,在特別定製的 7pinUSB 接口處,手機內的 MCU 會控制第三個 MOSFET(保護)開關,實行第三級過載保護。 - 4)、電池過載保護
電池內的特殊 IC 和 MOSFET(保護)開關負責對進入電池的電壓電流實行過載保護。 - 5)、電池熔絲保護
出現異常時,電池內的保險絲會立即熔斷,物理性斷絕電流輸入。
- 1)、適配器過載保護
- 3、將充電安全指數從 PPM(百萬分之一)提升至航天級別 DPM(十億分之一)。
2)、快充技術
P=UI(電功率=電壓 * 電流)
普通充電過程
- 1)、先將 220V 電壓通過充電頭降至 5V。
- 2)、然後,手機內部電路再把 5V 電壓降至 4.2V。
- 3)、最後,把電量輸送給電池,而整個降壓的過程中會產生熱能。
分類
- 1)、高壓低電流快充方案:在充電過程中國提升充電電壓(7-20V)來提升充電功率。
- 2)、低壓大電流快充方案:在電壓一定情況下,增加電流,通常使用並聯電路的方式進行分流。
3)、鋁-石墨烯超級電池
- 超高耐用性和安全性,快充充電1.1秒就能充滿電。
- 實驗階段。
3、壽命
通常使用充電循環次數衡量。
4、安全性
嚴格控制電池容量,例如 VOOC 就使用了各種安全檢測技術。
5、電量和硬件
- 手機耗電是通過使用相應的硬件模塊來消耗電能。
- CPU、屏幕、WIFI、數據網絡、GPS、音視頻通話在日常耗電量中佔比最大。
6、Android 耗電演進
KITKAT
批處理傳感器
分批有效地收集和傳遞傳感器事件。
Alarm 對齊
批處理在合理的相似時間內的所有應用的鬧鈴,以便系統僅喚醒一次。
Lollipop
- 開啓 Volta 項目
- Job Scheduler
- dumpsys batterystats
- Battery Historian
- 修復 native fork 進程保活的 bug
Marshmallow
- 省電功能
- Doze 低功耗模式
- App Standby 應用待機摸手機
Nougat
- 優化省電功能
- Doze 加強版
- implicit broadcasts 顯示
- 混合編譯
Oreo
- 更多優化省電功能
- 後臺執行限制
- 後臺位置限制
P(電壓管理嚴格限制)
應用待機分組(App Standby Bueckets)
- 從應用安裝開始。
- 分組決定後臺被限制的程度。
- 不常用的應用將被限制地更加嚴格。
應用後臺限制(Background Restrictions)
- 用戶開啓。
- 停止後臺運行。
- 提示用戶後臺耗電嚴重的應用,用戶可選擇停止它們的後臺運行。
省電模式(Battery Saver)
- 用戶開啓。
- 所有應用進入待機模式。
- 更加嚴格的後臺限制,而且無視應用的 Target API。
三、電量檢測方案
對於電量的統計有一個公式,如下所示:
模塊電量(mAh) = 模塊電流(mA)* 模塊耗時(h)
Android 系統要求 ROM 廠商必須在 /frameworks/base/core/res/res/xml/power_profile.xml 提供組件的電源配置文件。而 Android 系統的電量計算 PowerProfile 正是通過讀取 power_profile.xml 的數據。
1、設置—耗電排行
- 1)、直觀,但沒有詳細數據,對解決問題幫助不大。
- 2)、需要找特定場景專項測試,比如在某一個界面操作一段時間,然後來判斷這個頁面是否耗電。
2、使用廣播監聽電量變化—ACTION_BATTERY_CHANGED
獲取電池電量、充電狀態、電池狀態等信息。
實戰案例
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
Intent intent = registerReceiver(null, filter);
LogUtils.i("battery " + intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1));
缺點
- 1)、價值不大:針對手機整體的耗電量,而非單個 App。
- 2)、實時性差、精度較低,被動通知。
3、dumpsys batterystats
batterystats 是 Android 5.0 提供的工具,它可以獲取各個 App 的 WakeLock、CPU 時間佔用等信息,同時增加了一個 Estimated power use(mAh)功能,預估耗電量。
作用
將電量測量轉化爲功能模塊的使用時間或者次數。
adb shell dumpsys batterystats > battery.txt
在 battery.txt 搜索 ‘Estimated power use’ 關鍵字,下面粗略統計了各個 Uid 的總耗電量。
Estimated power use (mAh):
Capacity: 3350, Computed drain: 2767, actual drain: 3752-3853
Uid 1000: 1014 ( cpu=999 wake=1.36 radio=11.4 wifi=1.24 gps=0.435 sensor=0.808 ) Excluded from smearing
Unaccounted: 985 ( ) Including smearing: 0 ( ) Excluded from smearing
Uid 0: 416 ( cpu=157 wake=210 radio=38.8 wifi=9.51 ) Excluded from smearing
...
batterystats 所記錄的電量統計數據源自於 BatteryStatsService-電量統計服務,其實現類爲 BatteryStatsImpl,內部正是使用的 PowerProfile 。
BatteryStatsImpl 爲每一個應用創建與之對應的 UID 來監控器系統資源的使用情況,其統計了 12 大模塊的電量消耗,如下所示:
- Camera、Audio、Video
- Bluetooth、Network、Wakelock
- Sensor、Radio、Screen
- WIFI、CPU、GPS
4、Battery Historian
特點
- 1)、查看自設備上次充電以來各種彙總統計信息,而且可以選擇對應的 App 查看詳細信息。
- 2)、可視化展示指標:
- 耗電比例。
- 執行時間、次數。
- 3)、僅適合線下使用。
安裝
- 1)、安裝 Docker
- 2)、docker – run -p :9999 gcr.io/android-battery-historian/stable:3.0 --port 9999 (需要外網)
導出電量信息
- 1)、使用 batterystats 命令重置手機電量:adb shell dumpsys batterystats --reset
- 2)、使用 batterystats 命令獲取電池數據權限並開啓記錄全面的電量信息:adb shell dumpsys batterystats --enable full-wake-history
- 3)、測試完成後,使用 bugreport 導出電量信息:
- 7.0和7.0以後:adb bugreport bugreport.zip
- 6.0和6.0之前:adb bugreport > bugreport.txt
- 通過 historian 圖形化展示結果:python historian.py -a bugreport.txt > battery.html
上傳分析
- 1)、打開 http://localhost:
如果打不開,可以使用備用網站 bathist
- 2)、上傳 bugreport 文件,點 Submit 提交即可。
Battery Historian 數據分析
Hitorian V2 — 電量統計圖表
Add Metrics
在 Add Metrics 中我們可以增加更多的測量項。
CPU running
如果一直處於 running,則表明電量消耗比較高。
JobScheduler
選中 Job Scheduler 的某一個工作時間片,我們可以查看具體的 發生的時間、耗時以及次數,最重要的是它統計出來了是哪一個進程在使用這個 JobScheduler。
App Selection
- 1)、選擇要分析電量的指定 App。
- 2)、點擊右邊區域的 System Stats 一欄可以在下方查看各個系統組件的電量百分比消耗詳情,例如 Userspace Wakelocks。
主入口處的 Switch to Bugreport Comparison
選擇多個文件進行上傳對比。
5、電量專項測試
1)、耗電場景測試
- 複雜計算。
- 音視頻播放。
2)、傳感器相關
- 使用時長
- 耗電量
- 發熱
3)、後臺靜默測試
四、耗電優化
1、耗電優化的難點
- 1)、缺乏現場,無法復現。
- 2)、信息不全,難以定位。
- 3)、無法評估結果。
在 App 開發中,經常會由於某個需求場景或 代碼 bug 而導致大量耗電。
2、後臺調度任務省電
思考步驟
- 需要後臺運行
- 長時間下載:DownloadManager
- 數據同步:SyncAdapter
- 本地任務:JobScheduler
- 特定時間執行:AlarmManager
- 實時通信:推送服務
- 立刻執行:Foreground Service
對於耗電優化中,我們最常用的就是 JobScheduler,下面👇,我們來實戰一下。
Job Scheduler 實戰
/**
* 開啓 JobScheduler
*/
private void startJobScheduler() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
JobInfo.Builder builder = new JobInfo.Builder(1, new ComponentName(getPackageName(), JobSchedulerService.class.getName()));
// 設置僅在 充電和WIFI 下才使用 JobScheduler 進行批量任務處理
builder.setRequiresCharging(true)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);
jobScheduler.schedule(builder.build());
}
}
其中,JobSchedulerService 就是用於進行批量任務處理的服務,示例代碼如下所示:
/**
* 用於進行批量任務處理的 JobSchedulerService
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class JobSchedulerService extends JobService {
@Override
public boolean onStartJob(JobParameters params) {
// 此處執行在主線程
// 模擬一些處理:批量網絡請求,APM日誌上報
return false;
}
@Override
public boolean onStopJob(JobParameters params) {
return false;
}
}
特點
- 1)、僅支持 API 21 及之上。
- 2)、在符合某些條件時創建執行在後臺的任務。
- 3)、把不緊急的任務放到更合適的時機批量處理。
符合 Android 規則,手機在充電狀態纔去做耗電工作。示例代碼如下所示:
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = context.registerReceiver(null, ifilter);
//獲取用戶是否在充電的狀態或者已經充滿電了
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL;
3、電量優化套路總結
1、優化應用的後臺耗電
避免後臺長時間獲取 WakeLock、WIFI 和藍牙的掃描等。
2、符合系統的耗電規則
Android P 使用了 Android Vitals 監控後臺耗電,其規則如下所示:
- 1)、Alarm Manager wakeup 喚醒過多:當手機不在充電狀態,每小時 wakeup 喚醒次數大於 10 次。
- 2)、頻繁使用局部喚醒鎖:當手機不在充電狀態,partial wake lock 持有超過1小時。
- 3)、後臺網絡使用量過高:當手機不在充電狀態而且應用在後臺,每小時網絡使用量超過 50MB。
- 4)、後臺 WiFi scans 過多:當手機不在充電狀態而且應用在後臺,每小時大於4次 WiFi scans。
3、CPU 時間片
Android 手機保護 AP 和 BP 兩個 CPU。AP 即 Application Processor,所有的用戶界面以及 App 都是運行在 AP 上的。BP 即 Baseband Processor,手機射頻都是運行在這個 CPU 上的。而一般我們所說的耗電,PowerProfile 文件裏面的 CPU,指的是 AP。
CPU 耗電通常有兩種情況:
- 1)、長期頻繁喚醒:原本可以僅僅在 BP 上運行,消耗 5mA 左右,但是因爲喚醒,AP 就會運作,不同手機情況不一樣,至少會導致 20~30 mA 左右的耗電。
- 2)、CPU 長期高負荷:例如 App 退到後臺的時候沒有停止動畫,或者程序有不退出的死循環等等,導致 CPU 滿頻、滿核地跑。
常用優化 CPU 時間片的方式有:
- 1)、獲取運行過程線程 CPU 消耗,定位 CPU 佔用率異常方法。
- 2)、減少後臺應用的主動運行。
4、網絡相關
通常情況下,使用 WIFI 連接網絡時的功耗要低於使用移動網絡的功耗。而使用移動網絡傳輸數據,電量的消耗有以下3種狀態:
- Full power:高功率狀態,移動網絡連接被激活,允許設備以最大的傳輸速率進行操作。
- Low power:低功耗狀態,對電量的消耗差不多是 Full power 狀態下的 50%。
- Standby:空閒態,沒有數據連接需要傳輸,電量消耗最少。
因此,爲了避免網絡連接所帶來的電量消耗,我們可以採用如下幾種方案:
- 1)、儘量在 WIFI 環境下進行數據傳輸,在使用 WIFI 傳輸數據時,應該儘可能增大每個包的大小(不超過 MTU),並降低發包的頻率。
- 2)、在蜂窩移動網絡下需要對請求時機及次數控制:可以延遲執行的網絡請求稍後一起發送,最好做到批量執行,儘量避免頻繁的間隔網絡請求,以儘量多地保持在 Radio Standby 狀態。
- 3)、使用 JSON 和 Protobuf 進行數據壓縮,減少時間。
- 4)、禁止使用輪詢功能:輪詢會導致網絡請求一直處於被激活的狀態,耗電過高。
5、定位相關
- 1)、根據場景謹慎選擇定位模式:對定位準確度沒那麼高的場景可以選擇低精度模式。
- 2)、可以考慮網絡定位代替 GPS。
- 3)、使用後務必及時關閉,減少更新頻率,例如定位開啓一定時間後超過某個閾值可以執行一個兜底策略:強制關閉 GPS。
6、界面相關
- 1)、離開界面後停止相關活動,例如關閉動畫。
- 2)、耗電操作判斷前後臺,如果是後臺則不執行相關操作。
7、WakeLock 相關
WakeLock 常用於後臺播放音視頻、錄製音視頻、下載文件的情況。如果沒有合理使用 WakeLock,則會造成嚴重的耗電問題,爲了避免該問題,我們應該定期針對使用了 WakeLock 的模塊進行重點排查。
我們可以使用 adb shell dumpsys power
命令查看系統當前的耗電信息,其中我們可以看到 WakeLock 列表,它通常會以 ”mLocks.size“ 或者 ”Wake Locks:size“ 開頭。關於 WakeLock 的使用我們要着重注意以下幾點:
- 1)、注意成對使用 acquire、release。
- 2)、建議使用帶參數的 acquire,避免沒有及時釋放而導致電量消耗過大。
- 3)、使用 finally 確保 release 一定會被調用。
- 4)、常亮場景使用 keepScreenOn 即可。
- 5)、WakeLock 有一個接口 setReferenceCounted,用來設置 WakeLock 的技術機制,官方默認爲計數。true 爲計數,false 爲不計數。所謂計數即每一個 acquire 必須對應一個 release;不計數則是無論有多少個 acquire,一個 release 就可以釋放。但是問題是有的第三方 ROM 它將默認設置爲了不計數,以爲我們需要在調用 newWakeLock 之後再調用 setReferenceCounted 爲 false。
8、計算優化
浮點運算比整數運算更消耗 CPU 時間片,因此耗電也會增加。避開浮點運算的優化方法如下所示:
- 1)、除法變乘法。
- 2)、充分利用移位。
- 3)、在 native 層開發時,可以利用 ARM neon 指令集做並行運算,注意需要 ARM V7 及以上架構 CPU 才能支持。
9、滅屏時停止動畫
我們可以監聽滅屏以及亮屏的廣播,在滅屏的時候停止 surfaceView 的動畫繪製。在亮屏的時候,恢復動畫的繪製。
五、耗電監控
以後臺耗電監控爲主,必須監控的模塊有:
- 1)、Alarm wakeup
- 2)、WakeLock
- 3)、WiFi scans
- 4)、Network
必須監控的現場信息有 :
- 1)、堆棧信息
- 2)、是否充電
- 3)、電量水平
- 4)、應用前後臺時間
- 5)、CPU 狀態信息
最後,我們需要 提煉規則,將監控內容 => 抽象成規則。
1、Java Hook
我們可以通過代理對應的 Service 實現,完成收集 Wakelock、Alarm、GPS 的申請堆棧、釋放信息、手機充電狀態等等。
2、電量輔助監控實戰
1)、獲取運行時能耗文件
- 1)、adb pull /system/framework/framework-res.apk
- 2)、反編譯,xml—》power_profile
2)、電量輔助監控
線下使用 epic 進行 AOP 電量輔助統計
這裏我們就以 WakeLock 的監控爲例,切面代碼如下所示:
public static long sStartTime = 0;
@Insert(value = "acquire")
@TargetClass(value = "com.optimize.performance.wakelock.WakeLockUtils",scope = Scope.SELF)
public static void acquire(Context context){
trace = Log.getStackTraceString(new Throwable());
sStartTime = System.currentTimeMillis();
Origin.callVoid();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
WakeLockUtils.release();
}
},1000);
}
@Insert(value = "release")
@TargetClass(value = "com.optimize.performance.wakelock.WakeLockUtils",scope = Scope.SELF)
public static void release(){
LogUtils.i("PowerManager "+(System.currentTimeMillis() - sStartTime)+"/n"+trace);
此外,我們也可以利用 epic 來監控每個線程的執行時間,超過閾值則警告,示例代碼如下所示:
public static long runTime = 0;
@Insert(value = "run")
@TargetClass(value = "java.lang.Runnable",scope = Scope.ALL)
public void run(){
runTime = System.currentTimeMillis();
Origin.callVoid();
LogUtils.i("runTime "+(System.currentTimeMillis() - runTime));
}
3、編譯插樁
寫一個基礎類,然後在統一的調用接口中添加監控邏輯。這裏我們可以參考 Facebook Battery-Metrics
獲取、監控數據的方式。其代碼如下所示:
public class WakelockMetrics {
/**
* 獲取 WakeLock
*
* @param wakeLock WakeLock
* @param timeout 超時時間
*/
public static void acquire(PowerManager.WakeLock wakeLock, long timeout) {
wakeLock.acquire(timeout);
// 監控 wakelock 相關信息
Log.e("HOOOOOOOOK", "--acquireWakeLock--");
Log.e("HOOOOOOOOK", Utils.getStackTrace());
// 使用 Battery-Metrics 庫統計其它維度的電量信息
}
/**
* 釋放 WakeLock
*
* @param wakeLock WakeLock
*/
public static void release(PowerManager.WakeLock wakeLock) {
wakeLock.release();
Log.e("HOOOOOOOOK", "--releaseWakeLock--");
Log.e("HOOOOOOOOK", Utils.getStackTrace());
// 使用 Battery-Metrics 庫統計其它維度的電量信息
}
}
Gradle 耗電量統計插件中 BatteryCreateMethodVisitor 的核心實現代碼如下所示:
@Override
public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
// 監控 Wakelock
String monitorClass = "com/ss/android/ugc/bytex/example/battery_monitor/WakelockMetrics";
if (!monitorClass.equals(className)
&& "android/os/PowerManager$WakeLock".equals(owner)
&& opcode == Opcodes.INVOKEVIRTUAL
&& "acquire".equals(name)) {
mv.visitMethodInsn(
Opcodes.INVOKESTATIC,
monitorClass,
name,
"(Landroid/os/PowerManager$WakeLock;J)V",
isInterface
);
return;
}
if (!monitorClass.equals(className)
&& "android/os/PowerManager$WakeLock".equals(owner)
&& opcode == Opcodes.INVOKEVIRTUAL
&& "release".equals(name)) {
mv.visitMethodInsn(
Opcodes.INVOKESTATIC,
monitorClass,
name,
"(Landroid/os/PowerManager$WakeLock;)V",
isInterface
);
return;
}
// 監控 Gps
monitorClass = "com/ss/android/ugc/bytex/example/battery_monitor/GpsMetrics";
if (!monitorClass.equals(className)
&& "android/location/LocationManager".equals(owner)
&& opcode == Opcodes.INVOKEVIRTUAL
&& "requestLocationUpdates".equals(name)) {
mv.visitMethodInsn(
Opcodes.INVOKESTATIC,
monitorClass,
name,
"(Landroid/location/LocationManager;Ljava/lang/String;JFLandroid/location/LocationListener;)V",
isInterface
);
return;
}
if (!monitorClass.equals(className)
&& "android/location/LocationManager".equals(owner)
&& opcode == Opcodes.INVOKEVIRTUAL
&& "removeUpdates".equals(name)) {
mv.visitMethodInsn(
Opcodes.INVOKESTATIC,
monitorClass,
name,
"(Landroid/location/LocationManager;Landroid/location/LocationListener;)V",
isInterface
);
return;
}
// 監控 Alarm Service
monitorClass = "com/ss/android/ugc/bytex/example/battery_monitor/AlarmMetrics";
if (!monitorClass.equals(className)
&& "android/app/AlarmManager".equals(owner)
&& opcode == Opcodes.INVOKEVIRTUAL
&& "set".equals(name)) {
mv.visitMethodInsn(
Opcodes.INVOKESTATIC,
monitorClass,
name,
"(Landroid/app/AlarmManager;IJLandroid/app/PendingIntent;)V",
isInterface
);
return;
}
if (!monitorClass.equals(className)
&& "android/app/AlarmManager".equals(owner)
&& opcode == Opcodes.INVOKEVIRTUAL
&& "cancel".equals(name)) {
mv.visitMethodInsn(
Opcodes.INVOKESTATIC,
monitorClass,
name,
"(Landroid/app/AlarmManager;Landroid/app/PendingIntent;)V",
isInterface
);
return;
}
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
}
缺點
系統的代碼插樁方案無法替換。
六、電量優化常見問題
1、怎麼做電量測試?
電量相關的測試相對來說難度較大,因爲 App 在具體手機上的耗電量無法準確統計,每一個手機所使用的硬件不一樣,那麼它相應的功耗就不一樣。而且這個功耗值我們只能在線下通過導出手機的 power_profile.xml 文件拿到。
由於我們無法獲取準確的耗電量,所以我們只能增加多個維度來輔助判斷 App 是否耗電。
最後,我們可以分場景各個突破。
關於電量測試,我們可以針對各個功能場景進行鍼對性的專項測試。操作一段時間後,我們可以在手機設置—電量消耗裏面,利用其數據作爲判斷依據。這樣雖然直觀,但精確度不行。
介紹 Battery Historian:
- Google 推出的一款 Android 電量分析工具,它支持 Android 5.0 及以上系統的電量分析。
- 它獲取到的各個耗電模塊的耗電信息要相對精確、豐富地多。例如 GPS、WaleLock、藍牙 等的工作時間以及耗電量。
- 此外,它不僅可以針對單個 App 進行選擇,也可以比對不同的電量場景的信息,比如 優化前、優化後 的信息。
- Battery Historian 的缺點在於它只能在線下使用。因此除了使用其在線下測試之外,我們還需要在線上增加一些電量的輔助監控,統計例如:耗電組件的使用次數、調用堆棧以及訪問時間。這些都是與用戶相關的基礎電量消耗數據,如果有用戶反饋,我們就可以通過這些信息來判斷用戶是不是有耗電的操作。
2、有哪些有效的電量優化手段?
因爲我們不能在線上統計出 App 的電量消耗,因此需要在儘量保證 App 在正常使用下的耗電。對此我們採取了一系列的電量優化措施:
1)、網絡相關
- 網絡請求的時機以及次數,將可以延遲的網絡請求批量發送,減少網絡被激活的時機與次數。
- 此外,我們可以對網絡傳輸數據進行壓縮,以降低傳輸的時間與流量。
- 最後,一定要禁止使用輪詢的方式來做業務操作。
2)、傳感器相關
根據場景謹慎地選擇傳感器使用的模式,比如說在使用 GPS 的時候一般要避免使用高精度的模式,或者是儘量複用上一次的定位結果。
3)、WakeLock
我們在實際項目中使用 WakeLock 有幾個注意事項,第一,acquire、release 要成對地釋放,第二,儘量使用 acquire 的超時方法來設置超時時間,避免因爲異常情況從而導致 WakeLock 而無法釋放的情況,第三,關於 WakeLock 的釋放一定要寫在 try-catch-finally 的 finally 當中,保證 WakeLock 在異常情況下的釋放。
4)、JobScheduler
JobScheduler 可以允許開發者在符合某些條件下創造執行在後臺的任務,我們可以設置執行一些耗電操作的場景,比如說 處於 WIFI 狀態下同時連接電源 的情況下。同時,要注意用戶在離開界面後,要避免耗電的操作,比如說停止播放動畫。通過這些操作,我們的 App 就不會比之前耗電了。
七、總結
對於電量優化來說,最重要的就是 建立監控與自動化報警的一整套體系,只有發現了耗電的問題所在,才能使用針對性的解決措施。
公衆號
我的公衆號 JsonChao
開通啦,歡迎關注~
參考鏈接:
- 1、《Android性能優化最佳實踐》第六章 耗電優化(基礎)
- 2、慕課網之Top團隊大牛帶你玩轉Android性能分析與優化 第九章 App電量優化(進階)
- 3、極客時間之Android開發高手課 耗電優化(進階)
- 4、《Android移動性能實戰》第五章 電池(經驗)
- 5、手機硬件已進入發展瓶頸,未來電池技術將如何突破?
- 6、VOOC 閃充
- 7、google/battery-historian
- 8、google/battery-historian-docs
- 9、google/battery-historian-api
- 10、大衆點評 App 的短視頻耗電量優化實戰
- 11、Android 後臺調度任務與省電
- 12、Android P 電量管理
- 13、facebookincubator/Battery-Metrics
- 14、simplezhli/Chapter19
Contanct Me
● 微信:
歡迎關注我的微信:
bcce5360
● 微信羣:
由於微信羣人數過多,麻煩大家想進微信羣的朋友們,加我微信拉你進羣。
● QQ羣:
2千人QQ羣,Awesome-Android學習交流羣,QQ羣號:959936182, 歡迎大家加入~
About me
-
Email: [email protected]
-
Blog: https://jsonchao.github.io/
-
掘金: https://juejin.im/user/5a3ba9375188252bca050ade