1. 程式人生 > >Android 電量變化監聽

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。
電池的資訊,電壓,溫度,充電狀態等等,都是由BatteryService來提供的。電池的這些資訊是BatteryService通過廣播 主動把資料傳送給所關心的應用程式。
通過該intent的extra我們可以取得電池的很多資訊,比如電壓可以用如下的方式:voltage=intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, -1); BatteryManager類列出了該intent的extra所包含的資訊: 可能的值為:  : integer.the resource ID of a small status bar icon indicating the current battery state.
它是當前用於表示電池狀態的icon的資源id. 可能的值有: 0:表示電源是電池 int BATTERY_PLUGGED_AC :表示電源是AC charger.[應該是指充電器]。 : boolean.表示是否提供電池。有些手機在使用USB電源的情況下,即使拔出了電池,仍然可以正常工作。 可能的值為: 另外還有兩種intent專門用於表示電量低的情況 ACTION_BATTERY_LOW :表示當前電池電量低。 ACTION_BATTERY_OKAY:表示當前電池已經從電量低恢復為正常。

當你在更改後臺更新頻率來減少這些更新對電池壽命的影響時,檢查當前電量和充電狀態是一個好的開始。

電池壽命通過剩餘電量和充電狀態來影響應用更新的執行。當用交流電充電時,執行更新操作對裝置的影響是微不足道的,所以在大多數案例裡,你可以把更新頻率調到最快。如果裝置不在充電,降低更新頻率可以幫助延長電池壽命。

類似的,你可以檢查電池剩餘電量級別,在電量低時,應該降低更新頻率甚至停止更新。

注:此處的更新,指的是類似傳送心跳包的動作,或者定時更新內容。並非僅僅指更新應用版本。如果是使用者動作,比如翻頁重新整理,不需要根據電量和充電狀態處理。

判斷當前充電狀態

通過判斷當前充電狀態開始。BatteryManager會通過一個intent廣播所有電池和充電詳情,包含充電狀態。

因為這是一個sticky intent,你不需要註冊廣播接收器。簡單地通過呼叫 registerReceiver,像下面的程式碼段傳入一個null的接收器,當前電池狀態的intent就會返回。你也可以傳入一個真實的接收器物件,但我們暫時不會操作更新,所以這是沒必要的。

  1. IntentFilter ifilter =newIntentFilter(Intent.ACTION_BATTERY_CHANGED);
  2. Intent batteryStatus = context.registerReceiver(null, ifilter);
  3. //你可以讀到充電狀態,如果在充電,可以讀到是usb還是交流電
  4. // 是否在充電
  5. int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS,-1);
  6. boolean isCharging = status ==BatteryManager.BATTERY_STATUS_CHARGING ||
  7. status ==BatteryManager.BATTERY_STATUS_FULL;
  8. // 怎麼充
  9. int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED,-1);
  10. boolean usbCharge = chargePlug ==BatteryManager.BATTERY_PLUGGED_USB;
  11. boolean acCharge = chargePlug ==BatteryManager.BATTERY_PLUGGED_AC;

通常你應該在使用交流電充電時最大化後臺更新頻率,在使用usb充電時降低,不充電時更低。

監聽充電狀態的改變

充電狀態很容易改變(插入/拔出充電器),所以監聽充電狀態,更改重新整理頻率很重要。

充電狀態改變時,BatteryManager會發一個廣播。接收這些事件很重要,甚至在應用沒有執行的時候,因為可能你需要後臺開啟更新服務。所以,在Androidmanifest.xml裡註冊廣播接收器,加上兩個action:ACTION_POWER_CONNECTED 和ACTION_POWER_DISCONNECTED作為過濾。

  1. <receiverandroid:name=".PowerConnectionReceiver">
  2. <intent-filter>
  3. <actionandroid:name="android.intent.action.ACTION_POWER_CONNECTED"/>
  4. <actionandroid:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
  5. </intent-filter>
  6. </receiver>

在關聯的廣播接收器實現裡,你可以讀出當前充電狀態,方法跟上一步說的相同:

  1. publicclassPowerConnectionReceiverextendsBroadcastReceiver{
  2. @Override
  3. publicvoid onReceive(Context context,Intent intent){
  4. int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,-1);
  5. boolean isCharging = status ==BatteryManager.BATTERY_STATUS_CHARGING ||
  6. status ==BatteryManager.BATTERY_STATUS_FULL;
  7. int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED,-1);
  8. boolean usbCharge = chargePlug ==BatteryManager.BATTERY_PLUGGED_USB;
  9. boolean acCharge = chargePlug ==BatteryManager.BATTERY_PLUGGED_AC;
  10. }
  11. }

判斷當前剩餘電量

在某些案例裡,判斷當前剩餘電量同樣很有用。如果電量在某些水平之下,你可能會選擇降低後臺更新頻率。
你可以用下面的程式碼讀到電量:

  1. //當前剩餘電量
  2. int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL,-1);
  3. //電量最大值
  4. int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE,-1);
  5. //電量百分比
  6. float batteryPct = level /(float)scale;

監聽剩餘電量顯著改變

持續監聽電池狀態不容易,但你不必這麼做。
一般來說,持續監聽電池電量對電池的影響比app的正常行為還要大。所以,只監聽剩餘電量的指定級別的改變(進入或離開低電量狀態)是一個很好的實踐。
manifest裡宣告的接收器,會在進入或離開低電量狀態時觸發。

  1. <receiverandroid:name=".BatteryLevelReceiver">
  2. <intent-filter>
  3. <actionandroid:name="android.intent.action.ACTION_BATTERY_LOW"/>
  4. <actionandroid:name="android.intent.action.ACTION_BATTERY_OKAY"/>
  5. </intent-filter>
  6. </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" />