Poproś o uprawnienia czasu działania

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łasnej piaskownicy, możesz zadeklarować uprawnienia środowiska wykonawczego i skonfigurować prośbę o uprawnienia, która przyzna mu taki dostęp. Są one częścią przepływu pracy związanych z używaniem uprawnień.

Jeśli zadeklarujesz niebezpieczne uprawnienia, a Twoja aplikacja jest zainstalowana na urządzeniu z Androidem 6.0 (poziom interfejsu API 23) lub wyższym, musisz poprosić o takie uprawnienia w czasie działania, wykonując czynności opisane w tym przewodniku.

Jeśli nie deklarujesz żadnych niebezpiecznych uprawnień lub Twoja aplikacja jest zainstalowana na urządzeniu z Androidem 5.1 (poziom interfejsu API 22) lub niższym, uprawnienia zostaną przyznane automatycznie i nie będzie trzeba wykonywać żadnych pozostałych czynności na tej stronie.

Podstawowe zasady

Oto podstawowe zasady dotyczące wysyłania próśb o uprawnienia w czasie działania:

  • Poproś o uprawnienia w kontekście, gdy użytkownik zacznie korzystać z funkcji, która go wymaga.
  • Nie blokuj użytkownika. Zawsze zapewniaj opcję anulowania procesu edukacyjnego w interfejsie, na przykład procedury opisującej powód prośby o uprawnienia.
  • Jeśli użytkownik odmówi przyznania uprawnień lub cofnie te uprawnienia, odpowiednio obniż poziom aplikacji, aby mógł nadal z niej korzystać. Możesz na przykład wyłączyć funkcję, która ich wymaga.
  • Nie zakładaj żadnego działania systemu. Nie zakładaj na przykład, że uprawnienia występują w tej samej grupie uprawnień. Grupa uprawnień pomaga jedynie zminimalizować liczbę okien dialogowych wyświetlanych użytkownikowi, gdy aplikacja prosi o ściśle powiązane uprawnienia.

Proces wysyłania prośby o uprawnienia

Zanim zadeklarujesz i poproś o uprawnienia w czasie działania aplikacji, oceń, czy potrzebuje ona takich uprawnień. Aplikacja może pełnić wiele funkcji, takich jak robienie zdjęć, wstrzymywanie odtwarzania multimediów i wyświetlanie odpowiednich reklam bez potrzeby deklarowania uprawnień.

Jeśli stwierdzisz, że Twoja aplikacja musi zadeklarować i poprosić o uprawnienia w czasie działania, wykonaj te czynności:

  1. W pliku manifestu zadeklaruj uprawnienia, o które może prosić aplikacja.
  2. Zaprojektuj wrażenia użytkowników swojej aplikacji tak, aby określone działania w niej były powiązane z odpowiednimi uprawnieniami w czasie działania. Poinformuj użytkowników, które działania mogą wymagać od nich przyznania aplikacji uprawnień dostępu do prywatnych danych użytkowników.
  3. Poczekaj, aż użytkownik wywoła w Twojej aplikacji zadanie lub działanie, które wymaga dostępu do określonych prywatnych danych użytkownika. Aplikacja może wtedy poprosić o uprawnienia w czasie działania wymagane do uzyskania dostępu do tych danych.
  4. Sprawdź, czy użytkownik przyznał już uprawnienia do środowiska wykonawczego, którego wymaga Twoja aplikacja. Jeśli tak, aplikacja może uzyskać dostęp do prywatnych danych użytkownika. Jeśli nie, przejdź do następnego.

    Musisz sprawdzić, czy masz dane uprawnienie za każdym razem, gdy wykonujesz operację, która go wymaga.

  5. Sprawdź, czy aplikacja powinna wyświetlać użytkownikom uzasadnienie, dlaczego aplikacja potrzebuje od użytkownika przyznania określonych uprawnień w czasie działania. Jeśli system ustali, że aplikacja nie powinna wyświetlać uzasadnienia, przejdź od razu do następnego kroku, bez wyświetlania elementu interfejsu.

    Jeśli system określi, że aplikacja powinna wyświetlić uzasadnienie, podaj je użytkownikowi w elemencie interfejsu. W ramach tego uzasadnienia dokładnie wyjaśnij, do jakich danych aplikacja próbuje uzyskać dostęp i jakie korzyści może przynieść użytkownikowi aplikacja, jeśli przyzna ona uprawnienia w czasie działania. Gdy użytkownik potwierdzi uzasadnienie, przejdź do następnego kroku.

  6. Poproś o uprawnienia w czasie działania, które są niezbędne, aby aplikacja mogła uzyskać dostęp do prywatnych danych użytkownika. System wyświetla prośbę o uprawnienia w czasie działania, np. na stronie przeglądu uprawnień.

  7. Sprawdź odpowiedź użytkownika – niezależnie od tego, czy przyznał(a) uprawnienia do środowiska wykonawczego czy je odrzuca.

  8. Jeśli użytkownik przyznał Twojej aplikacji uprawnienia, możesz uzyskać dostęp do jej prywatnych danych. Jeśli użytkownik odmówił przyznania uprawnień, własnoręcznie ogranicz korzystanie z aplikacji, tak aby nie zawierała informacji chronionych przez to uprawnienie.

