Google Play-Dienste und Laufzeitberechtigungen

Seit Android 6.0 Marshmallow verwendet Android ein Berechtigungsmodell, das die Installation und automatische Aktualisierung von Apps vereinfacht. Berechtigungen werden während der Laufzeit und nicht vor der Installation der App angefordert. Außerdem können Nutzer bestimmte Berechtigungen ablehnen. Damit Nutzer diese Flexibilität haben, muss Ihre App sich wie erwartet verhalten, wenn ein Nutzer eine bestimmte Berechtigung aktiviert oder deaktiviert.

Google Play-Dienste selbst haben Laufzeitberechtigungen, die Nutzer separat von den Berechtigungen ablehnen können, die speziell von Ihrer App angefordert werden. Google Play-Dienste erhalten automatisch alle Berechtigungen, die für die Unterstützung der APIs erforderlich sind. Ihre App sollte jedoch weiterhin Laufzeitberechtigungen prüfen und anfordern, wenn dies erforderlich ist, und Fehler angemessen behandeln, wenn ein Nutzer Google Play-Diensten eine Berechtigung verweigert hat, die für eine von Ihrer App verwendete API erforderlich ist.

Es ist ratsam, die Erwartungen des Nutzers zu berücksichtigen, wenn Sie Berechtigungen festlegen, die die Laufzeit möglicherweise erfordert. Die folgenden Best Practices helfen Ihnen, potenzielle Probleme zu vermeiden.

Vorbereitung

Sie müssen Berechtigungen in der Datei AndroidManifest.xml deklarieren. Beispiel:

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

Richtlinien

Berechtigungen vor dem Aufrufen von APIs prüfen

Nachdem Sie die APIs deklariert haben, die Sie in Ihrer AndroidManifest.xml-Datei verwenden möchten, müssen Sie prüfen, ob Sie die erforderliche Berechtigung haben, bevor Sie eine API aufrufen. Dazu können Sie die Methode checkSelfPermission von ActivityCompat oder ContextCompat verwenden.

Wenn der Aufruf „false“ zurückgibt, bedeutet das, dass die Berechtigungen nicht erteilt wurden und Sie requestPermissions verwenden sollten, um sie anzufordern. Die Antwort darauf wird in einem Callback zurückgegeben, den Sie im nächsten Schritt sehen.

Beispiel:

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();
    }

Callback für Berechtigungsanfrage implementieren

Wenn die von Ihrer App benötigte Berechtigung vom Nutzer nicht erteilt wurde, sollte die Methode requestPermissions aufgerufen werden, um den Nutzer aufzufordern, sie zu erteilen. Die Antwort des Nutzers wird im onRequestPermissionsResult-Callback erfasst. Ihre App sollte dies implementieren und immer die Rückgabewerte prüfen, da die Anfrage abgelehnt oder abgebrochen werden kann. Sie können auch mehrere Berechtigungen gleichzeitig anfordern und prüfen. Im folgenden Beispiel wird nur eine einzelne Berechtigung geprüft.

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
            }
        }
    }

Begründung für die Berechtigung anzeigen

Wenn die von Ihrer App angeforderten Berechtigungen für die Kernfunktionen der App erforderlich sind und der Nutzer die Berechtigungsanfrage zuvor abgelehnt hat, sollte Ihre App eine zusätzliche Erklärung anzeigen, bevor sie die Berechtigung noch einmal anfordert. Nutzer erteilen Berechtigungen eher, wenn sie verstehen, warum die Berechtigung erforderlich ist und welchen unmittelbaren Vorteil sie davon haben.

In diesem Fall sollten Sie vor dem Aufrufen von requestPermissions shouldShowRequestPermissionRationale aufrufen. Wenn „true“ zurückgegeben wird, sollten Sie eine Benutzeroberfläche erstellen, um zusätzlichen Kontext für die Berechtigung anzuzeigen.

Ihr Code könnte beispielsweise so aussehen:

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();
    }

Bei API-Aufrufen für Google Play-Dienste wird automatisch entweder ein Dialogfeld (wenn der Client mit einem Activity instanziiert wird) oder eine Benachrichtigung in der Systemleiste (wenn der Client mit einem Context instanziiert wird) angezeigt, auf die der Nutzer tippen kann, um die Intent zur Berechtigungsauflösung zu starten. Anrufe werden in die Warteschlange gestellt und noch einmal versucht, sobald die Berechtigung erteilt wurde.