Każda aplikacja na Androida działa w piaskownicy z ograniczonym dostępem. Jeśli Twoja aplikacja musi korzystać z zasobów lub informacji spoza własnej piaskownicy, możesz zadeklarować uprawnienie w czasie działania i skonfigurować prośbę o uprawnienia, która zapewni ten dostęp. Te czynności są częścią procesu korzystania z uprawnień.
inny proces.Jeśli zadeklarujesz niebezpieczne uprawnienia, a aplikacja zostanie zainstalowana na urządzeniu z Androidem 6.0 (poziom interfejsu API 23) lub nowszym, musisz poprosić o niebezpieczne uprawnienia w czasie działania aplikacji, wykonując czynności opisane w tym przewodniku.
Jeśli nie zadeklarujesz żadnych uprawnień niebezpiecznych lub jeśli Twoja aplikacja jest zainstalowana na urządzeniu z Androidem 5.1 (API na poziomie 22) lub starszym, uprawnienia zostaną przyznane automatycznie i nie musisz wykonywać żadnych pozostałych czynności opisanych na tej stronie.
Podstawowe zasady
Podstawowe zasady przesyłania próśb o uprawnienia w czasie działania są następujące:
- Proś o uprawnienia w kontekście, gdy użytkownik zacznie korzystać z funkcji, która ich wymaga.
- Nie blokuj użytkownika. Zawsze udostępniaj opcję anulowania interfejsu edukacyjnego, np. wzorca, który wyjaśnia powody, dla których prosisz o przyznanie uprawnień.
- Jeśli użytkownik nie wyrazi zgody na uprawnienia wymagane przez daną funkcję lub wycofa udzieloną zgodę, przeprowadź łagodną degradację aplikacji, aby użytkownik mógł nadal z niej korzystać, być może przez wyłączenie funkcji, która wymaga tych uprawnień.
- Nie zakładaj żadnego zachowania systemu. Nie zakładaj na przykład, że uprawnienia pojawiają się w tej samej grupie uprawnień. Grupa uprawnień pomaga systemowi zminimalizować liczbę okien dialogowych, które są wyświetlane użytkownikowi, gdy aplikacja prosi o przyznanie ściśle powiązanych uprawnień.
Proces wysyłania prośby o uprawnienia
Zanim zadeklarujesz uprawnienia w czasie działania i poprosisz o nie w aplikacji, zastanów się, czy jest to konieczne. W aplikacji możesz realizować wiele przypadków użycia, np. robić zdjęcia, wstrzymywać odtwarzanie multimediów i wyświetlać trafne reklamy, bez konieczności deklarowania jakichkolwiek uprawnień.
Jeśli stwierdzisz, że aplikacja musi deklarować uprawnienia i o nie prosić w czasie działania, wykonaj te czynności:
- W pliku manifestu aplikacji zadeklaruj uprawnienia, o które aplikacja może poprosić.
- Zaprojektuj interfejs użytkownika aplikacji tak, aby konkretne działania w niej były powiązane z określonymi uprawnieniami w czasie działania. Informuj użytkowników, które działania mogą wymagać przyznania aplikacji uprawnień dostępu do prywatnych danych użytkownika.
- Poczekaj, aż użytkownik wywoła w aplikacji zadanie lub działanie, które wymaga dostępu do określonych prywatnych danych użytkownika. W tym momencie aplikacja może poprosić o uprawnienia wymagane do uzyskania dostępu do tych danych.
Sprawdź, czy użytkownik przyznał już uprawnienia wymagane przez aplikację. Jeśli tak, aplikacja może uzyskać dostęp do prywatnych danych użytkownika. Jeśli nie, przejdź do następnego.
Za każdym razem, gdy wykonujesz operację wymagającą uprawnień, musisz sprawdzić, czy je masz.
Sprawdź, czy aplikacja powinna wyświetlać użytkownikowi uzasadnienie, w którym wyjaśnia, dlaczego potrzebuje przyznania określonego uprawnienia w czasie działania. Jeśli system uzna, że aplikacja nie powinna wyświetlać uzasadnienia, przejdź bezpośrednio do następnego kroku, nie wyświetlając elementu interfejsu.
Jeśli system uzna, że aplikacja powinna wyświetlić uzasadnienie, pokaż je użytkownikowi w elemencie interfejsu. W tym uzasadnieniu wyraźnie wyjaśnij, do jakich danych aplikacja próbuje uzyskać dostęp i jakie korzyści może przynieść użytkownikowi, jeśli przyzna on uprawnienia w czasie działania. Gdy użytkownik potwierdzi uzasadnienie, przejdź do następnego kroku.
Poproś o zezwolenie wymagane przez aplikację do uzyskania dostępu do prywatnych danych użytkownika. System wyświetli prośbę o przyznanie uprawnień w czasie działania, np. taką jak na stronie omówienia uprawnień.
Sprawdź odpowiedź użytkownika – czy przyznał uprawnienia w czasie działania aplikacji, czy odmówił.
Jeśli użytkownik przyznał aplikacji uprawnienia, możesz uzyskać dostęp do prywatnych danych użytkownika. Jeśli użytkownik odmówi udzielenia uprawnień, łagodnie zdegraduj działanie aplikacji, aby zapewnić użytkownikowi funkcjonalność bez informacji chronionych przez te uprawnienia.
Ilustracja 1 przedstawia przepływ pracy i zestaw decyzji związanych z tym procesem:
Sprawdź, czy aplikacja ma już przyznane uprawnienia.
Aby sprawdzić, czy użytkownik przyznał już Twojej aplikacji określone uprawnienia, przekaż je do metody ContextCompat.checkSelfPermission()
. Ta metoda zwraca wartość PERMISSION_GRANTED
lub PERMISSION_DENIED
w zależności od tego, czy aplikacja ma uprawnienia.
Wyjaśnij, dlaczego Twoja aplikacja potrzebuje tego uprawnienia
Okno uprawnień wyświetlane przez system, gdy wywołujesz requestPermissions()
, informuje, o jakie uprawnienia prosi aplikacja, ale nie podaje przyczyny. W niektórych przypadkach użytkownik może być tym zaskoczony. Przed wywołaniem funkcji requestPermissions()
warto wyjaśnić użytkownikowi, dlaczego aplikacja potrzebuje uprawnień.
Badania pokazują, że użytkownicy są znacznie bardziej skłonni do przyznawania uprawnień, jeśli wiedzą, dlaczego aplikacja ich potrzebuje, np. czy są one niezbędne do obsługi podstawowej funkcji aplikacji czy do wyświetlania reklam. Dlatego jeśli używasz tylko części wywołań interfejsu API, które należą do grupy uprawnień, warto wyraźnie wymienić, których uprawnień używasz i dlaczego. Jeśli na przykład używasz tylko przybliżonej lokalizacji, poinformuj o tym użytkownika w opisie aplikacji lub w artykułach pomocy dotyczących aplikacji.
W określonych sytuacjach warto też informować użytkowników o dostępie do danych wrażliwych w czasie rzeczywistym. Jeśli na przykład korzystasz z aparatu lub mikrofonu, warto poinformować o tym użytkownika, wyświetlając ikonę powiadomienia w aplikacji lub na pasku powiadomień (jeśli aplikacja działa w tle). Dzięki temu nie będzie on miał wrażenia, że potajemnie zbierasz dane.
Jeśli musisz poprosić o uprawnienia, aby coś w aplikacji działało, ale powód nie jest jasny dla użytkownika, znajdź sposób, aby poinformować go, dlaczego potrzebujesz najbardziej wrażliwych uprawnień.
Jeśli metoda ContextCompat.checkSelfPermission()
zwróci PERMISSION_DENIED
, wywołaj shouldShowRequestPermissionRationale()
.
Jeśli ta metoda zwróci wartość true
, wyświetl użytkownikowi interfejs edukacyjny. W tym interfejsie wyjaśnij, dlaczego funkcja, którą użytkownik chce włączyć, wymaga określonych uprawnień.
Jeśli aplikacja prosi o uprawnienia związane z lokalizacją, mikrofonem lub aparatem, rozważ wyjaśnienie, dlaczego potrzebuje dostępu do tych informacji.
Prośba o uprawnienia
Po wyświetleniu interfejsu edukacyjnego lub gdy wartość zwracana przez funkcję shouldShowRequestPermissionRationale()
wskazuje, że nie musisz wyświetlać interfejsu edukacyjnego, poproś o uprawnienia. Użytkownicy widzą okno uprawnień systemowych, w którym mogą zdecydować, czy przyznać aplikacji określone uprawnienie.
Aby to zrobić, użyj RequestPermission
umowy zawartej w bibliotece AndroidX, w której zezwalasz systemowi na zarządzanie kodem żądania uprawnień. Korzystanie z umowy RequestPermission
upraszcza logikę, dlatego jest to zalecane rozwiązanie, gdy jest to możliwe. W razie potrzeby możesz jednak samodzielnie zarządzać kodem żądania w ramach prośby o uprawnienia i uwzględnić ten kod w logice wywołania zwrotnego uprawnień.
Zezwalaj systemowi na zarządzanie kodem prośby o uprawnienia
Aby system mógł zarządzać kodem żądania powiązanym z prośbą o uprawnienia, dodaj zależności do tych bibliotek w pliku build.gradle
modułu:
androidx.activity
, wersja 1.2.0 lub nowszaandroidx.fragment
, wersja 1.3.0 lub nowsza
Możesz wtedy użyć jednej z tych klas:
- Aby poprosić o jedno uprawnienie, użyj
RequestPermission
. - Aby poprosić o kilka uprawnień jednocześnie, użyj
RequestMultiplePermissions
.
Z tych instrukcji dowiesz się, jak korzystać z umowy RequestPermission
. Proces jest prawie taki sam w przypadku umowy RequestMultiplePermissions
.
W logice inicjowania aktywności lub fragmentu przekaż implementację
ActivityResultCallback
do wywołaniaregisterForActivityResult()
.ActivityResultCallback
określa, jak aplikacja obsługuje odpowiedź użytkownika na prośbę o uprawnienia.Zachowaj odwołanie do wartości zwracanej przez
registerForActivityResult()
, która jest typuActivityResultLauncher
.Aby w razie potrzeby wyświetlić okno uprawnień systemowych, wywołaj metodę
launch()
na instancjiActivityResultLauncher
zapisanej w poprzednim kroku.Po wywołaniu funkcji
launch()
pojawi się okno uprawnień systemowych. Gdy użytkownik dokona wyboru, system asynchronicznie wywoła Twoją implementację funkcjiActivityResultCallback
, którą zdefiniowano w poprzednim kroku.Uwaga: aplikacja nie może dostosowywać okna dialogowego, które pojawia się, gdy dzwonisz pod numer
launch()
. Aby przekazać użytkownikowi więcej informacji lub kontekstu, zmień interfejs aplikacji, tak aby użytkownicy łatwiej rozumieli, dlaczego dana funkcja w aplikacji wymaga określonego uprawnienia. Możesz na przykład zmienić tekst na przycisku, który włącza tę funkcję.Tekst w oknie uprawnień systemowych odwołuje się też do grupy uprawnień powiązanej z uprawnieniem, o które prosisz. Ta grupa uprawnień została zaprojektowana z myślą o łatwości korzystania z systemu. Aplikacja nie powinna polegać na tym, czy uprawnienia znajdują się w określonej grupie uprawnień, czy poza nią.
Ten fragment kodu pokazuje, jak obsługiwać odpowiedź dotyczącą uprawnień:
Kotlin
// Register the permissions callback, which handles the user's response to the // system permissions dialog. Save the return value, an instance of // ActivityResultLauncher. You can use either a val, as shown in this snippet, // or a lateinit var in your onAttach() or onCreate() method. val requestPermissionLauncher = registerForActivityResult(RequestPermission() ) { isGranted: Boolean -> if (isGranted) { // Permission is granted. Continue the action or workflow in your // app. } else { // Explain to the user that the feature is unavailable because the // feature requires a permission that the user has denied. At the // same time, respect the user's decision. Don't link to system // settings in an effort to convince the user to change their // decision. } }
Java
// Register the permissions callback, which handles the user's response to the // system permissions dialog. Save the return value, an instance of // ActivityResultLauncher, as an instance variable. private ActivityResultLauncher<String> requestPermissionLauncher = registerForActivityResult(new RequestPermission(), isGranted -> { if (isGranted) { // Permission is granted. Continue the action or workflow in your // app. } else { // Explain to the user that the feature is unavailable because the // feature requires a permission that the user has denied. At the // same time, respect the user's decision. Don't link to system // settings in an effort to convince the user to change their // decision. } });
Ten fragment kodu pokazuje zalecany proces sprawdzania uprawnień i w razie potrzeby proszenia użytkownika o ich przyznanie:
Kotlin
when { ContextCompat.checkSelfPermission( CONTEXT, Manifest.permission.REQUESTED_PERMISSION ) == PackageManager.PERMISSION_GRANTED -> { // You can use the API that requires the permission. } ActivityCompat.shouldShowRequestPermissionRationale( this, Manifest.permission.REQUESTED_PERMISSION) -> { // In an educational UI, explain to the user why your app requires this // permission for a specific feature to behave as expected, and what // features are disabled if it's declined. In this UI, include a // "cancel" or "no thanks" button that lets the user continue // using your app without granting the permission. showInContextUI(...) } else -> { // You can directly ask for the permission. // The registered ActivityResultCallback gets the result of this request. requestPermissionLauncher.launch( Manifest.permission.REQUESTED_PERMISSION) } }
Java
if (ContextCompat.checkSelfPermission( CONTEXT, Manifest.permission.REQUESTED_PERMISSION) == PackageManager.PERMISSION_GRANTED) { // You can use the API that requires the permission. performAction(...); } else if (ActivityCompat.shouldShowRequestPermissionRationale( this, Manifest.permission.REQUESTED_PERMISSION)) { // In an educational UI, explain to the user why your app requires this // permission for a specific feature to behave as expected, and what // features are disabled if it's declined. In this UI, include a // "cancel" or "no thanks" button that lets the user continue // using your app without granting the permission. showInContextUI(...); } else { // You can directly ask for the permission. // The registered ActivityResultCallback gets the result of this request. requestPermissionLauncher.launch( Manifest.permission.REQUESTED_PERMISSION); }
Samodzielne zarządzanie kodem prośby o uprawnienia
Zamiast zezwalać systemowi na zarządzanie kodem prośby o uprawnienia, możesz samodzielnie zarządzać kodem prośby o uprawnienia. Aby to zrobić, w wywołaniu funkcji requestPermissions()
podaj kod żądania.
Ten fragment kodu pokazuje, jak poprosić o uprawnienia za pomocą kodu żądania:
Kotlin
when { ContextCompat.checkSelfPermission( CONTEXT, Manifest.permission.REQUESTED_PERMISSION ) == PackageManager.PERMISSION_GRANTED -> { // You can use the API that requires the permission. performAction(...) } ActivityCompat.shouldShowRequestPermissionRationale( this, Manifest.permission.REQUESTED_PERMISSION) -> { // In an educational UI, explain to the user why your app requires this // permission for a specific feature to behave as expected, and what // features are disabled if it's declined. In this UI, include a // "cancel" or "no thanks" button that lets the user continue // using your app without granting the permission. showInContextUI(...) } else -> { // You can directly ask for the permission. requestPermissions(CONTEXT, arrayOf(Manifest.permission.REQUESTED_PERMISSION), REQUEST_CODE) } }
Java
if (ContextCompat.checkSelfPermission( CONTEXT, Manifest.permission.REQUESTED_PERMISSION) == PackageManager.PERMISSION_GRANTED) { // You can use the API that requires the permission. performAction(...); } else if (ActivityCompat.shouldShowRequestPermissionRationale( this, Manifest.permission.REQUESTED_PERMISSION)) { // In an educational UI, explain to the user why your app requires this // permission for a specific feature to behave as expected, and what // features are disabled if it's declined. In this UI, include a // "cancel" or "no thanks" button that lets the user continue // using your app without granting the permission. showInContextUI(...); } else { // You can directly ask for the permission. requestPermissions(CONTEXT, new String[] { Manifest.permission.REQUESTED_PERMISSION }, REQUEST_CODE); }
Gdy użytkownik odpowie na okno uprawnień systemowych, system wywoła implementację funkcji onRequestPermissionsResult()
w Twojej aplikacji. System przekazuje odpowiedź użytkownika na okno z prośbą o uprawnienia oraz zdefiniowany przez Ciebie kod żądania, jak pokazano w tym fragmencie kodu:
Kotlin
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) { when (requestCode) { PERMISSION_REQUEST_CODE -> { // If request is cancelled, the result arrays are empty. if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) { // Permission is granted. Continue the action or workflow // in your app. } else { // Explain to the user that the feature is unavailable because // the feature requires a permission that the user has denied. // At the same time, respect the user's decision. Don't link to // system settings in an effort to convince the user to change // their decision. } return } // Add other 'when' lines to check for other // permissions this app might request. else -> { // Ignore all other requests. } } }
Java
@Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { switch (requestCode) { case PERMISSION_REQUEST_CODE: // If request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permission is granted. Continue the action or workflow // in your app. } else { // Explain to the user that the feature is unavailable because // the feature requires a permission that the user has denied. // At the same time, respect the user's decision. Don't link to // system settings in an effort to convince the user to change // their decision. } return; } // Other 'case' lines to check for other // permissions this app might request. } }
Wysyłanie prośby o dostęp do lokalizacji
Gdy wysyłasz prośbę o dostęp do lokalizacji, postępuj zgodnie z tymi samymi sprawdzonymi metodami co w przypadku innych uprawnień w czasie działania. Ważną różnicą w przypadku uprawnień do lokalizacji jest to, że system zawiera wiele uprawnień związanych z lokalizacją. O jakie uprawnienia prosisz i w jaki sposób to robisz, zależy od wymagań dotyczących lokalizacji w przypadku użycia aplikacji.
Lokalizacja na pierwszym planie
Jeśli aplikacja zawiera funkcję, która udostępnia lub odbiera informacje o lokalizacji tylko raz albo przez określony czas, wymaga ona dostępu do lokalizacji na pierwszym planie. Oto kilka przykładów:
- W aplikacji do nawigacji funkcja umożliwia użytkownikom uzyskiwanie szczegółowych wskazówek dojazdu.
- W aplikacji do obsługi wiadomości funkcja umożliwia użytkownikom udostępnianie bieżącej lokalizacji innemu użytkownikowi.
System uznaje, że aplikacja korzysta z lokalizacji na pierwszym planie, jeśli funkcja aplikacji uzyskuje dostęp do bieżącej lokalizacji urządzenia w jednej z tych sytuacji:
- Widoczna jest aktywność należąca do Twojej aplikacji.
Aplikacja działa jako usługa na pierwszym planie. Gdy usługa na pierwszym planie jest aktywna, system informuje o tym użytkownika, wyświetlając trwałe powiadomienie. Aplikacja zachowuje dostęp, gdy jest w tle, np. gdy użytkownik naciśnie przycisk ekranu głównego na urządzeniu lub wyłączy wyświetlacz urządzenia.
Na Androidzie 10 (poziom interfejsu API 29) i nowszych wersjach musisz zadeklarować typ usługi działającej na pierwszym planie
location
, jak pokazano w tym fragmencie kodu. W starszych wersjach Androida zalecamy zadeklarowanie tego typu usługi na pierwszym planie.<!-- Recommended for Android 9 (API level 28) and lower. --> <!-- Required for Android 10 (API level 29) and higher. --> <service android:name="MyNavigationService" android:foregroundServiceType="location" ... > <!-- Any inner elements go here. --> </service>
Potrzebę dostępu do lokalizacji na pierwszym planie deklarujesz, gdy aplikacja prosi o uprawnienie ACCESS_COARSE_LOCATION
lub ACCESS_FINE_LOCATION
, jak pokazano w tym fragmencie kodu:
<manifest ... > <!-- Include this permission any time your app needs location information. --> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- Include only if your app benefits from precise location access. --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> </manifest>
Lokalizacja w tle
Aplikacja wymaga dostępu do lokalizacji w tle, jeśli funkcja w niej stale udostępnia lokalizację innym użytkownikom lub korzysta z interfejsu Geofencing API. Oto kilka przykładów:
- W aplikacji do udostępniania lokalizacji w grupie rodzinnej funkcja umożliwia użytkownikom ciągłe udostępnianie lokalizacji członkom grupy rodzinnej.
- W aplikacji IoT funkcja umożliwia użytkownikom skonfigurowanie urządzeń domowych w taki sposób, aby wyłączały się, gdy użytkownik opuszcza dom, i włączały się ponownie, gdy wraca.
System uznaje, że aplikacja korzysta z lokalizacji w tle, jeśli uzyskuje dostęp do bieżącej lokalizacji urządzenia w innych sytuacjach niż opisane w sekcji Lokalizacja na pierwszym planie. Dokładność lokalizacji w tle jest taka sama jak dokładność lokalizacji na pierwszym planie, która zależy od uprawnień do lokalizacji zadeklarowanych przez aplikację.
Na Androidzie 10 (API na poziomie 29) i nowszym musisz zadeklarować uprawnienie
ACCESS_BACKGROUND_LOCATION
w manifeście aplikacji, aby w czasie działania aplikacji poprosić o dostęp do lokalizacji w tle. W starszych wersjach Androida, gdy aplikacja uzyskuje dostęp do lokalizacji na pierwszym planie, automatycznie uzyskuje też dostęp do lokalizacji w tle.
<manifest ... > <!-- Required only when requesting background location access on Android 10 (API level 29) and higher. --> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> </manifest>
Obsługa odmowy przyznania uprawnień
Jeśli użytkownik odrzuci prośbę o przyznanie uprawnień, aplikacja powinna pomóc mu zrozumieć konsekwencje takiej decyzji. W szczególności aplikacja powinna informować użytkowników o funkcjach, które nie działają z powodu braku uprawnień. Pamiętaj o tych sprawdzonych metodach:
Kieruj uwagę użytkownika. Wskaż konkretną część interfejsu aplikacji, w której funkcjonalność jest ograniczona, ponieważ aplikacja nie ma niezbędnych uprawnień. Przykłady działań, które możesz wykonać:
- Wyświetl komunikat w miejscu, w którym powinny się pojawić wyniki lub dane funkcji.
- Wyświetl inny przycisk z ikoną błędu i kolorem.
Unikaj ogólników. Nie wyświetlaj ogólnego komunikatu. Zamiast tego wyjaśnij, które funkcje są niedostępne, ponieważ aplikacja nie ma odpowiednich uprawnień.
Nie blokuj interfejsu. Innymi słowy, nie wyświetlaj ostrzeżenia na pełnym ekranie, które uniemożliwia użytkownikom dalsze korzystanie z aplikacji.
Jednocześnie aplikacja powinna szanować decyzję użytkownika o odmowie przyznania uprawnień. Od Androida 11 (poziom interfejsu API 30) jeśli użytkownik kliknie Odmów w przypadku określonego uprawnienia więcej niż raz od momentu zainstalowania aplikacji na urządzeniu, nie zobaczy okna dialogowego uprawnień systemowych, jeśli aplikacja ponownie poprosi o to uprawnienie. Działanie użytkownika oznacza „nie pytaj ponownie”. W poprzednich wersjach użytkownicy widzieli okno uprawnień systemowych za każdym razem, gdy aplikacja prosiła o uprawnienia, chyba że wcześniej zaznaczyli pole wyboru lub opcję „Nie pytaj ponownie”.
Jeśli użytkownik odrzuci prośbę o uprawnienia więcej niż raz, zostanie to uznane za trwałe odrzucenie. Bardzo ważne jest, aby prosić użytkowników o uprawnienia tylko wtedy, gdy potrzebują dostępu do konkretnej funkcji. W przeciwnym razie możesz nieumyślnie utracić możliwość ponownego poproszenia o uprawnienia.
W niektórych sytuacjach uprawnienie może zostać automatycznie odrzucone bez podejmowania przez użytkownika żadnych działań. (Uprawnienia mogą być też przyznawane automatycznie). Nie należy niczego zakładać w odniesieniu do automatycznego działania. Za każdym razem, gdy aplikacja musi uzyskać dostęp do funkcji wymagającej uprawnień, sprawdź, czy nadal ma te uprawnienia.
Aby zapewnić użytkownikom jak najlepsze wrażenia podczas proszenia o uprawnienia aplikacji, zapoznaj się też ze sprawdzonymi metodami dotyczącymi uprawnień aplikacji.
Sprawdzanie stanu odmowy podczas testowania i debugowania
Aby sprawdzić, czy aplikacja ma trwale odrzucone uprawnienia (na potrzeby debugowania i testowania), użyj tego polecenia:
adb shell dumpsys package PACKAGE_NAME
gdzie PACKAGE_NAME to nazwa pakietu do sprawdzenia.
Dane wyjściowe polecenia zawierają sekcje podobne do tych:
... runtime permissions: android.permission.POST_NOTIFICATIONS: granted=false, flags=[ USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED] android.permission.ACCESS_FINE_LOCATION: granted=false, flags=[ USER_SET|USER_FIXED|USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED] android.permission.BLUETOOTH_CONNECT: granted=false, flags=[ USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED] ...
Uprawnienia, które zostały raz odrzucone przez użytkownika, są oznaczone symbolem USER_SET
.
Uprawnienia, które zostały trwale odrzucone przez dwukrotne kliknięcie Odrzuć, są oznaczone symbolem USER_FIXED
.
Aby mieć pewność, że podczas testowania testerzy zobaczą okno z prośbą o zgodę, po zakończeniu debugowania aplikacji zresetuj te flagi. Aby to zrobić, użyj polecenia:
adb shell pm clear-permission-flags PACKAGE_NAME PERMISSION_NAME user-set user-fixed
PERMISSION_NAME to nazwa uprawnienia, które chcesz zresetować.
Pełną listę uprawnień aplikacji na Androida znajdziesz na stronie z dokumentacją interfejsu API uprawnień.
Jednorazowe uprawnienia
Od Androida 11 (API na poziomie 30) za każdym razem, gdy aplikacja poprosi o uprawnienia związane z lokalizacją, mikrofonem lub aparatem, w oknie dialogowym uprawnień wyświetlanym użytkownikowi pojawi się opcja Tylko tym razem, jak pokazano na rysunku 2. Jeśli użytkownik wybierze tę opcję w oknie, Twoja aplikacja otrzyma tymczasowe jednorazowe uprawnienie.
Aplikacja może wtedy uzyskać dostęp do powiązanych danych przez pewien czas, który zależy od zachowania aplikacji i działań użytkownika:
- Gdy aktywność aplikacji jest widoczna, może ona uzyskać dostęp do danych.
- Jeśli użytkownik przełączy aplikację w tryb tła, będzie ona mogła przez krótki czas nadal uzyskiwać dostęp do danych.
- Jeśli uruchomisz usługę na pierwszym planie, gdy aktywność jest widoczna, a użytkownik przeniesie aplikację w tle, aplikacja może nadal uzyskiwać dostęp do danych, dopóki usługa na pierwszym planie nie zostanie zatrzymana.
Proces aplikacji kończy się po cofnięciu uprawnień
Jeśli użytkownik cofnie jednorazowe uprawnienie, np. w ustawieniach systemu, Twoja aplikacja nie będzie mieć dostępu do danych, niezależnie od tego, czy uruchomisz usługę na pierwszym planie. Podobnie jak w przypadku innych uprawnień, jeśli użytkownik wycofa jednorazowe uprawnienie aplikacji, proces aplikacji zostanie zakończony.
Gdy użytkownik otworzy aplikację i funkcja w niej poprosi o dostęp do lokalizacji, mikrofonu lub aparatu, ponownie wyświetli się prośba o uprawnienia.
Resetowanie nieużywanych uprawnień
Android udostępnia kilka sposobów resetowania nieużywanych uprawnień środowiska wykonawczego do ich domyślnego stanu odmowy:
- Interfejs API, w którym możesz proaktywnie usuwać dostęp aplikacji do nieużywanych uprawnień środowiska wykonawczego.
- Mechanizm systemowy, który automatycznie resetuje uprawnienia nieużywanych aplikacji.
Usuwanie dostępu aplikacji
Na Androidzie 13 (API na poziomie 33) i nowszym możesz usunąć dostęp aplikacji do uprawnień środowiska wykonawczego, których aplikacja nie potrzebuje. Gdy zaktualizujesz aplikację, wykonaj ten krok, aby użytkownicy lepiej rozumieli, dlaczego aplikacja nadal prosi o określone uprawnienia. Ta wiedza pomaga budować zaufanie użytkowników do Twojej aplikacji.
Aby cofnąć dostęp do uprawnienia w czasie działania, przekaż nazwę tego uprawnienia do funkcji revokeSelfPermissionOnKill()
.
Aby jednocześnie odebrać dostęp do grupy uprawnień w czasie działania, przekaż kolekcję nazw uprawnień do metody revokeSelfPermissionsOnKill()
.
Proces usuwania uprawnień odbywa się asynchronicznie i kończy wszystkie procesy powiązane z identyfikatorem UID aplikacji.
Aby system usunął dostęp aplikacji do uprawnień, wszystkie procesy powiązane z aplikacją muszą zostać zakończone. Gdy wywołasz interfejs API, system określi, kiedy można bezpiecznie zakończyć te procesy. Zazwyczaj system czeka, aż aplikacja będzie działać w tle przez dłuższy czas, a nie na pierwszym planie.
Aby poinformować użytkownika, że aplikacja nie wymaga już dostępu do określonych uprawnień w czasie działania, wyświetl okno dialogowe przy następnym uruchomieniu aplikacji przez użytkownika. To okno dialogowe może zawierać listę uprawnień.
Automatyczne resetowanie uprawnień nieużywanych aplikacji
Jeśli Twoja aplikacja jest przeznaczona na Androida 11 (API na poziomie 30) lub nowszego i nie jest używana przez kilka miesięcy, system chroni dane użytkownika, automatycznie resetując wrażliwe uprawnienia czasu wykonywania, które użytkownik przyznał Twojej aplikacji. Więcej informacji znajdziesz w przewodniku na temat hibernacji aplikacji.
W razie potrzeby poproś o ustawienie aplikacji jako domyślnego modułu obsługi.
Niektóre aplikacje wymagają dostępu do informacji poufnych użytkownika związanych z rejestrami połączeń i SMS-ami. Jeśli chcesz poprosić o uprawnienia dostępu do rejestru połączeń i SMS-ów oraz opublikować aplikację w Sklepie Play, przed poproszeniem o te uprawnienia w czasie działania musisz poprosić użytkownika o ustawienie Twojej aplikacji jako domyślnego modułu obsługi podstawowej funkcji systemu.
Więcej informacji o domyślnych modułach obsługi, w tym wskazówki dotyczące wyświetlania użytkownikom prośby o wybranie domyślnego modułu obsługi, znajdziesz w przewodniku dotyczącym uprawnień używanych tylko w domyślnych modułach obsługi.
Przyznawanie wszystkich uprawnień w czasie działania na potrzeby testowania
Aby automatycznie przyznawać wszystkie uprawnienia w czasie działania aplikacji podczas instalowania jej na emulatorze lub urządzeniu testowym, użyj opcji -g
w przypadku polecenia adb shell install
, jak pokazano w tym fragmencie kodu:
adb shell install -g PATH_TO_APK_FILE
Dodatkowe materiały
Więcej informacji o uprawnieniach znajdziesz w tych artykułach:
Więcej informacji o prośbach o uprawnienia znajdziesz w przykładach dotyczących uprawnień.
Możesz też wykonać to ćwiczenie z programowania, które pokazuje najlepsze praktyki w zakresie ochrony prywatności.