Rysunek 1 przedstawia przepływ pracy i zbiór decyzji związanych z tym procesem:

Rysunek 1. Diagram przedstawiający przepływ pracy deklarowania i prośby o uprawnienia w czasie działania na Androidzie.

Sprawdzanie, czy aplikacja otrzymała już te uprawnienia

Aby sprawdzić, czy użytkownik przyznał już do aplikacji określone uprawnienia, przekaż je do metody ContextCompat.checkSelfPermission(). Ta metoda zwraca PERMISSION_GRANTED lub PERMISSION_DENIED w zależności od tego, czy aplikacja ma odpowiednie uprawnienia.

Wyjaśnij, dlaczego aplikacja potrzebuje tych uprawnień

Okno uprawnień wyświetlane przez system podczas wywoływania funkcji requestPermissions() pokazuje, jakich uprawnień potrzebuje Twoja aplikacja, ale nie podaje, dlaczego. Niekiedy może się to dziwić. Zanim wywołasz funkcję requestPermissions(), warto wyjaśnić użytkownikowi, dlaczego aplikacja potrzebuje tych uprawnień.

Badania pokazują, że użytkownicy znacznie chętniej odpowiadają na prośby o uprawnienia, jeśli wiedzą, do czego aplikacja ich potrzebuje (np. czy są one potrzebne do obsługi głównej funkcji aplikacji lub na potrzeby wyświetlania reklam). Jeśli używasz więc tylko części wywołań interfejsu API, które należą do określonej grupy uprawnień, warto wyraźnie wskazać, 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 na jej temat.

W określonych warunkach warto też na bieżąco informować użytkowników o dostępie do danych wrażliwych. Jeśli na przykład korzystasz z kamery lub mikrofonu, warto dać znać użytkownikowi, klikając ikonę powiadomień w innym miejscu aplikacji lub w obszarze powiadomień (jeśli aplikacja działa w tle). Dzięki temu nie będzie się wydawać, że zbierasz dane w sposób potajemny.

Jeśli musisz poprosić o przyznanie uprawnień, aby coś w aplikacji zadziałało, ale powód nie jest jasny dla użytkownika, znajdź sposób, aby wyjaśnić mu, dlaczego potrzebujesz najbardziej newralgicznych uprawnień.

Jeśli metoda ContextCompat.checkSelfPermission() zwraca wartość PERMISSION_DENIED, wywołaj shouldShowRequestPermissionRationale(). Jeśli ta metoda zwraca wartość true, pokaż użytkownikowi edukacyjny interfejs użytkownika. W tym interfejsie opisz, dlaczego funkcja, którą użytkownik chce włączyć, wymaga konkretnych uprawnień.

