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

Gdy funkcja w aplikacji potrzebuje dostępu do lokalizacji, poczekaj, aż użytkownik wejdzie z nią w interakcję, zanim wyślesz prośbę o uprawnienia. Ten proces jest zgodny ze sprawdzoną metodą proszenia o uprawnienia w czasie działania w odpowiednim kontekście, co opisano w przewodniku dotyczącym tego, jak prosić o uprawnienia aplikacji.

Rysunek 1 przedstawia przykład tego procesu. Aplikacja zawiera funkcję „udostępnij lokalizację”, która wymaga dostępu do lokalizacji na pierwszym planie. Aplikacja nie prosi jednak o uprawnienia dostępu 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 przyznanie uprawnień dostępu 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 przyznać dostęp tylko do przybliżonej lokalizacji

Na Androidzie 12 (API na poziomie 31) lub nowszym użytkownicy mogą zażądać, aby aplikacja pobierała tylko informacje o przybliżonej lokalizacji, nawet jeśli prosi ona o ACCESS_FINE_LOCATION w czasie działania.

Aby obsłużyć takie potencjalne zachowanie użytkownika, nie proś o uprawnienie ACCESS_FINE_LOCATION samodzielnie. Zamiast tego w jednym żądaniu w czasie działania poproś o uprawnienia ACCESS_FINE_LOCATION i ACCESS_COARSE_LOCATION. Jeśli spróbujesz poprosić tylko o ACCESS_FINE_LOCATION, system zignoruje to żądanie 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: w Logcat:

ACCESS_FINE_LOCATION must be requested with ACCESS_COARSE_LOCATION.

Gdy aplikacja prosi o ACCESS_FINE_LOCATION i ACCESS_COARSE_LOCATION, okno uprawnień systemowych zawiera te opcje dla użytkownika:

  • Precyzyjne: umożliwia aplikacji uzyskiwanie dokładnych informacji o lokalizacji.
  • Przybliżona: umożliwia aplikacji uzyskiwanie tylko przybliżonych informacji o lokalizacji.

Rysunek 3 pokazuje, że okno dialogowe zawiera wizualne wskazówki dotyczące obu opcji, aby ułatwić użytkownikowi wybór. Gdy użytkownik zdecyduje się na dokładność lokalizacji, kliknie jeden z 3 przycisków, aby wybrać czas trwania przyznania uprawnień.

Na Androidzie 12 i nowszym użytkownicy mogą przejść do ustawień systemowych, aby ustawić preferowaną dokładność lokalizacji dla dowolnej aplikacji, niezależnie od wersji pakietu SDK, na którą jest ona kierowana. Dotyczy to również sytuacji, gdy aplikacja jest zainstalowana na urządzeniu z Androidem 11 lub starszym, a następnie użytkownik uaktualni urządzenie do Androida 12 lub nowszego.

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

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

W tabeli poniżej przedstawiono uprawnienia, które system przyznaje aplikacji, w zależności od opcji wybranych przez użytkownika w oknie uprawnień w czasie działania:

Precyzyjne Przybliżona
Podczas używania aplikacji ACCESS_FINE_LOCATION i
ACCESS_COARSE_LOCATION
ACCESS_COARSE_LOCATION
Tylko tym razem ACCESS_FINE_LOCATION i
ACCESS_COARSE_LOCATION
ACCESS_COARSE_LOCATION
Odrzuć Brak uprawnień dostępu do lokalizacji Brak uprawnień dostępu do lokalizacji

Aby sprawdzić, które uprawnienia system przyznał Twojej aplikacji, sprawdź wartość zwracaną przez żądanie uprawnień. Możesz używać bibliotek Jetpack w kodzie podobnym do tego poniżej 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 uaktualnienie dostępu aplikacji z przybliżonej lokalizacji do dokładnej lokalizacji. Zanim poprosisz użytkownika o uaktualnienie dostępu aplikacji do dokładnej lokalizacji, zastanów się, czy przypadek użycia aplikacji absolutnie wymaga tego poziomu dokładności. Jeśli Twoja aplikacja musi sparować urządzenie z urządzeniami w pobliżu przez Bluetooth lub Wi-Fi, rozważ użycie parowania urządzeń towarzyszących lub uprawnień Bluetooth zamiast proszenia o uprawnienie ACCESS_FINE_LOCATION.

Aby poprosić użytkownika o uaktualnienie dostępu aplikacji do lokalizacji z przybliżonej na dokładną:

  1. W razie potrzeby wyjaśnij, dlaczego aplikacja potrzebuje tego uprawnienia.
  2. Ponownie poproś o uprawnienia ACCESS_FINE_LOCATION i ACCESS_COARSE_LOCATION. Ponieważ użytkownik zezwolił już systemowi na przyznanie aplikacji dostępu do przybliżonej lokalizacji, okno systemowe będzie tym razem inne, jak pokazano na rysunku 4 i 5:
W oknie dialogowym znajdują się opcje „Zmień na dokładną lokalizację”, „Tylko tym razem” i „Odmów”.
Rysunek 4. Użytkownik wybrał wcześniej Przybliżona i Podczas używania aplikacji (w oknie z rysunku 3).
W oknie dialogowym wyświetlają się opcje „Tylko tym razem” i „Odmów”.
Rysunek 5. Użytkownik wybrał wcześniej Przybliżona i Tylko tym razem (w oknie z rysunku 3).

Początkowo proś tylko o dostęp do 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 żądania stopniowe uprawnień dostępu do lokalizacji, prosząc najpierw o dostęp do lokalizacji na pierwszym planie, a potem o dostęp do lokalizacji w tle. Wysyłając żądania stopniowe, dajesz użytkownikom większą kontrolę i przejrzystość, ponieważ mogą oni lepiej zrozumieć, które funkcje w aplikacji potrzebują dostępu do lokalizacji w tle.

Rysunek 6 przedstawia przykład aplikacji, która jest zaprojektowana do obsługi żądań stopniowych. Zarówno funkcja „pokaż bieżącą lokalizację”, jak i „poleć miejsca w pobliżu” wymagają dostępu do lokalizacji na pierwszym planie. Tylko funkcja „poleć miejsca w pobliżu” wymaga jednak dostępu do lokalizacji w tle.

Przycisk, który umożliwia dostęp do lokalizacji na pierwszym planie, znajduje się w połowie 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 „poleć miejsca w pobliżu” wymaga dostępu do lokalizacji w tle.

Proces wysyłania żądań stopniowych wygląda tak:

  1. Na początku aplikacja powinna 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ż bieżącą 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 uzyska dostępu do lokalizacji na pierwszym planie.

  2. Później, gdy użytkownik będzie korzystać z funkcji, które wymagają 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:

Codelabs

Filmy

Przykłady