AndroidManifest Permissions: مفاهیم کلیدی، اعلام و انواع مجوزها

نویسنده: IT Sectr منتشر شده: 2026-05-21 زمان مطالعه: 10 دقیقه

AndroidManifest Permissions اعلامیه‌های مجوز در فایل AndroidManifest.xml هستند که تعیین می‌کنند برنامه به کدام منابع و داده‌های سیستمی دسترسی دارد. Android ایجاب می‌کند هر مجوز قبل از استفاده از API مربوطه در مانیفست ذکر شود: از دوربین و مکان‌یابی گرفته تا ارسال SMS و دسترسی به مخاطبان. طبق Android Developer Documentation، هر مجوز به یکی از چهار سطح حفاظتی تقسیم می‌شود: normal، dangerous، signature و special.

نکات اصلی

  • AndroidManifest.xml — فایل مانیفست با اعلام تمام مجوزهای برنامه
  • سطوح حفاظتی — normal، dangerous، signature، special با مکانیسم‌های درخواست متفاوت
  • Runtime Permission — مجوزهای dangerous نیاز به درخواست در زمان اجرا دارند (Android 6+)
  • Declare vs Request — اعلام در مانیفست الزامی است، اما dangerous نیاز به درخواست اضافی در کد دارند
  • گروه‌ها — مجوزها در گروه‌ها دسته‌بندی شده‌اند، موافقت با یکی دسترسی به کل گروه را می‌دهد

AndroidManifest Permissions چیست؟

AndroidManifest Permissions مکانیسم امنیتی Android است که دسترسی برنامه‌ها به داده‌های محافظت‌شده و عملکردهای سیستمی را کنترل می‌کند. هر برنامه باید مجوزهای لازم را در فایل AndroidManifest.xml با استفاده از عنصر <uses-permission> اعلام کند. بدون اعلام، فراخوانی API مربوطه با خطای امنیتی SecurityException شکست می‌خورد.

مدل مجوزهای Android چندین مرحله تکامل را پشت سر گذاشته است. قبل از Android 6.0 (API 23)، همه مجوزها هنگام نصب ارائه می‌شدند — کاربر لیست کامل را می‌دید و یا موافقت می‌کرد یا از نصب برنامه صرف‌نظر می‌کرد. از Android 6.0 به بعد، مجوزهای سطح dangerous در زمان اجرا (Runtime Permissions) درخواست می‌شوند که کنترل انعطاف‌پذیرتری به کاربر می‌دهد.

مجوزها به چهار سطح حفاظتی تقسیم می‌شوند: normal (به طور خودکار هنگام نصب اعطا می‌شود)، dangerous (نیاز به درخواست زمان اجرا دارد)، signature (فقط برای برنامه‌های امضا شده با همان گواهی در دسترس است) و special (نیاز به فعال‌سازی جداگانه در تنظیمات دارد). هر سطح مکانیسم اعطا و لغو خاص خود را دارد.

طبق Google I/O 2024، در Android 15 برنامه‌ریزی شده است که مجوزهای دقیق‌تری معرفی شوند — کاربر می‌تواند فقط به فایل‌های خاصی در کتابخانه رسانه دسترسی دهد، نه کل کتابخانه. این روند Android را به سمت به حداقل رساندن حجم داده‌های پیش‌فرض ادامه می‌دهد.

تفاوت با مدل مجوز iOS

برخلاف iOS که همه مجوزها در زمان اجرا (runtime) درخواست می‌شوند، Android مجوزها را به نصب (install-time) و اجرا (runtime) تقسیم می‌کند. سطح normal به طور خودکار هنگام نصب بدون اطلاع کاربر اعطا می‌شود. سطح dangerous مانند iOS نیاز به گفتگوی صریح دارد.

تفاوت دیگر: در Android مجوزها در گروه‌ها (permission groups) دسته‌بندی شده‌اند. اگر کاربر با دسترسی به دوربین موافقت کند، برنامه به طور خودکار به میکروفون نیز دسترسی پیدا می‌کند — آنها در یک گروه MICROPHONE هستند. در iOS هر مجوز مستقل از گروه به طور جداگانه درخواست می‌شود.

تکامل مجوزها بر اساس نسخه‌های Android

نسخه Androidتغییر در مدل مجوزها
Android 1.0–5.xهمه مجوزها هنگام نصب اعطا می‌شوند (install-time)
Android 6.0 (API 23)معرفی Runtime Permissions برای سطح dangerous
Android 10 (API 29)Scoped Storage — دسترسی به سیستم فایل محدود شد
Android 11 (API 30)بازنشانی خودکار مجوزها — مجوزهای استفاده‌نشده بازنشانی می‌شوند
Android 14 (API 34)مجوزهای زمان اجرا برای دسترسی به رسانه (عکس، ویدیو، صدا)

چه انواع مجوزهایی وجود دارد

Android چهار سطح حفاظتی (protection levels) برای مجوزها تعریف می‌کند که هر کدام قوانین اعطای خاص خود را دارند. هر سطح را به طور دقیق بررسی می‌کنیم.

Normal Permissions (install-time)

مجوزهای normal به طور خودکار هنگام نصب برنامه بدون اطلاع یا درخواست از کاربر اعطا می‌شوند. آنها دسترسی به عملکردهای کم‌خطر را پوشش می‌دهند که حریم خصوصی کاربر را تهدید نمی‌کنند: INTERNET، ACCESS_NETWORK_STATE، VIBRATE، BLUETOOTH. کاربر گفتگوی موافقت را نمی‌بیند — مجوز با نصب برنامه اعطا شده تلقی می‌شود.

توسعه‌دهنده نیازی به پردازش درخواست در کد برای مجوزهای normal ندارد — فقط اعلام آنها در مانیفست کافی است. با این حال، در Android 12+ هنگام نصب از Google Play، کاربر برگه «مجوزها» را با فهرست همه مجوزهای normal می‌بیند که شفافیت را افزایش می‌دهد. طبق Statista (2024)، بیش از 90٪ برنامه‌های Google Play از INTERNET به عنوان رایج‌ترین مجوز normal استفاده می‌کنند.

Dangerous Permissions (runtime)

مجوزهای dangerous دسترسی به داده‌ها و عملکردهایی را پوشش می‌دهند که می‌توانند حریم خصوصی را نقض کنند: دوربین، میکروفون، مکان‌یابی، مخاطبان، SMS، تلفن، تقویم، حسگرهای بدن. این مجوزها به مکانیسم دو مرحله‌ای نیاز دارند: اعلام در مانیفست + درخواست در زمان اجرا از طریق ActivityCompat.requestPermissions().

کاربر می‌تواند از اعطای مجوز dangerous خودداری کند و برنامه باید این سناریو را به درستی مدیریت کند. در Android 11+ اگر کاربر دو بار خودداری کند، درخواست‌های بعدی گفتگوی سیستمی را نشان نمی‌دهند — سیستم به طور خودکار DENIED برمی‌گرداند. در این صورت باید کاربر را به تنظیمات هدایت کرد.

Signature و Special Permissions

سطح signature — مجوز به طور خودکار اعطا می‌شود اگر برنامه با همان گواهی سیستم یا برنامه دیگری که مجوز را تعریف کرده امضا شده باشد. برای برنامه‌های سیستمی و شرکتی استفاده می‌شود. مثال: BIND_ACCESSIBILITY_SERVICE — فقط برای برنامه‌های سیستمی در دسترس است.

سطح special (SYSTEM_ALERT_WINDOW، WRITE_SETTINGS، REQUEST_INSTALL_PACKAGES، MANAGE_EXTERNAL_STORAGE) — نیاز به اقدام جداگانه کاربر از طریق تنظیمات سیستم دارد. برنامه می‌تواند صفحه تنظیمات را با Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION) باز کند. Google Play استفاده از مجوزهای special را محدود می‌کند و در هنگام انتشار نیاز به توجیه در فرم دارد.

Runtime Permission: کار با مجوزهای dangerous

از Android 6.0 به بعد، همه مجوزهای dangerous نیاز به درخواست در زمان اجرا دارند. بیایید چرخه کامل کار با runtime permissions را در Kotlin بررسی کنیم.

بررسی و درخواست مجوز