Jeśli aplikacja prosi o uprawnienia związane z lokalizacją, mikrofonem lub aparatem, wyjaśnij, dlaczego aplikacja potrzebuje dostępu do tych informacji.

Poproś o uprawnienia

Gdy użytkownik wyświetli interfejs edukacyjny lub zwróci wartość shouldShowRequestPermissionRationale() wskazującą, że nie musisz pokazywać interfejsu edukacyjnego, poproś o odpowiednie uprawnienia. Użytkownicy zobaczą okno uprawnień systemowych, w którym mogą wybrać, czy chcą przyznać aplikacji określone uprawnienia.

W tym celu użyj umowy RequestPermission znajdującej się w bibliotece AndroidaX, gdzie zezwalasz systemowi na zarządzanie kodem prośby o uprawnienia za Ciebie. Umowa RequestPermission upraszcza działanie logiki, 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 żądania uprawnień i uwzględnić ten kod żądania w logice wywołania zwrotnego uprawnienia.

Zezwalaj systemowi na zarządzanie kodem prośby o uprawnienia

Aby umożliwić systemowi zarządzanie kodem żądania powiązanym z prośbą o uprawnienia, dodaj zależności od tych bibliotek w pliku build.gradle modułu:

Następnie możesz skorzystać z jednego z tych zajęć:

Z instrukcji poniżej dowiesz się, jak korzystać z umowy RequestPermission. Proces jest prawie taki sam w przypadku umowy RequestMultiplePermissions.

  1. W logice inicjowania działania lub fragmentu przekazuj implementację ActivityResultCallback w wywołaniu metody registerForActivityResult(). ActivityResultCallback określa, jak aplikacja ma reagować na prośbę o uprawnienia.

    Zachowaj odwołanie do wartości zwróconej wartości registerForActivityResult(), która jest typu ActivityResultLauncher.

  2. Aby w razie potrzeby wyświetlić systemowe okno uprawnień, wywołaj metodę launch() w wystąpieniu ActivityResultLauncher zapisanym w poprzednim kroku.

    Po wywołaniu launch() pojawi się okno uprawnień systemowych. Gdy użytkownik dokona wyboru, system asynchronicznie wywoła Twoją implementację funkcji ActivityResultCallback zdefiniowaną w poprzednim kroku.

    Uwaga: aplikacja nie może dostosować okna wyświetlanego po wywołaniu launch(). Jeśli chcesz przekazać użytkownikowi więcej informacji lub kontekst, zmień interfejs aplikacji tak, aby mogli łatwiej zrozumieć, dlaczego dana funkcja aplikacji wymaga określonych uprawnień. Możesz na przykład zmienić tekst przycisku, który włącza tę funkcję.

    Ponadto tekst w oknie uprawnień systemowych odwołuje się do grupy uprawnień powiązanej z żądanym uprawnieniem. To grupowanie uprawnień zostało zaprojektowane z myślą o wygodzie użytkowania, a aplikacja nie powinna korzystać z uprawnień należących do określonej grupy uprawnień lub spoza niej.

Ten fragment kodu pokazuje, jak obsłużyć 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 prośby o nie od użytkowników, gdy jest to konieczne:

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 żądania uprawnień, możesz samodzielnie zarządzać tym kodem. Aby to zrobić, umieść kod żądania w wywołaniu metody requestPermissions().

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 w oknie uprawnień systemowych, system wywoła w aplikacji implementację onRequestPermissionsResult(). System przekazuje użytkownikowi odpowiedź na okno z prośbą o przyznanie uprawnień 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.
    }
}

Poproś o dostęp do lokalizacji

