Android 電量變化監聽
This is a sticky broadcast containing the charging state, level, and other information about the battery. See for documentation on the contents of the Intent.
This is a protected intent that can only be sent by the system.
Constant Value: "android.intent.action.BATTERY_CHANGED"如果我們註冊了對的監聽,那麼我們馬上會收到一個Action為Intent.ACTION_BATTERY_CHANGED的intent,之後只要我們沒有取消監聽,一定電池傳送變化,我們也會收到這樣的intent。
當你在更改後臺更新頻率來減少這些更新對電池壽命的影響時,檢查當前電量和充電狀態是一個好的開始。
電池壽命通過剩餘電量和充電狀態來影響應用更新的執行。當用交流電充電時,執行更新操作對裝置的影響是微不足道的,所以在大多數案例裡,你可以把更新頻率調到最快。如果裝置不在充電,降低更新頻率可以幫助延長電池壽命。
類似的,你可以檢查電池剩餘電量級別,在電量低時,應該降低更新頻率甚至停止更新。
注:此處的更新,指的是類似傳送心跳包的動作,或者定時更新內容。並非僅僅指更新應用版本。如果是使用者動作,比如翻頁重新整理,不需要根據電量和充電狀態處理。
判斷當前充電狀態
通過判斷當前充電狀態開始。BatteryManager會通過一個intent廣播所有電池和充電詳情,包含充電狀態。
因為這是一個sticky intent,你不需要註冊廣播接收器。簡單地通過呼叫 registerReceiver,像下面的程式碼段傳入一個null的接收器,當前電池狀態的intent就會返回。你也可以傳入一個真實的接收器物件,但我們暫時不會操作更新,所以這是沒必要的。
- IntentFilter ifilter =newIntentFilter(Intent.ACTION_BATTERY_CHANGED);
- Intent batteryStatus = context.registerReceiver(null, ifilter);
- //你可以讀到充電狀態,如果在充電,可以讀到是usb還是交流電
- // 是否在充電
- int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS,-1);
- boolean isCharging = status ==BatteryManager.BATTERY_STATUS_CHARGING ||
- status ==BatteryManager.BATTERY_STATUS_FULL;
- // 怎麼充
- int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED,-1);
- boolean usbCharge = chargePlug ==BatteryManager.BATTERY_PLUGGED_USB;
- boolean acCharge = chargePlug ==BatteryManager.BATTERY_PLUGGED_AC;
通常你應該在使用交流電充電時最大化後臺更新頻率,在使用usb充電時降低,不充電時更低。
監聽充電狀態的改變
充電狀態很容易改變(插入/拔出充電器),所以監聽充電狀態,更改重新整理頻率很重要。
充電狀態改變時,BatteryManager會發一個廣播。接收這些事件很重要,甚至在應用沒有執行的時候,因為可能你需要後臺開啟更新服務。所以,在Androidmanifest.xml裡註冊廣播接收器,加上兩個action:ACTION_POWER_CONNECTED 和ACTION_POWER_DISCONNECTED作為過濾。
- <receiverandroid:name=".PowerConnectionReceiver">
- <intent-filter>
- <actionandroid:name="android.intent.action.ACTION_POWER_CONNECTED"/>
- <actionandroid:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
- </intent-filter>
- </receiver>
在關聯的廣播接收器實現裡,你可以讀出當前充電狀態,方法跟上一步說的相同:
- publicclassPowerConnectionReceiverextendsBroadcastReceiver{
- @Override
- publicvoid 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;
- int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED,-1);
- boolean usbCharge = chargePlug ==BatteryManager.BATTERY_PLUGGED_USB;
- boolean acCharge = chargePlug ==BatteryManager.BATTERY_PLUGGED_AC;
- }
- }
判斷當前剩餘電量
在某些案例裡,判斷當前剩餘電量同樣很有用。如果電量在某些水平之下,你可能會選擇降低後臺更新頻率。
你可以用下面的程式碼讀到電量:
- //當前剩餘電量
- int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL,-1);
- //電量最大值
- int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE,-1);
- //電量百分比
- float batteryPct = level /(float)scale;
監聽剩餘電量顯著改變
持續監聽電池狀態不容易,但你不必這麼做。
一般來說,持續監聽電池電量對電池的影響比app的正常行為還要大。所以,只監聽剩餘電量的指定級別的改變(進入或離開低電量狀態)是一個很好的實踐。
manifest裡宣告的接收器,會在進入或離開低電量狀態時觸發。
- <receiverandroid:name=".BatteryLevelReceiver">
- <intent-filter>
- <actionandroid:name="android.intent.action.ACTION_BATTERY_LOW"/>
- <actionandroid:name="android.intent.action.ACTION_BATTERY_OKAY"/>
- </intent-filter>
- </receiver>
剩餘電量嚴重不足時,最好禁用所有後臺更新。在你可以使用手機之前就關機了,這種情況下,如果重新整理資料並不重要。
在很多情況下,裝置是是插入到底座裡充電的(好吧,反正我沒見幾個人額外花錢買底座的,可能國外較多)。下節講怎麼判斷當前底座狀態和監聽插入底座時改變。
<span style="font-size:32px;"> </span><span style="font-size:18px;"> int status = intent.getIntExtra("status", 0); //電池狀態,充電、放電、充滿、未充電
int health = intent.getIntExtra("health", 0); <span style="white-space:pre"> </span>//電池的健康狀態
boolean present = intent.getBooleanExtra("present", false);
int level = intent.getIntExtra("level", 0); //獲取當前電量
int scale = intent.getIntExtra("scale", 0); //獲取總電量
int icon_small = intent.getIntExtra("icon-small", 0);
int plugged = intent.getIntExtra("plugged", 0);
int voltage = intent.getIntExtra("voltage", 0); // 電池伏數
int temperature = intent.getIntExtra("temperature", 0); // 電池溫度
String technology = intent.getStringExtra("technology");
//電池狀態
switch (intent.getIntExtra("status",BatteryManager.BATTERY_STATUS_UNKNOWN)) {
{
case BatteryManager.BATTERY_STATUS_CHARGING:
BatteryStatus = "充電狀態";
break;
case BatteryManager.BATTERY_STATUS_DISCHARGING:
BatteryStatus = "放電狀態";
break;
case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
BatteryStatus = "未充電";
break;
case BatteryManager.BATTERY_STATUS_FULL:
BatteryStatus = "充滿電";
break;
case BatteryManager.BATTERY_STATUS_UNKNOWN:
BatteryStatus = "未知道狀態";
break;
}
switch (intent.getIntExtra("plugged", BatteryManager.BATTERY_PLUGGED_AC))
{
case BatteryManager.BATTERY_PLUGGED_AC:
BatteryStatus2 = "AC充電";
break;
case BatteryManager.BATTERY_PLUGGED_USB:
BatteryStatus2 = "USB充電";
break;
}
switch (intent.getIntExtra("health",
BatteryManager.BATTERY_HEALTH_UNKNOWN))
{
case BatteryManager.BATTERY_HEALTH_UNKNOWN:
BatteryTemp = "未知錯誤";
break;
case BatteryManager.BATTERY_HEALTH_GOOD:
BatteryTemp = "狀態良好";
break;
case BatteryManager.BATTERY_HEALTH_DEAD:
BatteryTemp = "電池沒有電";
break;
case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
BatteryTemp = "電池電壓過高";
break;
case BatteryManager.BATTERY_HEALTH_OVERHEAT:
BatteryTemp = "電池過熱";
break;
}
</span>
簡單例子
<RelativeLayout
android:id="@+id/play_rl_power_info"
android:layout_width="34.0dip"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true" >
<ImageView
android:id="@+id/play_iv_battery"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="2.0dip"
android:layout_marginTop="1.0dip"
android:layout_centerHorizontal="true"
android:visibility="visible" />
<TextView
android:id="@+id/play_tv_cur_time"
android:layout_width="34.0dip"
android:layout_height="wrap_content"
android:layout_below="@+id/play_iv_battery"
android:layout_marginRight="0.0dip"
android:layout_marginTop="2.0dip"
android:layout_centerHorizontal="true"
android:textColor="@color/background_white_50"
android:textSize="10.0sp"
android:gravity="center"
android:text="23:54"
android:textStyle="bold" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/play_report_speed_layout"
android:layout_width="wrap_content"
android:layout_height="23.0dip"
android:layout_centerVertical="true"
android:layout_marginRight="24.0dip"
android:layout_toLeftOf="@+id/play_rl_power_info" >
<TextView
android:id="@+id/play_report_speed_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/background_white_50"
android:gravity="center" />
</RelativeLayout>
<ImageButton
android:id="@+id/btn_back_land"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:background="@null"
android:padding="15.0dip"
android:src="@drawable/detail_back_ico_selector" />
<LinearLayout
android:id="@+id/play_title_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="10.0dip"
android:layout_marginRight="10.0dip"
android:layout_toLeftOf="@+id/play_report_error_layout"
android:layout_toRightOf="@+id/btn_back_land"
android:gravity="center_vertical"
android:orientation="vertical" >
<TextView
android:id="@+id/play_title_info_name_land"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:gravity="left"
android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true"
android:textColor="#ffffffff"
android:textSize="20.0sp" />
</LinearLayout>
</RelativeLayout>
在上面的資原始檔中只需要關注play_iv_battery這個ImageView
stat_sys_battery_charge.xml
<?xml version="1.0" encoding="utf-8"?>
<level-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:maxLevel="14">
<animation-list android:oneshot="false"
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:duration="2000" android:drawable="@drawable/stat_sys_battery_charge_anim0" />
<item android:duration="1000" android:drawable="@drawable/stat_sys_battery_charge_anim1" />
<item android:duration="1000" android:drawable="@drawable/stat_sys_battery_charge_anim2" />
<item android:duration="1000" android:drawable="@drawable/stat_sys_battery_charge_anim3" />
<item android:duration="1000" android:drawable="@drawable/stat_sys_battery_charge_anim4" />
<item android:duration="1000" android:drawable="@drawable/stat_sys_battery_charge_anim5" />
</animation-list>
</item>
<item android:maxLevel="29">
<animation-list android:oneshot="false"
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:duration="2000" android:drawable="@drawable/stat_sys_battery_charge_anim1" />
<item android:duration="1000" android:drawable="@drawable/stat_sys_battery_charge_anim2" />
<item android:duration="1000" android:drawable="@drawable/stat_sys_battery_charge_anim3" />
<item android:duration="1000" android:drawable="@drawable/stat_sys_battery_charge_anim4" />
<item android:duration="1000" android:drawable="@drawable/stat_sys_battery_charge_anim5" />
</animation-list>
</item>
<item android:maxLevel="49">
<animation-list android:oneshot="false"
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:duration="2000" android:drawable="@drawable/stat_sys_battery_charge_anim2" />
<item android:duration="1000" android:drawable="@drawable/stat_sys_battery_charge_anim3" />
<item android:duration="1000" android:drawable="@drawable/stat_sys_battery_charge_anim4" />
<item android:duration="1000" android:drawable="@drawable/stat_sys_battery_charge_anim5" />
</animation-list>
</item>
<item android:maxLevel="69">
<animation-list android:oneshot="false"
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:duration="2000" android:drawable="@drawable/stat_sys_battery_charge_anim3" />
<item android:duration="1000" android:drawable="@drawable/stat_sys_battery_charge_anim4" />
<item android:duration="1000" android:drawable="@drawable/stat_sys_battery_charge_anim5" />
</animation-list>
</item>
<item android:maxLevel="89">
<animation-list android:oneshot="false"
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:duration="2000" android:drawable="@drawable/stat_sys_battery_charge_anim4" />
<item android:duration="1000" android:drawable="@drawable/stat_sys_battery_charge_anim5" />
</animation-list>
</item>
<item android:drawable="@drawable/stat_sys_battery_charge_anim5" android:maxLevel="101" />
</level-list>
stat_sys_battery.xml
<?xml version="1.0" encoding="utf-8"?>
<level-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/stat_sys_battery_0" android:maxLevel="4" />
<item android:drawable="@drawable/stat_sys_battery_10" android:maxLevel="14" />
<item android:drawable="@drawable/stat_sys_battery_20" android:maxLevel="29" />
<item android:drawable="@drawable/stat_sys_battery_40" android:maxLevel="49" />
<item android:drawable="@drawable/stat_sys_battery_60" android:maxLevel="69" />
<item android:drawable="@drawable/stat_sys_battery_80" android:maxLevel="89" />