قبل از فراخوانی API که نیاز به مجوز dangerous دارد، همیشه وضعیت فعلی را از طریق ContextCompat.checkSelfPermission() بررسی کنید. اگر وضعیت PERMISSION_GRANTED باشد — می‌توان API را فراخوانی کرد. اگر PERMISSION_DENIED باشد — باید مجوز را از طریق ActivityResultContract RequestPermission (AndroidX) یا requestPermissions() منسوخ درخواست کرد.

توصیه می‌شود از ActivityResultContracts.RequestMultiplePermissions برای درخواست همزمان چند مجوز استفاده کنید. Google توصیه می‌کند مجوزهای مرتبط (مثلاً دوربین + میکروفون برای ضبط ویدیو) را در یک گفتگو گروه‌بندی کنید تا کاربر زمینه کامل درخواست را ببیند.

kotlin
import android.Manifest
import android.content.pm.PackageManager
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat

class CameraActivity : AppCompatActivity() {
    private val requestPermissionLauncher =
        registerForActivityResult(
            ActivityResultContracts.RequestPermission()
        ) { isGranted: Boolean ->
            if (isGranted) {
                openCamera()
            } else {
                explainWhyPermissionNeeded()
            }
        }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        checkCameraPermission()
    }

    private fun checkCameraPermission() {
        when {
            ContextCompat.checkSelfPermission(this,
                Manifest.permission.CAMERA
            ) == PackageManager.PERMISSION_GRANTED -> {
                openCamera()
            }
            shouldShowRequestPermissionRationale(
                Manifest.permission.CAMERA
            ) -> {
                showRationale()
            }
            else -> {
                requestPermissionLauncher.launch(
                    Manifest.permission.CAMERA
                )
            }
        }
    }
}

مدیریت رد «دوباره نپرس»

اگر کاربر دو بار مجوز را رد کند، Android درخواست را به حالت «Never ask again» می‌برد. در این حالت shouldShowRequestPermissionRationale() false برمی‌گرداند و گفتگوی سیستمی نشان داده نخواهد شد. برنامه باید کاربر را از طریق Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) به تنظیمات سیستم هدایت کند.

مهم: بلافاصله پس از اولین رد، گفتگوی پیشنهاد باز کردن تنظیمات را نشان ندهید — این رفتار تهاجمی تلقی می‌شود. از shouldShowRequestPermissionRationale() برای تعیین اینکه آیا نیاز به نشان دادن توضیح است استفاده کنید. Material Design Guidelines توصیه می‌کنند صفحه‌ای با توضیح ارزش دسترسی نشان دهید، نه فقط دکمه «باز کردن تنظیمات».

kotlin
private fun openAppSettings() {
    Intent(
        Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
        Uri.fromParts("package", packageName, null)
    ).also { intent ->
        startActivity(intent)
    }
}

private fun showPermissionSettings() {
    AlertDialog.Builder(this)
        .setTitle("دسترسی به دوربین")
        .setMessage("اجازه دسترسی به دوربین را در تنظیمات بدهید، "
            + "برای گرفتن عکس پروفایل")
        .setPositiveButton("باز کردن تنظیمات") { _, _ ->
            openAppSettings()
        }
        .setNegativeButton("لغو", null)
        .show()
}

اعلام مجوزها در AndroidManifest.xml

فایل AndroidManifest.xml شامل عنصر <uses-permission> برای هر مجوزی است که برنامه استفاده می‌کند. مجوزها در سطح <manifest> قبل از عنصر <application> اعلام می‌شوند.

سینتکس اعلام

هر مجوز با یک عنصر <uses-permission> مجزا با ویژگی android:name که نام کامل مجوز را نشان می‌دهد اعلام می‌شود. برای مجوزهایی که در نسخه‌های خاص Android ظاهر شده‌اند، از ویژگی maxSdkVersion استفاده کنید تا اعلام را فقط به نسخه‌های مورد نیاز محدود کنید — این کار سازگاری را بهبود می‌بخشد.