Gdy prosisz o dostęp do lokalizacji, postępuj zgodnie z tymi samymi sprawdzonymi metodami co w przypadku innych uprawnień dla środowiska wykonawczego. Ważna różnica w przypadku dostępu do lokalizacji polega na tym, że system obejmuje wiele uprawnień związanych z lokalizacją. Uprawnienia, które chcesz uzyskać, i sposób ich wysyłania zależą od wymagań dotyczących lokalizacji w danym przypadku użycia.

Lokalizacja na pierwszym planie

Jeśli aplikacja zawiera funkcję, która udostępnia lub otrzymuje informacje o lokalizacji tylko raz lub przez określony czas, wymaga ona dostępu do lokalizacji na pierwszym planie. Oto kilka przykładów:

  • Funkcja nawigacji zakręt po zakręcie dostępna w aplikacji nawigacyjnej.
  • Funkcja w aplikacji do obsługi wiadomości umożliwia udostępnianie bieżącej lokalizacji innemu użytkownikowi.

System uznaje, że aplikacja korzysta z lokalizacji na pierwszym planie, jeśli jej funkcja uzyskuje dostęp do bieżącej lokalizacji urządzenia w jednej z tych sytuacji:

  • Widoczna będzie aktywność, która należy do Twojej aplikacji.
  • Twoja aplikacja działa na pierwszym planie. Gdy usługa działa na pierwszym planie, system podnosi świadomość użytkownika, wyświetlając stałe powiadomienie. Aplikacja zachowuje dostęp, gdy jest umieszczona w tle, na przykład gdy użytkownik naciśnie przycisk ekranu głównego na urządzeniu lub wyłączy wyświetlacz urządzenia.

    W Androidzie 10 (poziom interfejsu API 29) i nowszych musisz zadeklarować typ usługi na pierwszym planie o wartości location, jak pokazano w tym fragmencie kodu. We wcześniejszych 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>
    

Deklarujesz potrzebę korzystania z lokalizacji na pierwszym planie, gdy aplikacja prosi o uprawnienie ACCESS_COARSE_LOCATION lub ACCESS_FINE_LOCATION, tak jak w tym fragmencie:

<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 jej funkcja stale udostępnia lokalizację innym użytkownikom lub używa interfejsu API geofencingu. Oto kilka przykładów:

  • Funkcja dostępna w aplikacji do udostępniania lokalizacji w grupie rodzinnej umożliwia użytkownikom ciągłe udostępnianie ich lokalizacji członkom grupy rodzinnej.
  • Funkcja dostępna w aplikacji IoT,

System uznaje, że aplikacja korzysta z lokalizacji w tle, jeśli uzyskuje dostęp do bieżącej lokalizacji urządzenia w sytuacji innej niż opisana 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ń dostępu do lokalizacji zadeklarowanych przez aplikację.

W Androidzie 10 (poziom interfejsu API 29) i nowszych musisz zadeklarować w pliku manifestu aplikacji uprawnienie ACCESS_BACKGROUND_LOCATION, aby prosić o dostęp do lokalizacji w tle w czasie działania. Na wcześniejszych wersjach Androida, gdy aplikacja uzyskuje dostęp do lokalizacji na pierwszym planie, automatycznie otrzymuje 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>

Wykonaj odmową przyznania uprawnień

Jeśli użytkownik odmówi przyznania uprawnień, aplikacja powinna pomóc mu zrozumieć konsekwencje odmowy. W szczególności aplikacja powinna informować użytkowników o funkcjach, które nie działają z powodu brakujących uprawnień. Warto przy tym pamiętać o tych sprawdzonych metodach:

  • Pokieruj uwagę użytkownika. Podkreśl ten fragment interfejsu aplikacji, który ma ograniczone funkcje, ponieważ aplikacja nie ma wymaganych uprawnień. Oto kilka przykładów:

    • Pokaż komunikat w miejscu, w którym mogłyby zostać wyświetlone wyniki lub dane danej funkcji.
    • wyświetlać inny przycisk, który zawiera ikonę błędu i kolor.
  • Unikaj ogólników. Nie wyświetlaj ogólnego komunikatu. Zamiast tego wyjaśnij, które funkcje są niedostępne, ponieważ aplikacja nie ma wymaganych uprawnień.

  • Nie blokuj interfejsu użytkownika. Inaczej mówiąc, nie wyświetlaj ostrzeżenia na pełnym ekranie, które uniemożliwia użytkownikom dalsze korzystanie z aplikacji.

Jednocześnie aplikacja powinna respektować decyzję użytkownika dotyczącą odmowy uprawnień. Począwszy od Androida 11 (poziom interfejsu API 30), jeśli użytkownik kliknie Odmów, aby uzyskać dostęp do określonych uprawnień więcej niż raz w trakcie instalacji aplikacji na urządzeniu, nie zobaczy okna z uprawnieniami systemowymi, gdy aplikacja ponownie poprosi o to uprawnienie. Czynność użytkownika oznacza, że nie pytaj ponownie. We wcześniejszych wersjach użytkownicy widzieli okno uprawnień systemowych za każdym razem, gdy aplikacja prosiła o przyznanie uprawnień, chyba że wcześniej zaznaczyli pole wyboru lub opcję „Nie pytaj ponownie”.

Odrzucenie prośby o przyznanie uprawnień więcej niż raz jest rozpatrywane jako odrzucenie na stałe. Pamiętaj, 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 uprawnienia mogą zostać przyznane automatycznie, a użytkownik nie podejmie żadnych działań. (Uprawnienie może też zostać przyznane automatycznie). Nie należy zakładać żadnych zachowań automatycznych. Za każdym razem, gdy aplikacja potrzebuje dostępu do funkcji, które wymagają uprawnień, sprawdź, czy nadal je ma.

Aby zadbać o jak najlepsze wrażenia użytkowników, zapoznaj się z artykułem Sprawdzone metody dotyczące uprawnień aplikacji.

Sprawdzanie stanu odmowy podczas testowania i debugowania

Aby sprawdzić, czy aplikacji nie przyznano trwale uprawnień (do celów debugowania i testowania), użyj tego polecenia:

adb shell dumpsys package PACKAGE_NAME

Gdzie PACKAGE_NAME to nazwa przesyłki do sprawdzenia.

Dane wyjściowe polecenia zawierają takie sekcje:

...
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 odrzucone raz przez użytkownika są oznaczane przez USER_SET. Uprawnienia, które zostały trwale odrzucone przez dwukrotne zaznaczenie opcji Odmów, są oznaczane przez USER_FIXED.

Aby mieć pewność, że testerzy zobaczą okno żądania podczas testowania, zresetuj te flagi po zakończeniu debugowania aplikacji. 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 informacjami o interfejsie API uprawnień.

Uprawnienia jednorazowe

Opcja „Tylko tym razem” jest drugim z trzech przycisków w oknie.
Rysunek 2. Okno systemowe, które wyświetla się, gdy aplikacja prosi o jednorazowe uprawnienie.

Od Androida 11 (poziom interfejsu API 30) za każdym razem, gdy aplikacja prosi o uprawnienia związane z lokalizacją, mikrofonem lub aparatem, okno uprawnień dla użytkownika zawiera opcję Tylko tym razem, jak widać na ilustracji 2. Jeśli użytkownik wybierze tę opcję w oknie, aplikacja otrzyma tymczasowe jednorazowe uprawnienie.

Aplikacja będzie miała dostęp do powiązanych danych przez okres, który zależy od działania aplikacji i działań użytkownika:

  • Aktywność w aplikacji jest widoczna, ale aplikacja ma dostęp do danych.
  • Jeśli użytkownik wyśle aplikację w tle, może ona nadal uzyskiwać dostęp do danych przez krótki czas.
  • Jeśli uruchomisz usługę działającej na pierwszym planie w chwili, gdy aktywność będzie widoczna, a użytkownik przeniesie aplikację w tle, będzie ona mogła nadal z nich korzystać do momentu zatrzymania działania tej usługi.

Proces aplikacji kończy się w momencie unieważnienia uprawnień

Jeśli użytkownik cofnie jednorazowe uprawnienie, np. w ustawieniach systemu, aplikacja nie będzie miała dostępu do danych niezależnie od tego, czy uruchomiono usługę na pierwszym planie. Tak jak w przypadku każdego innego uprawnienia, jeśli użytkownik cofnie swoje jednorazowe uprawnienie, proces aplikacji się zakończy.

Gdy użytkownik ponownie otworzy aplikację, a jej funkcja poprosi o dostęp do lokalizacji, mikrofonu lub aparatu, użytkownik zobaczy prośbę o ponowne przyznanie dostępu.

Zresetuj nieużywane uprawnienia

Android udostępnia kilka sposobów resetowania nieużywanych uprawnień środowiska wykonawczego do stanu domyślnego (odrzuconego):

Usuń dostęp aplikacji

Na Androidzie 13 (poziom interfejsu API 33) i nowszych możesz usunąć dostęp aplikacji do uprawnień w czasie działania, które nie są już wymagane. Przeprowadź ten krok, gdy zaktualizujesz aplikację, aby użytkownicy lepiej zrozumieli, dlaczego aplikacja nadal prosi o określone uprawnienia. Wiedza ta pomaga budować zaufanie użytkowników do Twojej aplikacji.

Aby usunąć dostęp do uprawnienia w czasie działania, przekaż jego nazwę do revokeSelfPermissionOnKill(). Aby jednocześnie usunąć dostęp do grupy uprawnień w czasie działania, przekaż kolekcję nazw uprawnień do revokeSelfPermissionsOnKill(). Proces usuwania uprawnień odbywa się asynchronicznie i zatrzymuje wszystkie procesy powiązane z identyfikatorem UID Twojej aplikacji.

Aby system mógł usunąć dostęp aplikacji do uprawnień, wszystkie powiązane z nią procesy muszą zostać zakończone. Gdy wywołujesz ten interfejs API, system określa, kiedy można bezpiecznie zakończyć ten proces. Zwykle 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 Twoja aplikacja nie wymaga już dostępu do określonych uprawnień czasu działania, przy następnym uruchomieniu aplikacji pokaż okno. Może ono zawierać listę uprawnień.

Automatyczne resetowanie uprawnień nieużywanych aplikacji

Jeśli Twoja aplikacja jest kierowana na Androida 11 (poziom interfejsu API 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 przyznane aplikacji. Więcej informacji znajdziesz w przewodniku o hibernacji aplikacji.

W razie potrzeby poproś o zostanie domyślnym modułem obsługi

Niektóre aplikacje wymagają dostępu do poufnych informacji użytkownika związanych z rejestrami połączeń i SMS-ami. Jeśli chcesz poprosić użytkownika o uprawnienia dotyczące rejestrów połączeń i SMS-ów oraz opublikować aplikację w Sklepie Play, musisz najpierw poprosić użytkownika o ustawienie aplikacji jako domyślnego modułu obsługi głównej funkcji systemu, zanim poprosisz o te uprawnienia w czasie działania.

Więcej informacji na temat domyślnych modułów obsługi, w tym wskazówki na temat wyświetlania użytkownikom promptów domyślnego modułu obsługi, znajdziesz w przewodniku na temat uprawnień używanych tylko w domyślnych modułach obsługi.

Przyznaj wszystkie uprawnienia w czasie działania na potrzeby testowania

Aby automatycznie przyznać wszystkie uprawnienia w czasie działania podczas instalowania aplikacji w emulatorze lub urządzeniu testowym, użyj w poleceniu adb shell install opcji -g, jak 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 przesyłaniu próśb o uprawnienia znajdziesz w przykładowych uprawnieniach.

Możesz też ukończyć to ćwiczenie z programowania, które pokazuje sprawdzone metody ochrony prywatności.