Każda aplikacja na Androida działa w piaskownicy o ograniczonym dostępie. Jeśli Twoja aplikacja musi korzystać z zasobów lub informacji spoza własnego środowiska piaskownicy, możesz zadeklarować uprawnienie w czasie działania i skonfigurować prośbę o uprawnienia, która zapewnia ten dostęp. Te czynności są częścią przepływu pracy związanego z uprawnieniami.
Jeśli zadeklarujesz jakiekolwiek 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 wzorca 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 systemu, które są wyświetlane użytkownikowi, gdy aplikacja prosi o ściśle powiązane uprawnienia.
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:
- Zadeklaruj uprawnienia, o które aplikacja może poprosić, w pliku manifestu aplikacji.
- Zaprojektuj interfejs użytkownika aplikacji tak, aby określone działania w aplikacji 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 w czasie działania, które są wymagane do uzyskania dostępu do tych danych.
- Sprawdź, czy użytkownik przyznał już wymagane przez aplikację uprawnienia w czasie działania. Jeśli tak jest, 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 jego zgody na przyznanie 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 jasno 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 aplikacji. Gdy użytkownik potwierdzi, że rozumie uzasadnienie, przejdź do następnego kroku. 
- Poproś o uprawnienia wymagane przez aplikację do uzyskania dostępu do prywatnych danych użytkownika. System wyświetli prośbę o uprawnienia w czasie działania aplikacji, np. taką jak na stronie z omówieniem uprawnień. 
- Sprawdź odpowiedź użytkownika – czy przyznał uprawnienia w czasie działania aplikacji, czy odmówił ich przyznania. 
- Jeśli użytkownik przyznał Twojej aplikacji uprawnienia, możesz uzyskać dostęp do prywatnych danych użytkownika. Jeśli użytkownik odmówi przyznania uprawnień, zadbaj o to, aby aplikacja działała prawidłowo, i zapewnij 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 uprawnienie, przekaż je do metody [ContextCompat.checkSelfPermission()][12].
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 tych uprawnień.
Okno uprawnień wyświetlane przez system, gdy wywołujesz [requestPermissions()][15], informuje o tym, jakich uprawnień żąda 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ń, wyraźnie wymień, 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, poinformuj 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 funkcja działała, ale powód nie jest jasny dla użytkownika, wyjaśnij, dlaczego potrzebujesz uprawnień dostępu do danych wrażliwych.
Jeśli metoda ContextCompat.checkSelfPermission() zwróci wartość PERMISSION_DENIED,
wywołaj [shouldShowRequestPermissionRationale()][16]. 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, wyjaśnij, 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ą wybrać, czy przyznać aplikacji określone uprawnienia.
Aby to zrobić, użyj kontraktu RequestPermission, który jest zawarty w bibliotece AndroidX. W jego przypadku zezwolisz systemowi na zarządzanie kodem żądania uprawnień. Korzystanie z umowy RequestPermission upraszcza logikę, dlatego jest to zalecane rozwiązanie, gdy tylko jest to możliwe. W razie potrzeby możesz też 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 żądaniem uprawnień, dodaj zależności do tych bibliotek w pliku build.gradle modułu:
- androidx.activityw wersji 1.2.0 lub nowszej
- androidx.fragmentw wersji 1.3.0 lub nowszej
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ę interfejsu - ActivityResultCallbackdo wywołania funkcji- registerForActivityResult(). Element- ActivityResultCallbackokreś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 typu- ActivityResultLauncher.
- Aby w razie potrzeby wyświetlić okno uprawnień systemowych, wywołaj metodę - launch()w instancji- ActivityResultLauncherzapisanej w poprzednim kroku.- Po wywołaniu funkcji - launch()pojawi się okno uprawnień systemowych. Gdy użytkownik dokona wyboru, system asynchronicznie wywoła Twoją implementację funkcji- ActivityResultCallback, 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ą. 
Poniższy fragment kodu pokazuje, jak obsługiwać odpowiedź dotyczącą uprawnień:
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); }
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 zarządzać nim samodzielnie. Aby to zrobić, uwzględnij kod żądania w wywołaniu funkcji [requestPermissions()][15].
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 dialogowe z prośbą o uprawnienia, a także 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 Twoja 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 uruchomiona, 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 Ekran główny na urządzeniu lub wyłączy wyświetlacz urządzenia. - W przypadku Androida 10 (poziom interfejsu API 29) i nowszych wersji musisz zadeklarować typ usługi działającej na pierwszym planie - location, jak pokazano w tym fragmencie kodu. W przypadku starszych wersji Androida zalecamy zadeklarowanie tego typu usługi działającej 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 zawarta 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 tak, 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ż te 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 zadeklarowanych przez aplikację uprawnień do lokalizacji.
Na Androidzie 10 (API na poziomie 29) i nowszych wersjach musisz zadeklarować uprawnienie
ACCESS_BACKGROUND_LOCATION w manifeście aplikacji, aby w czasie działania aplikacji prosić 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 musi pomóc mu zrozumieć konsekwencje takiej decyzji. W szczególności aplikacja musi 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. Wyróżnij konkretną część interfejsu aplikacji, w której funkcjonalność jest ograniczona, ponieważ aplikacja nie ma niezbędnych uprawnień. Oto 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 jasno informuj, które funkcje są niedostępne, ponieważ aplikacja nie ma odpowiednich uprawnień. 
- Nie blokuj interfejsu. Innymi słowy, nie wyświetlaj pełnoekranowego komunikatu ostrzegawczego, który uniemożliwia użytkownikom dalsze korzystanie z aplikacji. 
Jednocześnie aplikacja musi respektować 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 więcej niż raz odrzuci prośbę o uprawnienia, 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 określonej 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ć na temat automatycznego działania. Za każdym razem, gdy aplikacja musi uzyskać dostęp do funkcji wymagającej uprawnień, sprawdzaj, czy nadal ma te uprawnienia.
Aby zapewnić użytkownikom jak najlepsze wrażenia podczas proszenia o uprawnienia aplikacji, zapoznaj się też z artykułem Sprawdzone metody dotyczące 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 testerzy zobaczą okno z prośbą o zgodę podczas testowania, 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ć.
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 przeniesie aplikację na drugi plan, 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ę na drugi plan, 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 uprawnienia, 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 uprawnienia 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ń w czasie działania, których aplikacja nie potrzebuje. Gdy aktualizujesz aplikację, wykonaj ten krok, aby użytkownicy lepiej rozumieli, dlaczego aplikacja nadal prosi o przyznanie określonych uprawnień. Ta wiedza pomaga budować zaufanie użytkowników do aplikacji.
Aby cofnąć dostęp do uprawnienia w czasie działania, przekaż nazwę tego uprawnienia do funkcji revokeSelfPermissionOnKill(). Aby jednocześnie cofnąć dostęp do grupy uprawnień w czasie działania, przekaż kolekcję nazw uprawnień do funkcji revokeSelfPermissionsOnKill(). Proces usuwania uprawnień przebiega 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. Zwykle system czeka, aż aplikacja będzie działać w tle przez dłuższy czas, zamiast na pierwszym planie.
Aby poinformować użytkownika, że Twoja 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 w czasie działania, które użytkownik przyznał 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 dotyczące 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 po uprawnieniach 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.
[12]: /reference/androidx/core/content/ContextCompat#checkSelfPermission(android.content.Context, java.lang.String)
[15]: /reference/androidx/core/app/ActivityCompat.html#requestPermissions(android.app.Activity, java.lang.String[], int) [16]: /reference/androidx/core/app/ActivityCompat#shouldShowRequestPermissionRationale(android.app.Activity, java.lang.String)
