APP開發實戰167-開機自啓動的功能設計

30.15 開機自啓動的功能設計

30.15.1 普通模式

對於Android7.0之前的系統,如果設計APP在系統啓動之後自啓動,只需在APP添加處理ACTION_BOOT_COMPLETED廣播消息的代碼即可。

30.15.2直接啓動模式

從Android7.0開始,系統有了一種新的啓動模式“直接啓動”模式,針對這種模式需要做特別處理。

    當設備已開機但用戶尚未解鎖設備時,Android N 將在安全的“直接啓動”模式下運行。 爲支持此操作,系統爲數據提供兩個存儲位置:

    憑據加密存儲,這是默認存儲位置,僅在用戶解鎖設備後可用。

    設備加密存儲,該存儲位置在“直接啓動”模式下和用戶解鎖設備後均可使用。

    默認情況下,應用不會在“直接啓動”模式下運行。如果應用需要在“直接啓動”模式下進行操作,可以註冊在此模式期間應運行的應用組件。 對於需要在“直接啓動”模式下運行的應用,常見的一些用例包括:

    已安排通知的應用,如鬧鐘應用。

    提供重要用戶通知的應用,如短信應用。

    提供無障礙服務的應用,如 Talkback。

    如果應用在“直接啓動”模式下運行時需要訪問數據,則使用設備加密存儲。 設備加密存儲包含使用密鑰加密的數據,僅在設備已成功執行驗證啓動後密鑰纔可用。

   對於應使用與用戶憑據(如 PIN 或密碼)關聯的密鑰加密的數據,請使用憑據加密存儲。憑據加密存儲僅在用戶已成功解鎖設備後可用,直到用戶再次重啓設備。 如果用戶在解鎖設備後啓用鎖定屏幕,則不會鎖定憑據加密存儲。

30.15.3 請求在直接啓動時運行

    應用必須先向系統註冊其組件,然後才能在“直接啓動”模式下運行或訪問設備加密存儲。應用通過將組件標記爲“加密感知”來註冊系統。 若要將組件標記爲加密感知,需在清單中將 android:directBootAware 屬性設爲 true。

    當設備重啓後,加密感知組件可以註冊接收來自系統的 LOCKED_BOOT_COMPLETED 廣播消息。 此時設備加密存儲可用,APP組件可以在“直接啓動”模式下執行需要運行的任務,例如觸發已設定的鬧鈴。

    以下代碼段展示如何將 BroadcastReceiver 註冊爲加密感知並在應用清單中爲 LOCKED_BOOT_COMPLETED 添加 Intent 過濾器:

<receiver
  android:directBootAware="true" >
  ...
  <intent-filter>
    <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED"/>
  </intent-filter>
</receiver>

在用戶解鎖設備後,所有組件均可訪問設備加密存儲以及憑據加密存儲。

30.15.4 訪問設備加密存儲

    要訪問設備加密存儲,需通過調用 Context.createDeviceProtectedStorageContext() 創建另一個 Context 實例。使用此上下文執行的所有存儲 API 調用均訪問設備加密存儲。 以下示例訪問設備加密存儲並打開現有應用數據文件:

Context directBootContext = appContext.createDeviceProtectedStorageContext();
// Access appDataFilename that lives in device encrypted storage
FileInputStream inStream = directBootContext.openFileInput(appDataFilename);
// Use inStream to read content...

    僅針對在“直接啓動”模式下必須可訪問的信息使用設備加密存儲。請勿將設備加密存儲用作通用加密存儲。對於專有用戶信息,或在“直接啓動”模式下不需要的加密數據,請使用憑據加密存儲。

30.15.5 接收用戶解鎖通知

    重啓後一旦用戶解鎖了設備,應用即可切換至訪問憑據加密存儲,並使用依賴用戶憑據的常規系統服務。

    爲了在重啓後用戶解鎖設備時收到通知,請從一個正在運行的組件註冊 BroadcastReceiver 以偵聽 ACTION_USER_UNLOCKED 消息。 或者,可以接收現有 ACTION_BOOT_COMPLETED 消息,該消息現在表明設備已啓動,且用戶已解鎖設備。

    可以通過調用 UserManager.isUserUnlocked() 直接查詢用戶是否已解鎖設備。

30.15.6 示例代碼

    在AndroidManifest.xml文件中註冊廣播接收器:

<receiver android:name=".BootBroadcastReceiver"
    android:directBootAware="true">
    <!-- Listening the BOOT_COMPLETEDaction for legacy pre-N devices -->
    <intent-filter>
        <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED"/>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>

廣播接收器代碼:

public class BootBroadcastReceiver extends BroadcastReceiver {

    private static final String TAG= "BootBroadcastReceiver";

    @Override
   
public void onReceive(Contextcontext, Intent intent) {
        boolean bootCompleted;
        String action =intent.getAction();
        Log.i(TAG, "Receivedaction: " + action + ", user unlocked: " + UserManagerCompat
                .isUserUnlocked(context));
        if (BuildCompat.isAtLeastN()){
            bootCompleted= Intent.ACTION_LOCKED_BOOT_COMPLETED.equals(action);
        } else {
            bootCompleted= Intent.ACTION_BOOT_COMPLETED.equals(action);
        }
    }
}

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