性能優(yōu)化<第十二篇>:Android電量優(yōu)化

大致章節(jié)如下:
(1)為什么會耗電翰守?
(2)學(xué)會使用電量分析工具Battery Historian
(3)低耗電模式(Doze)和應(yīng)用待機模式(App Standby)
(4)監(jiān)控電池電量和充電狀態(tài)
(5)確定和監(jiān)控插接狀態(tài)和基座類型

一孵奶、為什么會耗電?
電量的消耗是一種必然現(xiàn)象蜡峰,主要是由于移動設(shè)備的硬件在工作導(dǎo)致耗電了袁;
硬件的過度工作朗恳,導(dǎo)致耗電增加,這種情況屬于不正吃芈蹋現(xiàn)象粥诫,所以需要電量優(yōu)化;
耗電比較嚴重的硬件主要有:CPU崭庸、wakelock怀浆、數(shù)據(jù)傳輸(流量和wifi)、wifi運行冀自、gps、other senior等秒啦。
二熬粗、學(xué)會使用電量分析工具Battery Historian

Battery Historian 是谷歌推出的系統(tǒng)電量分析工具,僅支持5.0(API21)及以上系統(tǒng)的電量分析余境。

Battery Historian 對應(yīng)的Github地址是:

https://github.com/google/battery-historian

在線電量分析工具地址是:https://bathist.ef.lc/驻呐,可以將bugreport文件上傳到在線網(wǎng)站上,從而進行數(shù)據(jù)分析芳来。但是含末,它的響應(yīng)速度太慢,甚至無法傳遞數(shù)據(jù)即舌,估計是需要翻墻才可以正常訪問吧佣盒。

Battery Historian可以配置本地環(huán)境,在Battery Historian的github官網(wǎng)上可以找到本地環(huán)境配置方法顽聂,步驟如下:

【1】 安裝Docker(https://docs.docker.com/engine/install/

需要注意的是:

現(xiàn)在官網(wǎng)提供的最新版本的Docker只支持win10以上的操作系統(tǒng)或者mac系統(tǒng)肥惭,作者本人特地將win7升級到win11系統(tǒng);
如果Docker啟動失敗紊搪,報`WSL 2 installation is incomplete.`錯誤蜜葱,那么需要安裝`wsl_update_x64.msi`才可以,下載地址是:
    https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

Docker安裝完之后耀石,啟動即可牵囤。

如果Docker中沒有正在執(zhí)行的鏡像,那么主頁面會提示沒有容器在運行滞伟,如圖:

image.png
docker run -d -p:運行鏡像的命令
80:端口號
docker/getting-started:鏡像名稱

可以在命令提示符或者git bash中執(zhí)行命令(需要保證Docker已啟動):

docker run -d -p 80:80 docker/getting-started

如果本地沒有docker/getting-started鏡像揭鳞,那么直接重遠程下載:

image.png

最終成功啟動鏡像:

image.png

輸入命令:

docker ps -a

可以看到當(dāng)前正在執(zhí)行的鏡像:

image.png

打開瀏覽器,輸入:

http://localhost:80

即可打開docker/getting-started鏡像的主頁面梆奈。

【2】 安裝電池分析相關(guān)鏡像

github上提供了電量分析相關(guān)的鏡像:gcr.io/android-battery-historian/stable:3.0

輸入以下命令下載并啟動鏡像(為了防止端口沖突汹桦,就不要設(shè)置80或者8080端口了):

docker run -d -p 9999:9999 gcr.io/android-battery-historian/stable:3.0 --port 9999

結(jié)果超時了:

image.png

之所以超時,可能是防火墻的原因鉴裹,或者需要翻墻舞骆。

如果您真的超時了钥弯,也無需煩惱,只需要使用Docker自帶的搜索命令督禽,輸入命令:

docker search battery

即脆霎,搜索關(guān)鍵字"battery"找到所有與battery相關(guān)的鏡像,如圖:

image.png

NAME為鏡像名稱狈惫,經(jīng)過一波嘗試睛蛛,最終確認,最好用的鏡像是:runcare/battery-historian胧谈,因為他可以做到秒開忆肾。

接下來就用runcare/battery-historian鏡像來演示。

輸入命令下載并啟動鏡像:

docker run -d -p 9999:9999 runcare/battery-historian --port 9999

等待下載完成菱肖,runcare/battery-historian鏡像下載完成之后客冈,會自動啟動,如果已經(jīng)啟動稳强,請先關(guān)閉场仲。
接下來,點擊下圖的RUN按鈕:

image.png

啟動之前退疫,需要配置下端口號:

image.png
Local Host對應(yīng)的是localhost后面的端口號渠缕;
Container Port是容器的端口號;

需要注意的是褒繁, Local Host和Container Port不能相同亦鳞,否則上傳電池信息的Submit按鈕無法顯示。

在瀏覽器上輸入(localhost后面的8888就是啟動鏡像之前配置的端口號):

http://localhost:8888/

打開后的頁面如下:

image.png

【3】 導(dǎo)出電池信息日志

重置電量信息:adb shell dumpsys batterystats --reset
獲取完整的wakelock信息:adb shell dumpsys batterystats --enable full-wake-history 
拔掉USB棒坏,讓設(shè)備不處于充電狀態(tài)蚜迅,等待一段時間....
獲得報告:
>7.0
adb bugreport bugreport.zip
<=6.0
adb bugreport > bugreport.txt

【4】 上傳bugreport文件并分析

在瀏覽器上輸入:

http://localhost:8888/

點擊“Browse”按鈕,選擇bugreport文件俊抵,之后頁面的右側(cè)會出現(xiàn)一個提交按鈕

image.png

點擊提交:

image.png

那么谁不,怎么分析這個數(shù)據(jù)呢?
主要從兩個維度上來分析:

(1)查看耗電應(yīng)用排行

點擊左側(cè)的“Tables - Device's Power Estimates”徽诲,

image.png

耗電排名第一的非系統(tǒng)應(yīng)用為高德地圖刹帕,這個數(shù)據(jù)理所當(dāng)然,因為這段時間谎替,我只打開了高德地圖應(yīng)用偷溺。

(2)查看具體應(yīng)用的耗電情況

找到左側(cè)的”App Selection“,選擇對應(yīng)耗電應(yīng)用的包名:

image.png

查看耗電信息:


image.png
三钱贯、低耗電模式(Doze)和應(yīng)用待機模式(App Standby)

為了延長電池壽命挫掏,谷歌在Android 6.0(API 23)引入了低耗電模式(Doze)和應(yīng)用待機模式(App Standby)。

低電耗模式:如果用戶未插接設(shè)備的電源秩命,在屏幕關(guān)閉的情況下尉共,讓設(shè)備在一段時間內(nèi)保持不活動狀態(tài)褒傅,那么設(shè)備就會進入低電耗模式。
在低電耗模式下袄友,系統(tǒng)會嘗試通過限制應(yīng)用訪問占用大量網(wǎng)絡(luò)和 CPU 資源的服務(wù)來節(jié)省電量殿托。
它還會阻止應(yīng)用訪問網(wǎng)絡(luò),并延遲其作業(yè)剧蚣、同步和標(biāo)準(zhǔn)鬧鐘支竹。

系統(tǒng)會定期退出低電耗模式一小段時間,讓應(yīng)用完成其延遲的活動鸠按。
在此維護期內(nèi)礼搁,系統(tǒng)會運行所有待處理的同步、作業(yè)和鬧鐘目尖,并允許應(yīng)用訪問網(wǎng)絡(luò)馒吴。

在每個維護期結(jié)束時,系統(tǒng)會再次進入低電耗模式卑雁,暫停網(wǎng)絡(luò)訪問并推遲作業(yè)募书、同步和鬧鐘绪囱。
隨著時間的推移测蹲,系統(tǒng)安排維護期的次數(shù)越來越少,這有助于在設(shè)備未連接至充電器的情況下長期處于不活動狀態(tài)時降低耗電量鬼吵。

一旦用戶通過移動設(shè)備扣甲、打開屏幕或連接至充電器喚醒設(shè)備,系統(tǒng)就會立即退出低電耗模式齿椅,并且所有應(yīng)用都會恢復(fù)正沉鹜冢活動。

在低耗電模式下涣脚,您的應(yīng)用會收到如下限制:

(1)暫停訪問網(wǎng)絡(luò)示辈;
(2)系統(tǒng)忽略喚醒鎖定(PowerManager.WakeLock);
(3)標(biāo)準(zhǔn) AlarmManager 的 setExact() 和 setWindow() 推遲到下個維護期遣蚀;
     如果需要在低耗電模式下觸發(fā)鬧鐘使用 `setAndAllowWhileIdle()` 和 `setExactAndAllowWhileIdle()` 即可矾麻;
     使用 `setAlarmClock()` 設(shè)置的鬧鐘將繼續(xù)正常觸發(fā),系統(tǒng)會在這些鬧鐘觸發(fā)之前不久退出低耗電模式芭梯;
(4)系統(tǒng)不執(zhí)行WLAN掃描险耀;
(5)系統(tǒng)不允許運行同步適配器;
(6)系統(tǒng)不允許運行JobScheduler玖喘;

低耗電模式下甩牺,您的應(yīng)用可能存在的影響?

低電耗模式可能會對應(yīng)用產(chǎn)生不同的影響累奈,具體取決于應(yīng)用提供的功能和使用的服務(wù)贬派。
許多應(yīng)用無需修改即可在低電耗模式周期內(nèi)正常運行急但。
在某些情況下,您必須優(yōu)化應(yīng)用管理網(wǎng)絡(luò)赠群、鬧鐘羊始、作業(yè)和同步的方式。
應(yīng)用應(yīng)該能夠在每個維護期內(nèi)高效地管理活動查描。
低電耗模式尤其可能會影響 `AlarmManager` 鬧鐘和定時器管理的活動突委,因為當(dāng)系統(tǒng)處于低電耗模式時,不會觸發(fā) Android 5.1(API 級別 22)或更低版本中的鬧鐘冬三。

為了幫助安排鬧鐘匀油,Android 6.0(API 級別 23)引入了兩種新的 `AlarmManager` 方法:`setAndAllowWhileIdle()` 和 `setExactAndAllowWhileIdle()`。
通過這些方法勾笆,您可以設(shè)置即使設(shè)備處于低電耗模式也會觸發(fā)的鬧鐘敌蚜。

低電耗模式對網(wǎng)絡(luò)訪問的限制也有可能影響應(yīng)用,特別是當(dāng)應(yīng)用依賴于操作消息或通知等實時消息時更是如此窝爪。

系統(tǒng)提供白名單弛车,可以部分免除低耗電模式和應(yīng)用待機模式給應(yīng)用帶來的影響?

通過妥善管理網(wǎng)絡(luò)連接、鬧鐘蒲每、作業(yè)和同步纷跛,幾乎所有應(yīng)用都應(yīng)該能夠支持低電耗模式。
系統(tǒng)提供了一個可配置的白名單邀杏,將部分免除低電耗模式和應(yīng)用待機模式優(yōu)化的應(yīng)用列入其中贫奠。

在低電耗模式和應(yīng)用待機模式期間,列入白名單的應(yīng)用可以使用網(wǎng)絡(luò)并保留部分喚醒鎖定望蜡。不過唤崭,列入白名單的應(yīng)用仍會受到其他限制,就像其他應(yīng)用一樣脖律。
例如谢肾,列入白名單的應(yīng)用的作業(yè)和同步會延遲(在搭載 API 級別 23 及更低級別的設(shè)備上),并且其常規(guī) `AlarmManager` 鬧鐘不會觸發(fā)小泉。
應(yīng)用可以調(diào)用 `isIgnoringBatteryOptimizations()` 來檢查它當(dāng)前是否在豁免白名單中芦疏。

用戶可以依次轉(zhuǎn)到`設(shè)置 > 電池 > 電池優(yōu)化`來手動配置該白名單。另外膏孟,系統(tǒng)也提供了一些方法眯分,讓應(yīng)用要求用戶將其列入白名單。
`設(shè)置 > 電池 > 電池優(yōu)化`只是部分手機的路徑柒桑,但是有些手機弊决,電池優(yōu)化的路徑并未暴露出來爷速,可以通過以下代碼直接跳轉(zhuǎn)到`電池優(yōu)化`界面咧栗。

    Intent intent = new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
    startActivity(intent);

類似這樣的界面:

image.png
image.png
Android 6.0 之后琅催,PowerManager 新增了isIgnoringBatteryOptimizations方法郊丛,來確定應(yīng)用是電池優(yōu)化的情況。

    PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        // 是否忽視電池優(yōu)化
        boolean isIgnoringBatteryOptimizations = powerManager.isIgnoringBatteryOptimizations(getPackageName());
    }

