خدمات Google Play و مجوزهای زمان اجرا

از اندروید 6.0 مارشمالو، اندروید از یک مدل مجوز استفاده می‌کند که فرآیند نصب و به‌روزرسانی خودکار برنامه را ساده می‌کند. مجوزها در زمان اجرا به جای قبل از نصب برنامه درخواست می شوند. علاوه بر این، کاربران می توانند مجوزهای خاص را رد کنند. برای دادن این انعطاف‌پذیری به کاربران، باید مطمئن شوید که وقتی کاربر مجوز خاصی را فعال یا غیرفعال می‌کند، برنامه شما مطابق انتظار عمل می‌کند.

خدمات Google Play خود دارای مجوزهای زمان اجرا هستند که کاربران می توانند جدا از آن مجوزهایی که به طور خاص توسط برنامه شما درخواست شده است، رد کنند. سرویس‌های Google Play به‌طور خودکار تمام مجوزهایی را که برای پشتیبانی از APIهای خود نیاز دارد، دریافت می‌کنند. با این حال، برنامه شما همچنان باید در صورت لزوم مجوزهای زمان اجرا را بررسی و درخواست کند و در مواردی که کاربر مجوز لازم برای API مورد نیاز برنامه شما را از خدمات Google Play رد کرده است، به درستی خطاها را رسیدگی کند.

مدیریت انتظارات کاربر در تنظیم مجوزهایی که زمان اجرا ممکن است به آن نیاز داشته باشد، تمرین خوبی است. بهترین روش های زیر به شما کمک می کند تا از مشکلات احتمالی جلوگیری کنید.

پیش نیازها

باید مجوزها را در فایل AndroidManifest.xml خود اعلام کنید. مثلا:

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

رهنمودها

قبل از فراخوانی APIها، مجوزها را تأیید کنید

هنگامی که API هایی را که می خواهید در فایل AndroidManifest.xml خود استفاده کنید، اعلام کردید، قبل از فراخوانی API مطمئن شوید که مجوز لازم را دارید. این را می توان با استفاده از روش checkSelfPermission ActivityCompat یا ContextCompat انجام داد.

اگر تماس نادرست برگردد، این بدان معناست که مجوزها اعطا نمی شوند و باید از requestPermissions برای درخواست آنها استفاده کنید. پاسخ به این در یک callback برگردانده می شود که در مرحله بعد خواهید دید.

مثلا:

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 را فراخوانی کنید. اگر درست است، باید یک UI ایجاد کنید تا زمینه اضافی برای مجوز نمایش داده شود.

به عنوان مثال، کد شما ممکن است به شکل زیر باشد:

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 تأیید می‌کند که تمام مجوزهای لازم را دارد. وقتی هیچ گروه مجوزی که توسط خود سرویس‌های Google Play نیاز است وجود نداشته باشد، connect() با شکست مواجه می‌شود.

اگر تماس برای 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;
    }
}

تماس‌های API مبتنی بر GoogleApi جدیدتر به‌طور خودکار یک گفتگو (اگر کلاینت با یک Activity نمونه‌سازی شده باشد) یا اعلان سینی سیستم (اگر کلاینت با یک Context نمونه‌سازی شده باشد) نمایش داده می‌شود که کاربر می‌تواند برای شروع هدف تفکیک مجوزها روی آن ضربه بزند. پس از اعطای مجوز، تماس ها در نوبت قرار می گیرند و دوباره امتحان می شوند.