Google Play Hizmetleri ve çalışma zamanı izinleri

Android 6.0 Marshmallow'dan beri Android, uygulama yükleme ve otomatik güncelleme sürecini kolaylaştıran bir izin modeli kullanır. İzinler, uygulama yüklenmeden önce değil, çalışma zamanında istenir. Ayrıca, kullanıcılar belirli izinleri reddedebilir. Kullanıcılara bu esnekliği sunmak için, uygulamanızın kullanıcı belirli bir izni etkinleştirdiğinde veya devre dışı bıraktığında beklendiği gibi davrandığından emin olmanız gerekir.

Google Play Hizmetleri'nin kendisinde, kullanıcıların uygulamanız tarafından özellikle istenen izinlerden ayrı olarak reddedebileceği çalışma zamanı izinleri vardır. Google Play Hizmetleri, API'lerini desteklemek için ihtiyaç duyduğu tüm izinleri otomatik olarak alır. Ancak uygulamanız, çalışma zamanı izinlerini gerektiği gibi kontrol etmeli ve istemeli, ayrıca kullanıcının uygulamanızın kullandığı bir API için Google Play Hizmetleri'ne gerekli izni vermediği durumlarda hataları uygun şekilde işlemelidir.

Çalışma zamanının gerektirebileceği izinleri ayarlarken kullanıcının beklentilerini yönetmek iyi bir uygulamadır. Aşağıdaki en iyi uygulamalar, olası sorunlardan kaçınmanıza yardımcı olur.

Ön koşullar

İzinleri AndroidManifest.xml dosyanızda beyan etmeniz gerekir. Örneğin:

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

Yönergeler

API'leri çağırmadan önce izinleri doğrulama

AndroidManifest.xml dosyanızda kullanmak istediğiniz API'leri beyan ettikten sonra bir API'yi çağırmadan önce gerekli izne sahip olduğunuzu doğrulayın. Bu işlem, ActivityCompat veya ContextCompat checkSelfPermission yöntemi kullanılarak yapılabilir.

Çağrı yanlış değerini döndürürse izinlerin verilmediği anlamına gelir ve bunları istemek için requestPermissions kullanmanız gerekir. Bunun yanıtı, sonraki adımda göreceğiniz bir geri çağırmada döndürülür.

Örneğin:

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

İzin isteği geri çağırmasını uygulama

Uygulamanızın ihtiyaç duyduğu izin kullanıcı tarafından verilmediyse kullanıcıdan izin vermesini istemek için requestPermissions yöntemi çağrılmalıdır. Kullanıcının yanıtı onRequestPermissionsResult geri çağırma işlevinde yakalanır. Uygulamanız bu işlevi uygulamalı ve istek reddedilebileceği veya iptal edilebileceği için her zaman dönüş değerlerini kontrol etmelidir. Aynı anda birden fazla izin isteğinde bulunabilir ve bunları kontrol edebilirsiniz. Aşağıdaki örnekte yalnızca tek bir izin kontrol edilmektedir.

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

İzin gerekçesini gösterme

Uygulamanızın istediği izinler, uygulamanın temel özellikleri için gerekliyse ve kullanıcı daha önce izin isteğini reddettiyse uygulamanız izni tekrar istemeden önce ek bir açıklama göstermelidir. Kullanıcıların, iznin neden gerekli olduğunu ve kendilerine sağlayacağı anlık faydayı anladıklarında izin verme olasılığı daha yüksektir.

Bu durumda, requestPermissions adlı kişiyi aramadan önce shouldShowRequestPermissionRationale adlı kişiyi aramanız gerekir. Doğru (true) değeri döndürürse izinle ilgili ek bağlamı göstermek için bir kullanıcı arayüzü oluşturmanız gerekir.

Örneğin, kodunuz aşağıdaki gibi görünebilir:

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

Google Play Hizmetleri API çağrıları, kullanıcının izin çözümü amacını başlatmak için dokunabileceği bir iletişim kutusu (istemci Activity ile başlatılmışsa) veya sistem tepsisi bildirimi (istemci Context ile başlatılmışsa) gösterir. İzin verildikten sonra aramalar sıraya alınır ve yeniden denenir.