به عنوان مثال، مجوز WRITE_EXTERNAL_STORAGE در Android 10+ (Scoped Storage) مورد نیاز نیست، بنابراین maxSdkVersion=«28» (Android 9) را مشخص کنید. این کار از سوالات غیرضروری کاربران در نسخه‌های جدید جلوگیری می‌کند. Android Studio از طریق Lint در مورد maxSdkVersion توصیه‌شده هشدار می‌دهد.

xml
<!-- AndroidManifest.xml -->
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- Normal permissions (install-time) -->
    <uses-permission
        android:name="android.permission.INTERNET" />
    <uses-permission
        android:name="android.permission.ACCESS_NETWORK_STATE" />

    <!-- Dangerous permissions (runtime) -->
    <uses-permission
        android:name="android.permission.CAMERA" />
    <uses-permission
        android:name="android.permission.ACCESS_FINE_LOCATION" />

    <!-- Legacy storage permission limited to API 28 and below -->
    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="28" />

    <uses-feature
        android:name="android.hardware.camera"
        android:required="false" />

    <application>
        <!-- ... -->
    </application>
</manifest>

استفاده از <uses-feature> برای فیلتر کردن

عنصر <uses-feature> مشخص می‌کند که برنامه به سخت‌افزار خاصی (دوربین، GPS، NFC) نیاز دارد. ویژگی android:required=«false» امکان نصب برنامه را روی دستگاه‌های بدون این سخت‌افزار فراهم می‌کند — بررسی در دسترس بودن در کد انجام می‌شود. اگر required=«true» باشد، Google Play برنامه را فیلتر می‌کند و برای دستگاه‌های نامناسب در دسترس نخواهد بود.

توصیه می‌شود برای همه عملکردهای سخت‌افزاری required=«false» تعیین کنید و در دسترس بودن را به صورت برنامه‌نویسی از طریق PackageManager.hasSystemFeature() بررسی کنید. این کار مخاطبان برنامه شما را گسترش می‌دهد. تنها استثنا زمانی است که عملکرد برای کار برنامه حیاتی است (برنامه سفارش تاکسی بدون GPS بی‌معنی است).

بهترین روش‌ها و اشتباهات

کار صحیح با مجوزها جنبه کلیدی کیفیت برنامه Android است. بیایید توصیه‌های اصلی و اشتباهات رایج را بررسی کنیم.

به حداقل رساندن مجوزهای درخواستی

فقط مجوزهایی را درخواست کنید که واقعاً برای کار برنامه ضروری هستند. هر مجوز اضافی نرخ تبدیل نصب را کاهش می‌دهد و تعداد ردها را افزایش می‌دهد. Google Play Console نشان می‌دهد چند کاربر به دلیل مجموعه مجوزها از نصب صرف‌نظر کرده‌اند. طبق AppBrain (2024)، برنامه‌های با 10+ مجوز dangerous 35٪ نصب کمتری دارند.

لیست مجوزها را مرتباً بررسی کنید. مجوزهای استفاده‌نشده را حذف کنید، به ویژه هنگام انتقال به نسخه‌های جدید Android که برخی مجوزها اختیاری شده‌اند. به عنوان مثال، با ظهور انتخابگر عکس (ActivityResultContracts.PickVisualMedia) در Android 13+، دسترسی به کتابخانه رسانه را می‌توان بدون مجوز dangerous READ_MEDIA_IMAGES دریافت کرد.

نمایش توضیح قبل از درخواست

قبل از درخواست مجوز dangerous، صفحه‌ای با توضیح اینکه چرا این مجوز لازم است و چه ارزشی دارد به کاربر نشان دهید. Material Design استفاده از bottom sheet یا گفتگو با آیکون، متن کوتاه و دکمه «ادامه» را توصیه می‌کند. Rationale موافقت را 20–30٪ در مقایسه با درخواست مستقیم افزایش می‌دهد.

قبل از فراخوانی launch()، shouldShowRequestPermissionRationale() را بررسی کنید. اگر true است — rationale را نشان دهید. اگر false است — یا مجوز قبلاً داده شده یا کاربر برای همیشه رد کرده (never ask again). در حالت آخر دکمه «باز کردن تنظیمات» را نشان دهید، نه اینکه درخواست را تکرار کنید.

تست همه سناریوهای مجوز

