خدمات Google Play وأذونات وقت التشغيل

وحيث إن Android 6.0 Marshmallow، يستخدم Android نموذج الأذونات الذي يساعد على تبسيط عملية تثبيت التطبيق عملية التحديث التلقائي. يتم طلب الأذونات في وقت التشغيل بدلاً من طلبها قبل تثبيت التطبيق. بالإضافة إلى ذلك، يمكن للمستخدمين اختيار رفض أذونات محدّدة. ولمنح المستخدمين هذه المرونة، يجب التأكّد من أنّ تطبيقك يعمل متوقع عندما يقوم المستخدم بتمكين أو تعطيل إذن معين.

وتتضمّن "خدمات Google Play" نفسها أذونات تشغيل يمكن للمستخدمين اختيار تنفيذها. بشكل منفصل عن تلك الأذونات التي تطلبها أنت التطبيق. تحصل "خدمات Google Play" تلقائيًا على جميع الأذونات التي تحتاج إليها. لتتوافق مع واجهات برمجة التطبيقات الخاصة بها. مع ذلك، يجب أن يتحقّق التطبيق من وقت التشغيل ويطلبه. الأذونات حسب الضرورة والتعامل مع الأخطاء بشكل مناسب في الحالات التي يكون فيها المستخدم لم يمنح "خدمات Google Play" إذنًا مطلوبًا لواجهة برمجة التطبيقات التي يستخدمها تطبيقك.

من الممارسات الجيدة إدارة توقعات المستخدم في تعيين الأذونات التي التي قد تتطلبها بيئة التشغيل. ستساعدك أفضل الممارسات التالية على تجنب والأخطاء المحتملة.

المتطلبات الأساسية

عليك الإفصاح عن الأذونات في ملف AndroidManifest.xml. على سبيل المثال:

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

الإرشادات

التحقّق من الأذونات قبل طلب واجهات برمجة التطبيقات

بعد إعلان واجهات برمجة التطبيقات التي تريد استخدامها في ملف AndroidManifest.xml، يرجى التأكد من أن لديك الإذن المطلوب قبل طلب واجهة برمجة تطبيقات. يمكن إجراء ذلك باستخدام الطريقة checkSelfPermission. عن ActivityCompat أو ContextCompat.

إذا ظهر خطأ في المكالمة، هذا يعني أنّه لم يتم منحك الأذونات وأنّك يجب استخدام requestPermissions لطلبها. الرد على هذا هو في معاودة اتصال والذي سيظهر لك في الخطوة التالية.

على سبيل المثال:

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

تنفيذ طلب معاودة الاتصال بإذن الطلب

إذا لم يمنح المستخدم الإذن الذي يحتاجه، سيتم تغيير يجب استدعاء طريقة requestPermissions لطلب المستخدم لمنحها. يتم تسجيل الرد من المستخدم في onRequestPermissionsResult معاودة الاتصال. يجب أن وتنفيذ ذلك والتحقق دائمًا من القيم المعروضة لأن الطلب قد يكون مرفوض أو ملغا. يمكنك أيضًا طلب أذونات متعددة والتحقق منها من خلال مرة واحدة--يتحقق النموذج التالي فقط من إذن واحد.

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

عرض أسباب الإذن

إذا كانت الأذونات التي يطلبها تطبيقك ضرورية للميزات الأساسية تطبيقك ورفض المستخدم طلب الإذن سابقًا، يجب على التطبيق عرض شرح إضافي قبل طلب الإذن مرة أخرى. المستخدمون من المرجح أن يمنحوا الأذونات عندما يفهمون سبب اللازمة والفائدة الفورية لها.

في هذه الحالة، قبل الاتصال بـ requestPermissions، يجب الاتصال shouldShowRequestPermissionRationale في حال إرجاع صحيح، يجب عليك إنشاء بعض واجهة المستخدم لعرض سياق إضافي إذن.

على سبيل المثال، قد تظهر التعليمة البرمجية على النحو التالي:

if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
    != PackageManager.PERMISSION_GRANTED) {
    // Check Permissions Now
    private static final int REQUEST_LOCATION = 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},
            ACCESS_FINE_LOCATION);
    }
} else {
    // permission has been granted, continue as usual
    Task<Location> locationResult = LocationServices
        .getFusedLocationProviderClient(this /** Context */)
        .getLastLocation();
}

التعامل مع حالات تعذُّر الاتصال

إذا كان تطبيقك يستخدم رمز GoogleApiClient المتوقّف، عند الاتصال connect()، تتحقّق "خدمات Google Play" من توفّر جميع الأذونات اللازمة. يتعذّر تفعيل connect() عند تفعيل أي مجموعات أذونات التي تحتاجها "خدمات Google Play" نفسها غير متوفّرة.

إذا تعذّر الاتصال برقم connect()، تأكَّد من أنّ تطبيقك يعالج تعذّر الاتصال بشكلٍ صحيح. إذا كانت "خدمات Google Play" نفسه يفتقد أذونات، فيمكنك استدعاء startResolutionForResult() إلى وبدء تدفق المستخدم لإصلاحها.

على سبيل المثال:

@Override
public void onConnectionFailed(ConnectionResult result) {
    if (mResolvingError) {
        // Already attempting to resolve an error.
        return;
    } else if (result.hasResolution()) {
        try {
            mResolvingError = true;
            result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR);
        } catch (SendIntentException e) {
            // There was an error with the resolution intent. Try again.
            mGoogleApiClient.connect();
        }
    } else {
        // Show dialog using GooglePlayServicesUtil.getErrorDialog()
        showErrorDialog(result.getErrorCode());
        mResolvingError = true;
    }
}

ستعرض طلبات البيانات الأحدث من واجهة برمجة التطبيقات المستندة إلى GoogleApi إما مربّع حوار تلقائيًا (في حال يتم إنشاء مثيل للبرنامج باستخدام Activity) أو إشعار لوحة النظام (إذا يتم إنشاء مثيل للبرنامج باستخدام Context) يمكن للمستخدم النقر عليه لبدء تحليل الأذونات. سيتم إدراج المكالمات في قائمة الانتظار وإعادة المحاولة بعد أن يتم منح الإذن.