Tworzenie aplikacji obsługujących wielu użytkowników

Jeśli urządzenie obsługuje wielu użytkowników , jego aplikacje muszą być informowane o tych różnych użytkownikach.

Niektóre aplikacje muszą mieć pewne komponenty działające jako singletony i mogą akceptować żądania od dowolnego użytkownika. Obecnie z tej funkcji mogą korzystać tylko aplikacje systemowe.

Ten obiekt:

  • Chroni zasoby
  • Rozdziela jeden lub więcej zasobów współdzielonych pomiędzy użytkownikami
  • Zmniejsza obciążenie sieci dzięki zastosowaniu pojedynczego połączenia z serwerem

Poniższy diagram przedstawia przepływ uprawnień w przypadku wielu użytkowników.

Przepływ uprawnień wielu użytkowników

Rysunek 1. Uprawnienia wielu użytkowników

Włączanie komponentu singleton

Aby zidentyfikować aplikację jako pojedynczą, dodaj android:singleUser="true" do swojej usługi, odbiorcy lub dostawcy w manifeście systemu Android.

System utworzy instancję tego komponentu w procesie działającym tylko jako użytkownik 0. Wszelkie żądania połączenia się z tym dostawcą lub usługą albo transmisji do tego odbiornika od dowolnego użytkownika będą kierowane do procesu w użytkowniku 0. Jeśli jest to jedyny komponent Twojej aplikacji, uruchomiona zostanie tylko jedna instancja Twojej aplikacji.

Działania w Twoim pakiecie będą nadal uruchamiane w osobnym procesie dla każdego użytkownika, z UID mieszczącym się w zakresie UID dla tego użytkownika (np. 1010034).

Interakcja z użytkownikami

Ustaw uprawnienia

Te uprawnienia są wymagane

INTERACT_ACROSS_USERS (signature|system)
INTERACT_ACROSS_USERS_FULL (signature)

Stosuj interfejsy API

Użyj poniższych interfejsów API, aby informować aplikacje o wielu użytkownikach.

  1. Wyodrębnij uchwyt użytkownika z przychodzących wywołań Bindera:
    • int userHandle = UserHandle.getCallingUserId()
  2. Korzystaj z nowych, chronionych API, aby uruchamiać usługi, działania, transmisje na konkretnym użytkowniku:
    • Context.startActivityAsUser(Intent, UserHandle)
    • Context.bindServiceAsUser(Intent, …, UserHandle)
    • Context.sendBroadcastAsUser(Intent, … , UserHandle)
    • Context.startServiceAsUser(Intent, …, UserHandle)
    UserHandle może być jawnym użytkownikiem lub jednym ze specjalnych uchwytów: UserHandle.CURRENT lub UserHandle.ALL . CURRENT wskazuje użytkownika, który aktualnie znajduje się na pierwszym planie. Użyj opcji ALL , jeśli chcesz wysłać transmisję do wszystkich użytkowników.
  3. Komunikuj się z komponentami we własnej aplikacji: (INTERACT_ACROSS_USERS) Lub z komponentami w innych aplikacjach: (INTERACT_ACROSS_USERS_FULL)
  4. Może zaistnieć potrzeba utworzenia komponentów proxy uruchamianych w procesie użytkownika, które następnie uzyskują dostęp do komponentu singleUser w użytkowniku 0.
  5. Zapytaj użytkowników i ich uchwyty za pomocą nowej usługi systemu UserManager :
    • UserManager.getUsers()
    • UserManager.getUserInfo()
    • UserManager.supportsMultipleUsers()
    • UserManager.getUserSerialNumber(int userHandle) - nierecyklingowy numer odpowiadający uchwytowi użytkownika.
    • UserManager.getUserHandle(int serialNumber)
    • UserManager.getUserProfiles() - zwraca kolekcję profili własnych i zarządzanych, jeśli takie istnieją.
  6. Zarejestruj się, aby słuchać określonych lub wszystkich użytkowników i wywołań zwrotnych dzięki nowym interfejsom API w ContentObserver, PackageMonitor i BroadcastReceiver, które dostarczają dodatkowych informacji o tym, który użytkownik spowodował wywołanie zwrotne.

Usługi w wielu użytkownikach lub profilach

Nie wszystkie usługi muszą uruchamiać instancję w innym profilu użytkownika lub pracy. Jeśli usługa systemowa musi działać tylko jako użytkownik 0, wyłącz komponenty usługi, gdy działają one pod kontrolą innych użytkowników, aby pomóc w oszczędzaniu zasobów. Poniższy przykład pokazuje, jak możesz to zrobić w punktach wejścia usługi:

// 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);
}

W przykładzie można również użyć PackageManager.setApplicationEnabledSetting() w celu wyłączenia całej aplikacji.