از اندروید 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
نمونهسازی شده باشد) نمایش داده میشود که کاربر میتواند برای شروع هدف تفکیک مجوزها روی آن ضربه بزند. پس از اعطای مجوز، تماس ها در نوبت قرار می گیرند و دوباره امتحان می شوند.