همه سناریوهای ممکن را تست کنید: اعطای مجوز، رد، رد برای همیشه، لغو مجوز در تنظیمات، بازنشانی مجوزها (Android 11+ auto-reset). هر سناریو باید بدون crash و بدون از دست دادن داده مدیریت شود. Android Testing Guide استفاده از کتابخانه TestPermission را برای خودکارسازی تست توصیه می‌کند.

به سناریویی توجه ویژه داشته باشید که کاربر مجوز را در حین کار برنامه لغو می‌کند (برنامه کوچک‌شده → تنظیمات → لغو). پس از بازگشت به برنامه، همه مجوزها را دوباره از طریق onResume() بررسی کنید. به کش کردن وضعیت مجوزها اعتماد نکنید — کاربر می‌تواند آنها را در هر زمان تغییر دهد.

اشتباهات رایج

  • درخواست مجوز بدون بررسی قبلی checkSelfPermission — باعث گفتگوی غیرضروری می‌شود
  • نادیده گرفتن shouldShowRequestPermissionRationale — تجربه کاربری را پس از اولین رد بدتر می‌کند
  • درخواست مجوز بدون زمینه (فقط «اجازه دسترسی?») — موافقت را کاهش می‌دهد
  • استفاده از WRITE_EXTERNAL_STORAGE در Android 10+ بدون maxSdkVersion — درخواست غیرضروری
  • عدم بررسی مجوزها در onResume — از دست دادن لغو مجوز در تنظیمات

سوالات متداول

آیا اگر SDK مجوزی را درخواست کند باید آن را اعلام کرد؟

بله، اگر SDK مجوزی را در مانیفست خود قرار دهد، هنگام ساخت با مانیفست برنامه ادغام می‌شود. می‌توانید مجوز غیرضروری SDK را با tools:node=«remove» در AndroidManifest.xml غیرفعال کنید.

اگر رد مجوز را مدیریت نکنم چه اتفاقی می‌افتد؟

فراخوانی API بدون مجوز باعث SecurityException می‌شود که منجر به crash برنامه می‌گردد. همیشه قبل از استفاده از API مربوطه وضعیت مجوز را بررسی کنید و رد را به درستی مدیریت کنید.

چگونه مجوزها را در فرآیند توسعه بازنشانی کنیم؟

در تنظیمات دستگاه: تنظیمات → برنامه‌ها → [برنامه شما] → مجوزها. برای بازنشانی همه مجوزها از دستور adb استفاده کنید: adb shell pm reset-permissions.

آیا می‌توان بدون Activity مجوز درخواست کرد؟

بله، با ActivityResultLauncher در Fragment یا Service. با این حال گفتگوی درخواست همیشه به زمینه UI Activity نیاز دارد. برای Service می‌توانید Notification با Intent بازکننده Activity حاوی درخواست نشان دهید.

چرا maxSdkVersion برای مجوزها لازم است؟

به عنوان مثال، WRITE_EXTERNAL_STORAGE در Android 10+ (Scoped Storage) مورد نیاز نیست. با مشخص کردن android:maxSdkVersion=«28»، اعلام مجوز را در نسخه‌های جدید حذف می‌کنید که سازگاری را بهبود می‌بخشد و لیست مجوزهای درخواستی را کاهش می‌دهد.

خلاصه

  • AndroidManifest Permissions — اعلامیه‌های اجباری دسترسی به منابع سیستمی در Android
  • 4 سطح حفاظتی — normal، dangerous، signature، special با مکانیسم‌های اعطای متفاوت
  • Runtime Permissions — مجوزهای dangerous نیاز به درخواست در زمان اجرا دارند (Android 6+)
  • گروه‌های مجوز — موافقت با یک مجوز در گروه به همه مجوزهای گروه دسترسی می‌دهد
  • Rationale — نمایش توضیح قبل از درخواست موافقت را 20–30٪ افزایش می‌دهد
  • حداقل‌سازی — فقط مجوزهای ضروری را درخواست کنید و از maxSdkVersion استفاده کنید
  • همیشه قبل از فراخوانی API وضعیت مجوز را بررسی کنید و همه سناریوهای رد را مدیریت کنید

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید