【Android 電量優化】電量優化 ( 充電狀態獲取 | 主動獲取充電狀態 | 廣播接受者監聽充電狀態 | 被動獲取充電狀態 | 註冊空廣播接受者獲取歷史廣播 )



參考 Google 官方文檔 : 優化電池續航時間





一、獲取充電狀態



在應用中執行某些操作 , 如軟件雲端備份 , 從服務器端獲取最新版本號 , 從服務器端緩存最新軟件安裝包 , 固件版本 , 等操作 , 最好都在充電狀態 , 那麼如何獲取充電狀態呢 , 這裏給出兩個方式 , 分別是主動獲取充電狀態 , 被動獲取充電狀態 ;





二、被動獲取充電狀態



1 . 被動獲取充電狀態 :


① 監聽方法 : 註冊廣播接受者 , 監聽充電狀態變化 ;

② 場景描述 : 當用戶插拔數據線時 , 充電狀態發生變化時 , 系統發出對應的廣播 , 使用廣播接受者接收這些廣播 ;

③ 數據線插入廣播 : 當數據線插入時 , 系統會發出 Intent.ACTION_POWER_CONNECTED 廣播 ;

④ 數據線拔出廣播 : 當數據線拔出時 , 系統會發出 Intent.ACTION_POWER_DISCONNECTED 廣播 ;



2 . 廣播接受者代碼示例 :

package kim.hsl.bp;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.util.Log;

/**
 * 被動獲取充電狀態
 * 充電狀態發生變化時 , 系統發出的廣播 , 使用廣播接受者接收這些廣播
 */
public class BatteryReceiver extends BroadcastReceiver {
    public static final String TAG = "BatteryReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        // 獲取廣播事件
        String action = intent.getAction();

        if(TextUtils.equals(Intent.ACTION_POWER_CONNECTED, action)){
            // 數據線插入
            Log.i(TAG, "數據線插入");
        }else if(TextUtils.equals(Intent.ACTION_POWER_DISCONNECTED, action)){
            // 數據先拔出
            Log.i(TAG, "數據線拔出");
        }
    }
}


3 . AndroidManifest.xml 註冊廣播接受者代碼示例 :

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="kim.hsl.bp">

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <receiver android:name=".BatteryReceiver" >
            <intent-filter>
                <!-- 充電線插上 -->
                <action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
                <!-- 充電線拔出 -->
                <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
            </intent-filter>
        </receiver>
        
    </application>

</manifest>




三、主動獲取充電狀態



1 . 主動獲取充電狀態流程 :


① 創建 IntentFilter : 創建 IntentFilter , 併爲其設置 Intent.ACTION_BATTERY_CHANGED 意圖 ;

IntentFilter intentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);

② 註冊廣播接受者 : 調用 Context 對象的 registerReceiver 方法 , 設置 BroadcastReceiver receiver 廣播接收者參數爲空 , IntentFilter 就是上述創建的意圖過濾器 ;

Intent intent = context.registerReceiver(null, intentFilter);

③ 獲取充電狀態 : 從註冊廣播返回的 Intent 意圖中獲取對應的充電狀態 ;

int batteryChargeState = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);

④ 對比充電狀態 : 將上述從 Intent.ACTION_BATTERY_CHANGED 匹配的意圖中獲取 BatteryManager.EXTRA_PLUGGED 對應的值 , 與以下 33 個值進行對比 , 如果一致 , 說明當前是此種充電狀態 ;

  • BatteryManager.BATTERY_PLUGGED_AC : 交流電充電 ;
  • BatteryManager.BATTERY_PLUGGED_USB : USB 接口充電 ;
  • BatteryManager.BATTERY_PLUGGED_WIRELESS : 無線充電 ;


2 . 廣播接受者註冊用法 :


① 註冊廣播接收者 : registerReceiver 方法主要作用是在主線程註冊一個廣播接收者 BroadcastReceiver 運行 ;

② 廣播接收者調用 : 當註冊的 IntentFilter 中的 action 匹配到相應的廣播時 , BroadcastReceiver 會被在主線程調用 ;

③ 歷史廣播保存 : 系統發送完畢的廣播 , 會被保存下來 , 在後續註冊時發送 ;

④ 廣播複用機制 : 一旦有廣播接收者註冊廣播 , 如果之前發送完畢的廣播與本次註冊的 IntentFilter 意圖的 Action 匹配 , 次函數就會返回一個 Intent , 這個 Intent 就是之前已經發送的廣播 ;

⑤ 如 : 本次註冊的 IntentFilter 中包含 Intent.ACTION_BATTERY_CHANGED , 如果使用如下方法 context.registerReceiver(null, intentFilter) 註冊空廣播接收者 , 返回值就是之前發送過的 Intent.ACTION_BATTERY_CHANGED 廣播 , 可以從該廣播中獲取對應的充電狀態變化數據 ;

⑥ 註冊多個意圖 : 如果在 IntentFilter 中註冊多個意圖 , 廣播接收者如果不爲空 , 則會處理每一個意圖 , 但是返回值只能返回一個意圖 , 返回哪個由系統決定 ;


廣播接收者註冊方法有兩種功能 , 一個是註冊廣播接收者 , 另一個是獲取之前已經發送的相同 Action 的歷史廣播 ;

這裏使用的註冊廣播接收者的獲取歷史廣播的功能 ;



3 . 代碼示例 :

package kim.hsl.bp;

import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;

public class BatteryUtils {

    /**
     * 主動獲取當前電池是否在充電 , 即數據線是否插在手機上
     * @return
     */
    public static boolean isBatteryCharging(Context context){
        boolean isBatteryCharging = false;
        // 主動發送包含是否正在充電狀態的廣播 , 該廣播會持續發送
        IntentFilter intentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        // 註冊廣播接受者
        Intent intent = context.registerReceiver(null, intentFilter);

        // 獲取充電狀態
        int batteryChargeState = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);

        // 判定是否是 AC 交流電充電
        boolean isAc = batteryChargeState == BatteryManager.BATTERY_PLUGGED_AC;
        // 判斷是否是 USB 充電
        boolean isUsb = batteryChargeState == BatteryManager.BATTERY_PLUGGED_USB;
        // 判斷是否是 無線充電
        boolean isWireless = batteryChargeState == BatteryManager.BATTERY_PLUGGED_WIRELESS;

        // 如何上述任意一種爲 true , 說明當前正在充電
        isBatteryCharging = isAc || isUsb || isWireless;

        return isBatteryCharging;
    }

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章