Usługi Google Play i uprawnienia w czasie wykonywania

Od Androida 6.0 Marshmallow system ten korzysta z modelu uprawnień, który upraszcza proces instalacji aplikacji i automatycznej aktualizacji. Uprawnienia są wymagane w czasie działania aplikacji, a nie przed jej instalacją. Użytkownicy mogą też odrzucić konkretne uprawnienia. Aby zapewnić użytkownikom taką elastyczność, musisz zadbać o to, aby aplikacja działała zgodnie z oczekiwaniami, gdy użytkownik włącza lub wyłącza określone uprawnienie.

Usługi Google Play mają własne uprawnienia w czasie działania, które użytkownicy mogą odrzucić niezależnie od uprawnień wymaganych przez Twoją aplikację. Usługi Google Play automatycznie uzyskują wszystkie uprawnienia potrzebne do obsługi interfejsów API. Aplikacja powinna jednak w razie potrzeby sprawdzać uprawnienia w czasie działania i o nie prosić oraz odpowiednio obsługiwać błędy w przypadkach, gdy użytkownik odmówi usługom Google Play uprawnienia wymaganego przez interfejs API używany przez aplikację.

Warto zarządzać oczekiwaniami użytkownika podczas ustawiania uprawnień, których może wymagać środowisko wykonawcze. Te sprawdzone metody pomogą Ci uniknąć potencjalnych problemów.

Wymagania wstępne

Uprawnienia musisz zadeklarować w pliku AndroidManifest.xml. Na przykład:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

Wytyczne

Sprawdzanie uprawnień przed wywołaniem interfejsów API

Po zadeklarowaniu interfejsów API, których chcesz używać w pliku AndroidManifest.xml, przed wywołaniem interfejsu API sprawdź, czy masz wymagane uprawnienia. Możesz to zrobić za pomocą metody checkSelfPermission w przypadku ActivityCompat lub ContextCompat.

Jeśli wywołanie zwraca wartość false, oznacza to, że uprawnienia nie zostały przyznane i należy użyć funkcji requestPermissions, aby o nie poprosić. Odpowiedź na to żądanie jest zwracana w wywołaniu zwrotnym, które zobaczysz w następnym kroku.

Na przykład:

Kotlin

    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
        != PackageManager.PERMISSION_GRANTED) {
            // Request Permissions Now
            ActivityCompat.requestPermissions(
                this,
                arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
                REQUEST_LOCATION_PERMISSION_CODE)
    } else {
        // permission has been granted, continue as usual
        val locationResult = LocationServices
            .getFusedLocationProviderClient(this /* Context */)
            .lastLocation
    }

Java

    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
        != PackageManager.PERMISSION_GRANTED) {
        // Request Permissions Now
        ActivityCompat.requestPermissions(
            this,
            new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
            REQUEST_LOCATION_PERMISSION_CODE);
    } else {
        // permission has been granted, continue as usual
        Task locationResult = LocationServices
            .getFusedLocationProviderClient(this /** Context */)
            .getLastLocation();
    }

Zaimplementuj wywołanie zwrotne prośby o uprawnienia

Jeśli użytkownik nie przyznał uprawnień, których potrzebuje Twoja aplikacja, należy wywołać metodę requestPermissions, aby poprosić użytkownika o ich przyznanie. Odpowiedź użytkownika jest rejestrowana w wywołaniu zwrotnym onRequestPermissionsResult. Aplikacja powinna to zaimplementować i zawsze sprawdzać zwracane wartości, ponieważ żądanie może zostać odrzucone lub anulowane. Możesz też poprosić o kilka uprawnień naraz i sprawdzić, czy zostały przyznane. Poniższy przykład sprawdza tylko jedno uprawnienie.

Kotlin

    fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array,
        grantResults: IntArray
    ) {
        if (requestCode == REQUEST_LOCATION_PERMISSION_CODE) {
            if (grantResults.singleOrNull() == PackageManager.PERMISSION_GRANTED) {
               // We can now safely use the API we requested access to
               val locationResult: Task = LocationServices
                    .getFusedLocationProviderClient(this /* Context */)
                    .lastLocation // Request the last known location.
            } else {
                // Permission was denied or request was cancelled
            }
        }
    }

Java

    public void onRequestPermissionsResult(int requestCode,
                                            String[] permissions,
                                            int[] grantResults) {
        if (requestCode == REQUEST_LOCATION_PERMISSION_CODE) {
            if(grantResults.length == 1
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // We can now safely use the API we requested access to
                Task locationResult = LocationServices
                    .getFusedLocationProviderClient(this /** Context */)
                    .getLastLocation(); // Request the last known location.
            } else {
                // Permission was denied or request was cancelled
            }
        }
    }

Wyświetlanie uzasadnienia uprawnień

Jeśli uprawnienia, o które prosi aplikacja, są niezbędne do działania jej podstawowych funkcji, a użytkownik wcześniej odrzucił prośbę o przyznanie uprawnień, przed ponownym wysłaniem prośby aplikacja powinna wyświetlić dodatkowe wyjaśnienie. Użytkownicy chętniej przyznają uprawnienia, gdy rozumieją, dlaczego są one potrzebne i jakie korzyści z nich wynikają.

W takim przypadku przed wywołaniem funkcji requestPermissions należy wywołać funkcję shouldShowRequestPermissionRationale. Jeśli zwróci wartość „true”, musisz utworzyć interfejs, który będzie wyświetlać dodatkowy kontekst uprawnień.

Twój kod może na przykład wyglądać tak:

Kotlin

    private const val REQUEST_LOCATION_PERMISSION_CODE = 2
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
        != PackageManager.PERMISSION_GRANTED) {
        // Check Permissions Now
        if ActivityCompat.shouldShowRequestPermissionRationale(
            this,
            Manifest.permission.ACCESS_FINE_LOCATION
        ) {
            // Display UI and wait for user interaction
        } else {
            ActivityCompat.requestPermissions(
                this,
                arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
                REQUEST_LOCATION_PERMISSION_CODE)
        }
    } else {
        // Permission has already been granted, continue as usual
        val locationResult: Task = LocationServices
            .getFusedLocationProviderClient(this /* Context */)
            .lastLocation
    }

Java

    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
        != PackageManager.PERMISSION_GRANTED) {
        // Check Permissions Now
        private static final int REQUEST_LOCATION_PERMISSION_CODE = 2;
        if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                Manifest.permission.ACCESS_FINE_LOCATION)) {
            // Display UI and wait for user interaction
        } else {
            ActivityCompat.requestPermissions(
                this, new String[]{Manifest.permission.LOCATION_FINE},
                REQUEST_LOCATION_PERMISSION_CODE);
        }
    } else {
        // permission has been granted, continue as usual
        Task locationResult = LocationServices
            .getFusedLocationProviderClient(this /** Context */)
            .getLastLocation();
    }

Wywołania interfejsu API Usług Google Play będą automatycznie wyświetlać okno (jeśli klient jest tworzony za pomocą Activity) lub powiadomienie na pasku systemowym (jeśli klient jest tworzony za pomocą Context), które użytkownik może kliknąć, aby uruchomić intencję rozwiązania problemu z uprawnieniami. Po przyznaniu uprawnień połączenia zostaną umieszczone w kolejce i ponowione.