Runtime Permission — مکانیسم درخواست مجوز در زمان اجرای برنامه، که در Android 6.0 (API 23) معرفی شد. به جای تنظیم مجوزها در هنگام نصب، runtime permissions به کاربر اجازه میدهد تا در هر لحظه به دادههای محرمانه (دوربین، مکانیابی، مخاطبات) دسترسی داشته باشد یا آن را لغو کند. به گزارش Android Developers (2026)، بیش از 85% برنامههای Google Play از حداقل یک runtime permission استفاده میکنند.
نکات کلیدی
Runtime Permission (مجوز زمان اجرا) — یک مدل امنیتی Android است که در آن برنامه در زمانی که آن قابلیت واقعاً به کاربر نیاز است، درخواست دسترسی به دادههای محرمانه را ارسال میکند. پیش از Android 6.0، تمام مجوزها در زمان نصب برنامه اعطا میشدند و کاربر نمیتوانست آنها را بدون حذف کامل برنامه لغو کند.
پیش از Android 6.0، کاربر لیست تمام مجوزها را در زمان نصب میدید و میتوانست یا همه را بپذیرد یا از نصب امتناع کند. یک مطالعه در سال 2015 نشان داد که 87% کاربران لیست مجوزها را در زمان نصب نمیخوانند. Android 6.0 runtime permissions را معرفی کرد و مجوزها را به normal (خودکار) و dangerous (با درخواست) تقسیم کرد. Android 11 one-time permissions را اضافه کرد — لغو خودکار پس از بستن برنامه. Android 13 Photo Picker و اعلامهای push را به عنوان runtime permissions جداگانه معرفی کرد.
iOS از نسخه iOS 10 از مدل مشابهی استفاده میکند، که در آن دسترسی به دوربین، میکروفن و مکانیابی در اولین مراجعه درخواست میشود. اما iOS مفهوم «normal permissions» را ندارد — هر مجوزی به صورت صریح درخواست میشود و امتناع تا زمان درخواست مجدد توسط توسعهدهنده از طریق تنظیمات سیستم ذخیره میشود.
Runtime Permission از طریق کادر محاوره سیستمی که با متد requestPermissions() (AndroidX — ActivityResultLauncher) فراخوانده میشود، کار میکند. سیستم یک کادر محاوره استاندارد با توضیح نشان میدهد و کاربر «اجازه» یا «ممنوع» را انتخاب میکند. پس از پاسخ، callback نتیجه فراخوانده میشود که در آن برنامه تصمیم کاربر را مدیریت میکند.
private lateinit var requestPermissionLauncher: ActivityResultLauncher<String>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) {
startCamera()
} else {
showPermissionDeniedDialog()
}
}
}
private fun checkCameraPermission() {
when {
ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED -> {
startCamera()
}
ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA) -> {
showRationaleDialog { requestPermissionLauncher.launch(Manifest.permission.CAMERA) }
}
else -> {
requestPermissionLauncher.launch(Manifest.permission.CAMERA)
}
}
}
روش shouldShowRequestPermissionRationale اگر کاربر قبلاً یک بار درخواست را رد کرده باشد، true بازمیگرداند. در این صورت توصیه میشود کادری با توضیح نشان داده شود که چرا برنامه به مجوز نیاز دارد و سپس مجدداً درخواست کند. این احتمال موافقت کاربر را 30–40% افزایش میدهد (اطلاعات Google I/O 2024).
Android تمام مجوزها را به چند سطح حفاظت طبقهبندی میکند: normal، dangerous، signature و special. Normal permissions در زمان نصب به طور خودکار اعطا میشوند. Dangerous permissions نیازمند درخواست runtime هستند. Signature permissions فقط برای برنامههایی که با همان گواهینامه امضا شدهاند قابل دسترسی هستند.
| گروه | مجوزها | API Level |
|---|---|---|
| CAMERA | CAMERA | API 23+ |
| LOCATION | ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION, ACCESS_BACKGROUND_LOCATION | API 23+ (background — API 29+) |
| STORAGE | READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE, READ_MEDIA_IMAGES (API 33+) | API 23+ (تغییرات در API 33) |
| PHONE | READ_PHONE_STATE, CALL_PHONE, READ_CALL_LOG | API 23+ |
| MICROPHONE | RECORD_AUDIO | API 23+ |
| CONTACTS | READ_CONTACTS, WRITE_CONTACTS, GET_ACCOUNTS | API 23+ |
| NOTIFICATIONS | POST_NOTIFICATIONS | API 33+ |
Special permissions (SYSTEM_ALERT_WINDOW, WRITE_SETTINGS, MANAGE_EXTERNAL_STORAGE) نیازمند مراجعه به تنظیمات سیستم از طریق Settings.ACTION_MANAGE_OVERLAY_PERMISSION هستند. این مجوزها نمیتوانند با کادر محاوره استاندارد درخواست شوند و نیازمند مراجعه صریح کاربر به صفحه تنظیمات هستند.
Android 12 تغییرات قابل توجهی در مدل runtime permissions ایجاد کرد. One-time permissions به شما اجازه میدهد به دوربین، میکروفن یا مکانیابی فقط برای یک جلسه دسترسی دهید. هنگامی که کاربر برنامه را میبندد، مجوز به طور خودکار لغو میشود. Privacy indicators — نشانگرهای سبز در نوار وضعیت که نشان میدهند کی برنامه از دوربین یا میکروفن استفاده میکند.
// Android 12+ — پردازش مجوز یکبار مصرف برای مکانیابی
private fun checkLocationPermission() {
val permissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
val fineLocationGranted = permissions[Manifest.permission.ACCESS_FINE_LOCATION]
val coarseLocationGranted = permissions[Manifest.permission.ACCESS_COARSE_LOCATION]
if (fineLocationGranted == true) {
showUserLocation()
} else {
showLocationDisabledDialog()
}
}
permissionLauncher.launch(
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
)
}
// بررسی اینکه آیا مجوز توسط سیستم لغو شده است (Android 12+)
class PermissionReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == Intent.ACTION_PERMISSION_REVOCATION) {
handleRevokedPermission(intent.getStringExtra(Intent.EXTRA_REVOKED_PERMISSION))
}
}
}
Android 13 مجوز POST_NOTIFICATIONS را به گروه dangerous اضافه کرد و برای ارسال اعلامهای push درخواست صریح را ضروری کرد. Android 14 محدودیتهایی بر مکانیابی پسزمینه اعمال کرد: برنامه باید هر بار برای درخواست background location رضایت صریح کاربر را دریافت کند. Photo Picker (API 33+) نیاز به READ_EXTERNAL_STORAGE برای انتخاب تصاویر را برطرف کرد.
امتناع کاربر از اعطای مجوز یک وضعیت عادی است که باید به طور صحیح مدیریت شود. دو نوع امتناع وجود دارد: یکبار (کاربر «ممنوع» را فشرده است) و دائمی (کاربر «دیگر نپرس» را انتخاب کرده است). در صورت دوم، کادر محاوره سیستم دیگر نشان داده نمیشود و برنامه باید کاربر را به تنظیمات سیستم هدایت کند.
پس از امتناع اول، برنامه باید rationale dialog را نشان دهد — توضیح خود برنامه درباره لزوم مجوز. اگر کاربر مجدداً امتناع کرد، باید او را به صفحه تنظیمات برنامه از طریق Settings.ACTION_APPLICATION_DETAILS_SETTINGS هدایت کند. Material 3 استفاده از PermissionRequestBottomSheet را برای UX طبیعیتر توصیه میکند.
مهم است که در صورت امتناع، فعالیت برنامه را کاملاً مسدود نکنید. به عنوان مثال، اگر کاربر مکانیابی را رد کرد، برنامه باید ورود دستی آدرس را پیشنهاد دهد. برای دوربین — امکان بارگذاری تصویر از گالری را فراهم کنید. Google توصیه میکند همیشه برای همه runtime permissions یک مکانیسم fallback ارائه دهید.
Runtime permissions فقط یک مکانیسم فنی نیستند، بلکه عنصری از اعتماد کاربر به برنامه نیز میباشند. درخواست مجوز در زمان نامناسب (مثلاً در نخستین بار اجرا) احتمال موافقت را به شدت کاهش میدهد. Google Play Store تعداد و زمینه درخواستهای مجوز را تحلیل میکند: برنامههایی با درخواستهای پرتجاوزی رتبه پایینتری در جستجو دارند.
زمینه — مجوز را درست قبل انجام عملی که به آن نیاز دارد، درخواست کنید. حداقل — فقط مجوزهایی را که واقعاً برای کارکرد ویژگی ضروری هستند، درخواست کنید. شفافیت — قبل از کادر محاوره سیستم، به کاربر توضیح دهید چرا به مجوز نیاز است. لغو — برای مدیریت صحیح لغو مجوز در زمان اجرا، دنبال کننده ACTION_PERMISSION_REVOCATION شوید.
برای آزمایش runtime permissions از دستورات adb استفاده کنید: adb shell pm revoke <package> android.permission.CAMERA به شما اجازه میدهد لغو مجوز را بدون نصب مجدد برنامه شبیهسازی کنید. Espresso و UiAutomator از آزمایش کادرهای مجوز از طریق GrantPermissionRule پشتیبانی میکنند. ادغام این ابزارها در خط لوله CI/CD برای برنامههای با runtime permissions اجباری است.
Google Play Console بخش Permission auditing (حسابرسی مجوز) را ارائه میدهد که در آن توسعهدهنده میتواند ببیند چقدر اتفاق مجوزها درخواست میشوند، چند درصد کاربران دسترسی میدهند و کدام مجوزها لغو شدهاند. تحلیل این دادهها به شناسایی درخواستهای ناکارآمد و بهبود UX کمک میکند. به عنوان مثال، اگر کمتر از 40% کاربران مکانیابی را تایید میکنند، باید زمانبندی درخواست را مجدد بررسی کرده و توضیح قانعکنندهتری اضافه کنید.
استفاده از Android Vitals برای نظارت بر ANR (پاسخ ندادن برنامه) مربوط به مجوز نیز حیاتی است. اگر درخواست مجوز در ترد اصلی اجرا شود یا کادر محاوره سیستم UI را مسدود کند، این میتواند در دستگاههای کند باعث ANR شود. بررسی و درخواست مجوز را به یک ترد جداگانه منتقل کنید یا از کوروتینهای Kotlin برای پردازش ناهمگام استفاده کنید تا از مسدود شدن رابط کاربر جلوگیری شود.
سوالات متداول
shouldShowRequestPermissionRationale در صورت امتناع دائمی (وقتی کاربر «دیگر نپرس» را انتخاب کرده است) false بازمیگرداند. این روش در صورت امتناع یکبار true بازمیگرداند و امکان نشان دادن rationale dialog را فراهم میکند. اگر روش false بازگرداند، تنها راه هدایت کاربر به تنظیمات سیستم برنامه است.
بله، ActivityResultContracts.RequestMultiplePermissions امکان درخواست مجموعهای از مجوزها را در یک تماس فراهم میکند. سیستم به صورت پیاپی کادرهایی برای هر مجوز نشان میدهد. توصیه میشود مجوزهای مرتبط منطقی را گروهبندی کنید (مثلاً CAMERA و RECORD_AUDIO برای فیلمبرداری)، اما بیش از 2–3 را در یک بار درخواست نکنید.
Android TV از همان مدل runtime permissions با نمایش کادرها در صفحه تلویزیون استفاده میکند. Wear OS نسخه 3+ از runtime permissions پشتیبانی میکند، اما کادرها روی ساعت نمایش داده میشوند. برای Android Auto، تمام مجوزها در تلفن درخواست میشوند و سیستم خودرو مجوزهای تاییدشده را از طریق اتصال bridge دریافت میکند.
بر اساس اطلاعات اولیه، Android 16 «منقضی شدن مجوز» را برای مجوزهای یکبار مصرف با لغو خودکار پس از 24 ساعت معرفی میکند. همچنین افزایش سختگی ضوابط برای background location و گسترش لیست dangerous permissions برای دستههای جدید (حسگرهای محیطی، اسکن Wi-Fi) انتظار میرود. جزئیات دقیق در سهماهه سوم 2027 منتشر خواهد شد.
iOS از «مجوزهای عادی» پشتیبانی نمیکند — هر مجوز به صورت صریح از طریق کادر محاوره سیستم درخواست میشود. کاربر میتواند در هر لحظه از طریق تنظیمات مجوز را لغو کند. تفاوت اصلی این است که iOS وضعیت مجوز را از طریق معادل checkSelfPermission از قبل بررسی نمیکند: سیستم به طور خودکار در اولین مراجعه به API محفوظشده، کادر را نشان میدهد.
نتایج
POST_NOTIFICATIONS را به عنوان runtime permission اضافه کرد، Android 14 ضوابط مکانیابی پسزمینه را سفتتر کرد.READ_EXTERNAL_STORAGE برای انتخاب تصاویر را برطرف میکند.ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید