如果裝置支援多位使用者,則其應用程式必須瞭解這些不同的使用者。
某些應用程式需要讓部分元件以單例模式執行,並可接受來自任何使用者的請求。目前只有系統應用程式可以使用這項功能。
這項設施:
- 節省資源
- 為多位使用者仲裁一或多個共用資源
- 使用單一伺服器連線可減少網路支出
請參閱下方圖表,瞭解多位使用者的權限流程。
圖 1. 多位使用者權限
啟用單例元件
如要將應用程式視為單例,請在 Android 資訊清單中將 android:singleUser="true"
新增至服務、接收器或提供者。
系統只會在以使用者 0 身分執行的程序中,以例項化方式建立該元件。任何使用者提出的連線至該供應商或服務,或向該接收端廣播的請求,都會轉送至使用者 0 的程序。如果這是應用程式中唯一的元件,則只會執行一個應用程式執行個體。
套件中的活動仍會針對每位使用者在個別程序中啟動,且 UID 會位於該使用者的 UID 範圍內 (例如 1010034)。
與使用者互動
設定權限
必須具備下列權限:
INTERACT_ACROSS_USERS (signature|system) INTERACT_ACROSS_USERS_FULL (signature)
使用 API
使用下列 API,讓應用程式瞭解多位使用者。
- 從傳入的 Binder 呼叫中擷取使用者句柄:
int userHandle = UserHandle.getCallingUserId()
- 使用新的受保護 API,針對特定使用者啟動服務、活動和廣播:
Context.startActivityAsUser(Intent, UserHandle)
Context.bindServiceAsUser(Intent, …, UserHandle)
Context.sendBroadcastAsUser(Intent, … , UserHandle)
Context.startServiceAsUser(Intent, …, UserHandle)
UserHandle
可以是明確的使用者,也可以是下列特殊句柄:UserHandle.CURRENT
或UserHandle.ALL
。CURRENT
表示目前在前景的使用者。如要向所有使用者發送廣播訊息,請使用ALL
。 - 與您應用程式中的元件通訊:
(INTERACT_ACROSS_USERS)
或與其他應用程式中的元件通訊:(INTERACT_ACROSS_USERS_FULL)
- 您可能需要建立在使用者程序中執行的代理元件,然後存取使用者 0 中的
singleUser
元件。 - 使用新的
UserManager
系統服務查詢使用者和其句柄:UserManager.getUsers()
UserManager.getUserInfo()
UserManager.supportsMultipleUsers()
UserManager.getUserSerialNumber(int userHandle)
:對應使用者帳號的未回收號碼。UserManager.getUserHandle(int serialNumber)
UserManager.getUserProfiles()
- 傳回自有和受管理的設定檔集合 (如果有的話)。
- 註冊以便監聽特定或所有使用者,以及在 ContentObserver、PackageMonitor、BroadcastReceiver 上使用新 API 的回呼,這些 API 可提供哪些使用者導致回呼的相關資訊。
多位使用者或設定檔中的服務
並非所有服務都需要在其他使用者或工作資料夾中執行例項。如果系統服務只需要以使用者 0 的身份執行,請在以其他使用者身分執行時停用服務的元件,以利保留資源。以下範例說明如何在服務的進入點執行這項操作:
// Add on all entry points such as boot_completed or other manifest-listed receivers and providers if (!UserManager.isSystemUser()) { // Disable the service ComponentName targetServiceName = new ComponentName(this, TargetService.class); context.getPackageManager().setComponentEnabledSetting( targetServiceName, COMPONENT_ENABLED_STATE_DISABLED, 0); }
這個範例也可以使用 PackageManager.setApplicationEnabledSetting()
停用整個應用程式。