一、概述
DirectBootAware是Android 7.0引入的新特性,解決了在設備啟動的時候應用無法及時獲取重要信息的問題。它允許應用在設備啟動的時候就能夠訪問受保護的存儲。此外,在設備處於休眠狀態下,也可以使用DirectBootAware來保持設備保持響應。
二、如何使用DirectBootAware
在應用中使用DirectBootAware,我們需要做以下幾步:
1、創建BootCompletedReceiver。
public class BootCompletedReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { Intent serviceIntent = new Intent(context, MyService.class); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { context.startForegroundService(serviceIntent); } else { context.startService(serviceIntent); } } } }
在onReceive()方法里,我們啟動自己的服務。注意,如果系統版本號大於等於26,也就是Android 8.0,我們需要使用startForegroundService()方法來啟動服務。
2、創建一個繼承自IntentService的服務。
public class MyService extends IntentService { public MyService() { super("MyService"); } @Override protected void onHandleIntent(Intent intent) { Log.d("MyService", "Service started"); } }
onHandleIntent()是IntentService中的回調方法,它在服務被啟動的時候被調用。現在,我們已經可以使用DirectBootAware來啟動服務了。
3、使服務支持DirectBootAware。
public class MyService extends IntentService implements DirectBootAware { public MyService() { super("MyService"); } @Override protected void onHandleIntent(Intent intent) { Log.d("MyService", "Service started"); } @Override public void onCreate() { super.onCreate(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { startForeground(1, new Notification()); } } @Override public void onEnabled(Context context) { Log.d("MyService", "DirectBootAware onEnabled"); } @Override public void onDisabled(Context context) { Log.d("MyService", "DirectBootAware onDisabled"); } }
我們實現了DirectBootAware接口,並重載了它的onEnabled()和onDisabled()方法,在Service被啟用和禁用的時候,這兩個方法就會被調用。此外,我們也重載了onCreate()方法,在Android 7.1及以上的版本中需要調用startForeground()方法,這樣可以在系統啟動之後讓服務一直運行。
三、DirectBootAware原理
1、異步消息模式
在Android 7.0中,系統啟動完成後,首先會創建一個名為com.android.server.SystemServer的進程,它是系統服務的管理者。SystemServer會啟動一個名為SystemServiceManager的服務來管理所有的系統服務,其中包含ActivityManagerService、PackageManagerService、WindowManagerService等等。SystemServiceManager會在SystemServer的一個子線程中對這些服務進行初始化,最終下載並運行對應的組件。
2、初始化DirectBootManagerService
public class SystemServiceManager { private SystemServiceManager() { ... registerService(Context.DIRECTBOOT_SERVICE, new DirectBootManagerService(context)); } }
在SystemServiceManager的初始化過程中,我們可以看到系統服務DirectBootManagerService的註冊過程。直接通過registerService()方法來進行註冊,這樣,就會有DirectBootManagerService這個系統服務了。
3、DirectBootManagerService實現原理
public class DirectBootManagerService extends IDirectBootService.Stub { private final Context mContext; private final KeyguardManager mKeyguardManager; private final IActivityManager mActivityManager; private final Object mLock = new Object(); public DirectBootManagerService(Context context) { mContext = context; mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); mActivityManager = ActivityManagerNative.getDefault(); } @Override public void startActivityAndShowWhenLocked(Intent intent) { synchronized (mLock) { ... mActivityManager.startActivityFromRecents(taskId, options.toBundle()); ... } } }
DirectBootManagerService在啟動的時候,會創建KeyguardManager、ActivityManager實例用來控制設備的狀態和管理應用程序的生命周期,同時也會創建一個鎖對象。
4、啟動應用的過程
當直接啟動應用時,會調用Intent.ACTION_MAIN和category.LAUNCHER兩個標誌來啟動應用程序:
Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); intent.setComponent(new ComponentName(this, MainActivity.class)); startActivity(intent);
上述代碼會觸發ActivityManagerService進行處理。ActivityManagerService會先檢查Launcher是否可以在鎖屏狀態下喚醒,如果可以的話就會進行喚醒並開啟Activity。否則,就會記錄下來一個任務棧,並在解鎖後按順序依次開啟。
四、小結
總之,DirectBootAware是一個很有用的特性,使用該特性可以在設備啟動和休眠狀態下維持設備的響應和保護。通過理解DirectBootManagerService的實現原理,我們不僅可以更好地使用該特性,還可以在實際工作中針對特定問題進行更好的優化。
原創文章,作者:EYLGX,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/351724.html