Jeśli urządzenie obsługuje wielu użytkowników, aplikacje muszą być informowane o tych różnych użytkownikach.
Niektóre aplikacje muszą mieć komponenty działające jako pojedyncze instancje i mogące przyjmować żądania od dowolnego użytkownika. Obecnie z tej funkcji mogą korzystać tylko aplikacje systemowe.
Ta usługa:
- Oszczędzanie zasobów
- Rozstrzyga spory dotyczące co najmniej 1 zasobu udostępnionego przez różnych użytkowników.
- Zmniejsza narzut sieciowy dzięki użyciu jednego połączenia z serwerem
Na diagramie poniżej pokazano proces przyznawania uprawnień wielu użytkownikom.
Rysunek 1. Uprawnienia wielu użytkowników
Włączanie komponentu pojedynczego
Aby zidentyfikować aplikację jako singleton, dodaj android:singleUser="true"
do usługi, odbiornika lub dostawcy w pliku manifestu Androida.
System tworzy instancję tego komponentu w procesie działającym jako użytkownik 0. Wszelkie żądania połączenia z tym dostawcą lub usługą lub transmisji do tego odbiornika od dowolnego użytkownika są kierowane do procesu w użytkowniku 0. Jeśli jest to jedyny komponent w aplikacji, działa tylko jedna jej instancja.
Aktywności w Twoim pakiecie są nadal uruchamiane w ramach osobnego procesu dla każdego użytkownika, a identyfikator UID należy do zakresu identyfikatorów UID tego użytkownika (np. 1010034).
Interakcje z użytkownikami
Ustaw uprawnienia
Wymagane są te uprawnienia:
INTERACT_ACROSS_USERS (signature|system) INTERACT_ACROSS_USERS_FULL (signature)
Używanie interfejsów API
Aby aplikacje mogły wykrywać wielu użytkowników, użyj tych interfejsów API:
- Wyodrębnij identyfikator użytkownika z przychodzących połączeń z Binderem:
int userHandle = UserHandle.getCallingUserId()
- Używanie nowych, chronionych interfejsów API do uruchamiania usług, działań i transmisji dla konkretnego użytkownika:
Context.startActivityAsUser(Intent, UserHandle)
Context.bindServiceAsUser(Intent, …, UserHandle)
Context.sendBroadcastAsUser(Intent, … , UserHandle)
Context.startServiceAsUser(Intent, …, UserHandle)
UserHandle
może być konkretnym użytkownikiem lub jednym z specjalnych nicków:UserHandle.CURRENT
lubUserHandle.ALL
.CURRENT
wskazuje użytkownika, który jest obecnie na pierwszym planie. UżyjALL
, jeśli chcesz wysłać transmisję do wszystkich użytkowników. - Komunikacja z komponentami w Twojej aplikacji:
(INTERACT_ACROSS_USERS)
Komunikacja z komponentami w innych aplikacjach:(INTERACT_ACROSS_USERS_FULL)
- Może być konieczne utworzenie komponentów zastępczych, które działają w procesie użytkownika, a następnie uzyskują dostęp do komponentu
singleUser
w użytkowniku 0. - Wysyłaj zapytania do użytkowników i ich nicków za pomocą nowej usługi systemowej
UserManager
:UserManager.getUsers()
UserManager.getUserInfo()
UserManager.supportsMultipleUsers()
UserManager.getUserSerialNumber(int userHandle)
– niewykorzystany numer, który odpowiada nazwie użytkownika.UserManager.getUserHandle(int serialNumber)
UserManager.getUserProfiles()
– zwraca kolekcję profili własnych i zarządzanych (jeśli istnieją).
- Zarejestruj się, aby odbierać powiadomienia o działaniach określonych lub wszystkich użytkowników oraz wywołaniach zwrotnych za pomocą nowych interfejsów API w ContentObserver, PackageMonitor i BroadcastReceiver, które dostarczają dodatkowych informacji o tym, który użytkownik wywołał wywołanie zwrotne.
Usługi dla wielu użytkowników lub profili
Nie wszystkie usługi muszą działać w ramach instancji na innym profilu użytkownika lub profilu służbowym. Jeśli usługa systemowa musi działać tylko jako użytkownik 0, wyłącz jej komponenty, gdy działają pod innymi kontami użytkowników, aby oszczędzać zasoby. Poniższy przykład pokazuje, jak 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 tym przykładzie można też użyć PackageManager.setApplicationEnabledSetting()
, aby wyłączyć całą aplikację.