Wysyłanie prośby o dostęp do lokalizacji w czasie działania

Jeśli funkcja w aplikacji wymaga dostępu do lokalizacji, poczekaj, aż użytkownik zacznie z niej korzystać, a dopiero potem poproś o uprawnienia. Ten proces jest zgodny ze sprawdzoną metodą polegającą na prośbach o uprawnienia w kontekście w czasie działania aplikacji, jak opisano w przewodniku Prośby o uprawnienia aplikacji.

Rysunek 1 przedstawia przykładowy sposób wykonania tego procesu. Aplikacja zawiera funkcję „udostępnianie lokalizacji”, która wymaga dostępu do lokalizacji na pierwszym planie. Aplikacja nie prosi o dostęp do lokalizacji, dopóki użytkownik nie kliknie przycisku Udostępnij lokalizację.

Gdy użytkownik kliknie przycisk Udostępnij lokalizację, pojawi się okno z prośbą o dostęp do lokalizacji
Rysunek 1. Funkcja udostępniania lokalizacji, która wymaga dostępu do lokalizacji na pierwszym planie. Funkcja jest włączona, jeśli użytkownik wybierze Zezwalaj tylko podczas używania aplikacji.

Użytkownik może udostępnić tylko przybliżoną lokalizację.

W systemie Android 12 (poziom API 31) lub nowszym użytkownicy mogą poprosić aplikację o pobieranie tylko przybliżonych informacji o lokalizacji, nawet jeśli aplikacja poprosi o uprawnienia w czasie działania ACCESS_FINE_LOCATION.

Aby uwzględnić to potencjalne zachowanie użytkowników, nie proś o same uprawnienia ACCESS_FINE_LOCATION. Zamiast tego poproś o uprawnienia ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION w jednym żądaniu w czasie wykonywania. Jeśli spróbujesz wysłać tylko prośbę ACCESS_FINE_LOCATION, system zignoruje ją w niektórych wersjach Androida 12. Jeśli Twoja aplikacja jest kierowana na Androida 12 lub nowszego, system zapisze w Logcat ten komunikat o błędzie:

ACCESS_FINE_LOCATION must be requested with ACCESS_COARSE_LOCATION.

Gdy aplikacja prosi o uprawnienia ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION, w oknie uprawnień systemowych użytkownik ma do wyboru te opcje:

  • Dokładna: aplikacja może uzyskać dokładne informacje o lokalizacji.
  • Przybliżona: aplikacja może uzyskać tylko przybliżone informacje o lokalizacji.

Rysunek 3 pokazuje, że okno zawiera wizualne wskazówki dotyczące obu opcji, aby ułatwić użytkownikowi dokonanie wyboru. Po wybraniu dokładności lokalizacji użytkownik klika jeden z 3 przycisków, aby wybrać czas trwania przyznanych uprawnień.

W Androidzie 12 i nowszych użytkownicy mogą przejść do ustawień systemu, aby ustawić preferowaną dokładność lokalizacji dla dowolnej aplikacji, niezależnie od wersji docelowego pakietu SDK tej aplikacji. To ograniczenie obowiązuje nawet wtedy, gdy aplikacja jest zainstalowana na urządzeniu z Androidem 11 lub starszym, a użytkownik zaktualizuje urządzenie do Androida 12 lub nowszej wersji.

Dialog dotyczy tylko przybliżonej lokalizacji i zawiera 3 przyciski, jeden nad drugim
Rysunek 2. Okno uprawnień systemowych, które pojawia się, gdy aplikacja prosi o dostęp do ACCESS_COARSE_LOCATION.
Okno zawiera 2 zestawy opcji, jeden nad drugim
Rysunek 3. Okno uprawnień systemowych, które pojawia się, gdy aplikacja prosi o dostęp do ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION w jednym żądaniu w czasie działania.

Wybór użytkownika wpływa na przyznanie uprawnień

Poniższa tabela zawiera uprawnienia, które system przyznaje aplikacji na podstawie opcji wybranych przez użytkownika w oknie uprawnień:

Dokładnie W przybliżeniu
Podczas używania aplikacji ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
ACCESS_COARSE_LOCATION
Tylko tym razem ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
ACCESS_COARSE_LOCATION
Odrzuć Brak uprawnień do lokalizacji Brak uprawnień do lokalizacji

Aby sprawdzić, jakie uprawnienia system przyznał aplikacji, sprawdź wartość zwracaną przez prośbę o uprawnienia. W kodzie możesz użyć bibliotek Jetpacka podobnych do tego przykładu lub bibliotek platformy, w których samodzielnie zarządzasz kodem prośby o uprawnienia.

Kotlin

@RequiresApi(Build.VERSION_CODES.N)
fun requestPermissions() {
    val locationPermissionRequest = registerForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) { permissions ->
        when {
            permissions.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false) -> {
                // Precise location access granted.
            }
            permissions.getOrDefault(Manifest.permission.ACCESS_COARSE_LOCATION, false) -> {
                // Only approximate location access granted.
            }
            else -> {
                // No location access granted.
            }
        }
    }

    // Before you perform the actual permission request, check whether your app
    // already has the permissions, and whether your app needs to show a permission
    // rationale dialog. For more details, see Request permissions:
    // https://developer.android.com/training/permissions/requesting#request-permission
    locationPermissionRequest.launch(
        arrayOf(
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION
        )
    )
}

Java

private void requestPermissions() {

    ActivityResultLauncher<String[]> locationPermissionRequest =
            registerForActivityResult(new ActivityResultContracts
                            .RequestMultiplePermissions(), result -> {

                Boolean fineLocationGranted = null;
                Boolean coarseLocationGranted = null;

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    fineLocationGranted = result.getOrDefault(
                            Manifest.permission.ACCESS_FINE_LOCATION, false);
                    coarseLocationGranted = result.getOrDefault(
                            Manifest.permission.ACCESS_COARSE_LOCATION,false);
                }

                if (fineLocationGranted != null && fineLocationGranted) {
                    // Precise location access granted.
                } else if (coarseLocationGranted != null && coarseLocationGranted) {
                    // Only approximate location access granted.
                } else {
                    // No location access granted.
                }
            }
        );

    // ...

    // Before you perform the actual permission request, check whether your app
    // already has the permissions, and whether your app needs to show a permission
    // rationale dialog. For more details, see Request permissions.
    locationPermissionRequest.launch(new String[] {
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION
    });
}

Prośba o uaktualnienie do dokładnej lokalizacji

Możesz poprosić użytkownika o zmianę dostępu aplikacji z przybliżonej lokalizacji na dokładną lokalizację. Zanim poprosisz użytkownika o udostępnienie aplikacji dostępu do dokładnej lokalizacji, zastanów się, czy Twój przypadek użycia aplikacji absolutnie wymaga takiego poziomu dokładności. Jeśli Twoja aplikacja musi sparować urządzenie z urządzeniami w pobliżu przez Bluetootha lub Wi-Fi, rozważ użycie parowania urządzenia towarzyszącego lub uprawnień Bluetootha zamiast prosić o uprawnienia ACCESS_FINE_LOCATION.

Aby poprosić użytkownika o zmianę z przybliżonego na dokładny dostępu aplikacji do lokalizacji:

  1. W razie potrzeby wyjaśnij, dlaczego aplikacja potrzebuje tego uprawnienia.
  2. Poproś o uprawnienia ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION ponownie. Użytkownik zezwolił już systemowi na udostępnienie aplikacji przybliżonej lokalizacji, więc tym razem okno systemu będzie wyglądać inaczej niż na rysunkach 4 i 5:
W oknie znajdują się opcje „Zmień na dokładną lokalizację”, „Tylko tym razem” i „Odrzuć”.
Rysunek 4. Użytkownik wcześniej wybrał W przybliżeniuPodczas korzystania z aplikacji (w oknie rysunku 3).
W oknie znajdują się opcje „Tylko tym razem” i „Odmów”.
Rysunek 5. Użytkownik wcześniej wybrał PrzybliżoneTylko tym razem (w oknie z rysunku 3).

Początkowo żądaj tylko lokalizacji na pierwszym planie

Nawet jeśli kilka funkcji w aplikacji wymaga dostępu do lokalizacji, prawdopodobnie tylko niektóre z nich wymagają dostępu do lokalizacji w tle. Dlatego zalecamy, aby aplikacja wysyłała stopniowe żądania dostępu do lokalizacji, prosząc najpierw o dostęp do lokalizacji na pierwszym planie, a potem w tle. Dzięki żądaniom stopniowym użytkownicy zyskują większą kontrolę i przejrzystość, ponieważ mogą lepiej zrozumieć, które funkcje aplikacji potrzebują dostępu do lokalizacji w tle.

Na rysunku 6. widać przykład aplikacji, która obsługuje dodatkowe żądania. Zarówno funkcja „Pokaż bieżącą lokalizację”, jak i „Polecaj miejsca w pobliżu” wymagają dostępu do lokalizacji na pierwszym planie. Tylko funkcja „polecanie miejsc w pobliżu” wymaga dostępu do lokalizacji w tle.

Przycisk, który umożliwia dostęp do lokalizacji na pierwszym planie, znajduje się w odległości połowy długości ekranu od przycisku, który umożliwia dostęp do lokalizacji w tle.
Rysunek 6. Obie funkcje wymagają dostępu do lokalizacji, ale tylko funkcja „polecanie funkcji w pobliżu” wymaga dostępu do lokalizacji w tle.

Proces wykonywania żądań przyrostowych:

  1. Aplikacja powinna najpierw kierować użytkowników do funkcji, które wymagają dostępu do lokalizacji na pierwszym planie, takich jak funkcja „Udostępnij lokalizację” na rysunku 1 lub funkcja „Pokaż aktualną lokalizację” na rysunku 2.

    Zalecamy wyłączenie dostępu użytkowników do funkcji, które wymagają dostępu do lokalizacji w tle, dopóki aplikacja nie będzie mieć dostępu do lokalizacji na pierwszym planie.

  2. Gdy użytkownik będzie korzystać z funkcji wymagających dostępu do lokalizacji w tle, możesz poprosić o dostęp do lokalizacji w tle.

Dodatkowe materiały

Więcej informacji o uprawnieniach dostępu do lokalizacji w Androidzie znajdziesz w tych materiałach:

Ćwiczenia z programowania

Filmy

Próbki