如果應(yīng)用的電池優(yōu)化選擇了`不優(yōu)化`昆稿,那么`isIgnoringBatteryOptimizations`的值為true纺座,
此時就相當(dāng)于已經(jīng)加入了白名單,電池電量肯能會更快耗盡溉潭,系統(tǒng)將不再限制應(yīng)用在后臺使用電量净响;

具有 `REQUEST_IGNORE_BATTERY_OPTIMIZATIONS` 權(quán)限的應(yīng)用可以觸發(fā)一個系統(tǒng)對話框,讓用戶直接將該應(yīng)用添加到白名單喳瓣,而無需轉(zhuǎn)到“設(shè)置”馋贤。
此類應(yīng)用將通過觸發(fā) `ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS` Intent 來觸發(fā)該對話框。
代碼如下:

    PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        // 是否忽視電池優(yōu)化
        boolean isIgnoringBatteryOptimizations = powerManager.isIgnoringBatteryOptimizations(getPackageName());
        if (!isIgnoringBatteryOptimizations) {
            Intent intent = new Intent(ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
            startActivity(intent);
        }
    }

`ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS`的目的是為了彈出系統(tǒng)對話框畏陕,但是配乓,部分手機并沒有這個對話框,可以使用try...catch來保護惠毁。

另外犹芹,用戶可以根據(jù)需要從白名單中手動移除應(yīng)用。

如何在低電耗模式下進行測試鞠绰?

為確保用戶獲得良好的體驗腰埂,您應(yīng)在低電耗模式和應(yīng)用待機模式下全面測試您的應(yīng)用。

您可以按以下步驟在低電耗模式下測試您的應(yīng)用:
(1)使用 Android 6.0(API 級別 23)或更高版本的系統(tǒng)映像配置硬件設(shè)備或虛擬設(shè)備洞豁。
(2)將設(shè)備連接到開發(fā)計算機并安裝您的應(yīng)用盐固。
(3)運行您的應(yīng)用并使其保持活動狀態(tài)荒给。
(4)運行以下命令丈挟,強制系統(tǒng)進入閑置模式:

    adb shell dumpsys deviceidle force-idle

(5)準(zhǔn)備就緒后,運行以下命令志电,使系統(tǒng)退出閑置模式:

    adb shell dumpsys deviceidle unforce

(6)執(zhí)行以下命令曙咽,重新激活設(shè)備:

    adb shell dumpsys battery reset

(7)在重新激活設(shè)備后觀察應(yīng)用的行為。確保應(yīng)用在設(shè)備退出低電耗模式時正程袅荆恢復(fù)例朱。

如何在應(yīng)用待機模式下進行測試?

如需在應(yīng)用待機模式下測試您的應(yīng)用鱼蝉,請執(zhí)行以下操作:
(1)使用 Android 6.0(API 級別 23)或更高版本的系統(tǒng)映像配置硬件設(shè)備或虛擬設(shè)備洒嗤。
(2)將設(shè)備連接到開發(fā)計算機并安裝您的應(yīng)用。
(3)運行您的應(yīng)用并使其保持活動狀態(tài)魁亦。
(4)運行以下命令渔隶,強制應(yīng)用進入應(yīng)用待機模式:

    adb shell dumpsys battery unplug
    adb shell am set-inactive <packageName> true

(5)使用以下命令模擬喚醒您的應(yīng)用:

    adb shell am set-inactive <packageName> false
    adb shell am get-inactive <packageName>

(6)在喚醒應(yīng)用后觀察它的行為。確保應(yīng)用從待機模式正常恢復(fù)间唉。您應(yīng)特別檢查應(yīng)用的通知和后臺作業(yè)是否繼續(xù)按預(yù)期運行绞灼。
四、監(jiān)控電池電量和充電狀態(tài)
如果您要通過改變后臺更新的頻率降低這些更新對電池續(xù)航時間的影響呈野,最好先從檢查當(dāng)前電池電量和充電狀態(tài)入手低矮。

執(zhí)行應(yīng)用更新對電池續(xù)航時間的影響取決于設(shè)備的電池電量和充電狀態(tài)。設(shè)備通過交流電源充電時執(zhí)行更新的影響可以忽略不計被冒,因此在大多數(shù)情況下军掂,
只要設(shè)備連接到壁式充電器,您就可以最大限度地提高更新頻率昨悼。相反良姆,如果設(shè)備正在放電,降低更新頻率有助于延長電池續(xù)航時間幔戏。

同理玛追,您也可以檢查電池充電電量,并在電池電量近乎耗盡時降低更新頻率闲延,甚至停止更新痊剖。

如何確認當(dāng)前充電狀態(tài)?

首先垒玲,確定當(dāng)前充電狀態(tài)陆馁。`BatteryManager` 會在一個包含充電狀態(tài)的粘性 `Intent` 中廣播所有電池和充電詳情。

由于它是一個粘性 Intent合愈,因此您并不需要如下一代碼段中所示的那樣通過簡單地調(diào)用 `registerReceiver` 
傳入 `null` 作為接收器來注冊 `BroadcastReceive`叮贩,便可返回當(dāng)前電池狀態(tài) Intent。
您可以在此處傳入實際 `BroadcastReceive` 對象佛析,但由于稍后我們將會處理更新益老,因此并不需要這樣做。

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


獲取電池的充電狀態(tài)寸莫?

    int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
    電池的充電狀態(tài)有:
    BatteryManager.BATTERY_STATUS_UNKNOWN:沒有安裝電池
    BatteryManager.BATTERY_STATUS_CHARGING:正在充電
    BatteryManager.BATTERY_STATUS_DISCHARGING:放電中
    BatteryManager.BATTERY_STATUS_NOT_CHARGING:未充電
    BatteryManager.BATTERY_STATUS_FULL:已經(jīng)充滿(電量100%不代表一定是BATTERY_STATUS_FULL狀態(tài)捺萌,如果電量100%并且正在充電才是BATTERY_STATUS_FULL狀態(tài))

    // 是否正在充電
    boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL;

您可以提取當(dāng)前充電狀態(tài),并且如果設(shè)備正在充電膘茎,則還可以提取設(shè)備是通過 USB 還是交流充電器進行充電桃纯。

    int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
    電池的電源類型有:
    BatteryManager.BATTERY_PLUGGED_USB:電源為USB端口
    BatteryManager.BATTERY_PLUGGED_AC:電源為交流充電器
    BatteryManager.BATTERY_PLUGGED_WIRELESS:電源為無線

    // 電源是否是USB端口
    boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
    // 電源是否是交流充電器
    boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;
    // 電源是否是無線的
    boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_WIRELESS;

您可以獲取電池的健康狀態(tài)

    // 電池的健康狀況
    int chargeHealth = batteryStatus.getIntExtra(BatteryManager.EXTRA_HEALTH, -1);
    電池的健康狀況有:
    BatteryManager.BATTERY_HEALTH_UNKNOWN:未知
    BatteryManager.BATTERY_HEALTH_GOOD:良好
    BatteryManager.BATTERY_HEALTH_OVERHEAT:過熱
    BatteryManager.BATTERY_HEALTH_DEAD:沒電
    BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:過電壓
    BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:未知故障
    BatteryManager.BATTERY_HEALTH_COLD:冷卻

    // 是否為Good狀態(tài)
    boolean chargeGood = chargeHealth == BatteryManager.BATTERY_HEALTH_GOOD;

如何監(jiān)控充電狀態(tài)變化?

就像設(shè)備可以輕松地插入電源披坏,充電狀態(tài)也很容易發(fā)生變化态坦,因此必須監(jiān)控充電狀態(tài)的變化并相應(yīng)地改變刷新頻率。

每當(dāng)設(shè)備連接或斷開電源時棒拂,`BatteryManager` 都會廣播一項操作伞梯。請務(wù)必接收這些事件,即便您的應(yīng)用并未運行,
尤其要考慮到這些事件可能會影響您啟動應(yīng)用以便發(fā)起后臺更新的頻率壮锻,因此您應(yīng)在清單中注冊一個 `BroadcastReceiver`琐旁,
通過在一個 Intent 過濾器內(nèi)定義 `ACTION_POWER_CONNECTED` 和 `ACTION_POWER_DISCONNECTED` 來同時監(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>


public class PowerConnectionReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
        boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL;
        if (isCharging) {
            Log.d("TAG", "正在充電...");
        } else {
            Log.d("TAG", "放電中...");
        }
    }
}

    IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
    this.registerReceiver(new PowerConnectionReceiver(), ifilter);

當(dāng)充電器插拔時猜绣,充電狀態(tài)改變灰殴,PowerConnectionReceiver廣播總是被觸發(fā)。

如何確定當(dāng)前電池電量掰邢?

在某些情況下牺陶,確定當(dāng)前電池電量也很有用處。您可以選擇在電池電量低于某一水平時降低后臺更新的頻率辣之。

您可以通過從電池狀態(tài) intent 提取當(dāng)前電池電量和刻度來了解當(dāng)前電池電量掰伸,如下所示:

    int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
    int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);

    float batteryPct = level * 100 / (float)scale;

如何監(jiān)控電池電量變化?

您無法輕松地持續(xù)監(jiān)控電池狀態(tài)怀估,您也不必如此狮鸭。

一般而言,持續(xù)監(jiān)控電池電量對電池的影響大于應(yīng)用正常行為造成的影響多搀,因此最好只監(jiān)控顯著的電池電量變化歧蕉,特別是在設(shè)備進入或退出電量不足狀態(tài)時。

Android給我們提供了兩個給力的Actiton康铭,分別是:BATTERY_LOW 和 BATTERY_OKAY
BATTERY_LOW:設(shè)備進入電量不足狀態(tài)
BATTERY_OKAY:設(shè)備退出電量不足狀態(tài)

    <receiver android:name=".BatteryLevelReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BATTERY_LOW"/>
            <action android:name="android.intent.action.BATTERY_OKAY"/>
        </intent-filter>
    </receiver>

一般而言惯退,建議您在電量極低時停用所有后臺更新。如果手機自行關(guān)機从藤,您就無法利用相關(guān)數(shù)據(jù)催跪,數(shù)據(jù)的新鮮度也就無關(guān)緊要。
五夷野、確定和監(jiān)控插接狀態(tài)和基座類型
Android 設(shè)備可插接到幾個不同種類的基座懊蒸,其中包括車載或家用基座以及數(shù)字和模擬基座。
插接狀態(tài)通常與充電狀態(tài)聯(lián)系密切扫责,因為許多基座都為插接的設(shè)備供電榛鼎。

手機插接狀態(tài)對更新頻率的影響取決于您的應(yīng)用逃呼。
您可以選擇在手機插入桌面基座時提高體育中心應(yīng)用的更新頻率鳖孤,或者在設(shè)備插入車載基座時完全停用更新。
相反抡笼,如果您的后臺服務(wù)正在更新路況信息苏揣,則您可以選擇在已插接車載基座的情況下最大限度地提高更新頻率。

插接狀態(tài)也會以粘性 `Intent` 形式廣播推姻,以便您查詢設(shè)備是否已插接以及已插接情況下的基座類型平匈。

如何確定當(dāng)前插接狀態(tài)?

插接狀態(tài)詳情以 extra 形式包含在 `ACTION_DOCK_EVENT` 操作的粘性廣播中。由于它是粘性廣播增炭,因此您只需調(diào)用 `registerReceiver()`忍燥,將 `null` 作為廣播接收器傳入。
以下代碼段展示了如何完成此流程:

IntentFilter ifilter = new IntentFilter(Intent.ACTION_DOCK_EVENT);
Intent dockStatus = context.registerReceiver(null, ifilter);

您可以從 EXTRA_DOCK_STATE extra 中提取當(dāng)前插接狀態(tài):

    int dockState = dockStatus.getIntExtra(EXTRA_DOCK_STATE, -1);
    boolean isDocked = dockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;

基座類型有:

Intent.EXTRA_DOCK_STATE_UNDOCKED:無基座
Intent.EXTRA_DOCK_STATE_DESK:桌面基座
Intent.EXTRA_DOCK_STATE_CAR:車載基座
Intent.EXTRA_DOCK_STATE_LE_DESK:低端(模擬)桌面基座
Intent.EXTRA_DOCK_STATE_HE_DESK:高端(數(shù)字)桌面基座

請注意隙姿,后兩種類型從 Android 的 API 級別 11 才開始引入梅垄,因此如果您只關(guān)注基座類型而不關(guān)心其具體為數(shù)字還是模擬形式,則最好檢查所有三種類型:

    boolean isCar = dockState == EXTRA_DOCK_STATE_CAR;
    boolean isDesk = dockState == EXTRA_DOCK_STATE_DESK ||
                     dockState == EXTRA_DOCK_STATE_LE_DESK ||
                     dockState == EXTRA_DOCK_STATE_HE_DESK;

[本章完...]

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末输玷,一起剝皮案震驚了整個濱河市队丝,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌欲鹏,老刑警劉巖机久,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異赔嚎,居然都是意外死亡膘盖,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門尤误,熙熙樓的掌柜王于貴愁眉苦臉地迎上來衔憨,“玉大人,你說我怎么就攤上這事袄膏〖迹” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵沉馆,是天一觀的道長码党。 經(jīng)常有香客問我,道長斥黑,這世上最難降的妖魔是什么揖盘? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮锌奴,結(jié)果婚禮上兽狭,老公的妹妹穿的比我還像新娘。我一直安慰自己鹿蜀,他們只是感情好箕慧,可當(dāng)我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著茴恰,像睡著了一般颠焦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上往枣,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天伐庭,我揣著相機與錄音粉渠,去河邊找鬼。 笑死圾另,一個胖子當(dāng)著我的面吹牛霸株,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播集乔,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼淳衙,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了饺著?” 一聲冷哼從身側(cè)響起箫攀,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎幼衰,沒想到半個月后靴跛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡渡嚣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年梢睛,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片识椰。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡绝葡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出腹鹉,到底是詐尸還是另有隱情藏畅,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布功咒,位于F島的核電站愉阎,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏力奋。R本人自食惡果不足惜榜旦,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望景殷。 院中可真熱鬧溅呢,春花似錦、人聲如沸猿挚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽亭饵。三九已至休偶,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間辜羊,已是汗流浹背踏兜。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留八秃,地道東北人碱妆。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像昔驱,于是被迫代替她去往敵國和親疹尾。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,933評論 2 355

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