درخواست اجازه‌های زمان اجرا

همه برنامه‌های Android در جعبه امن با دسترسی محدود اجرا می‌شوند. اگر برنامه‌تان نیاز به استفاده از منابع یا اطلاعات خارج از محیط ایمن خود دارد، می‌توانید اجازه زمان اجرا را اعلام کنید و درخواست اجازه‌ای را تنظیم کنید که این دسترسی را فراهم کند. این مراحل بخشی از گردش کار برای استفاده از اجازه‌ها است.

اگر هرگونه اجازه خطرناک را اعلام کنید و اگر برنامه‌تان در دستگاهی نصب شده باشد که Android نسخه ۶.۰ (سطح میانای برنامه کاربردی ۲۳) یا بالاتر را اجرا می‌کند، باید با دنبال کردن مراحل این راهنما، اجازه‌های خطرناک را در زمان اجرا درخواست کنید.

اگر هیچ اجازه خطرناکی را اعلام نکنید، یا اگر برنامه‌تان در دستگاهی نصب شده باشد که Android نسخه ۵.۱ (سطح میانای برنامه‌سازی کاربردی ۲۲) یا پایین‌تر را اجرا می‌کند، اجازه‌ها به‌طور خودکار اعطا می‌شوند و لازم نیست هیچ‌کدام از مراحل باقی‌مانده در این صفحه را تکمیل کنید.

اصول پایه

اصول اولیه برای درخواست اجازه‌ها در زمان اجرا به‌شرح زیر است:

  • وقتی کاربر شروع به تعامل با ویژگی‌ای می‌کند که به اجازه نیاز دارد، اجازه را در بافتار درخواست کنید.
  • کاربر را مسدود نکنید. همیشه گزینه لغو جریان واسط کاربر آموزشی را ارائه دهید، مثلاً جریانی که منطق درخواست اجازه‌ها را توضیح می‌دهد.
  • اگر کاربر اجازه‌ای را که ویژگی نیاز دارد رد یا لغو کرد، برنامه‌تان را به‌طور متین تنزل دهید تا کاربر بتواند به استفاده از برنامه‌تان ادامه دهد، احتمالاً با غیرفعال کردن ویژگی‌ای که به اجازه نیاز دارد.
  • هیچ رفتار سیستمی را فرض نکنید. برای مثال، فرض نکنید که اجازه‌ها در یک گروه اجازه نشان داده می‌شوند. گروه اجازه صرفاً به سیستم کمک می‌کند تعداد کادرهای گفتگوی سیستم را که هنگام درخواست اجازه‌های بسیار مرتبط توسط برنامه به کاربر نشان داده می‌شود به‌حداقل برساند.

گردش کار برای درخواست اجازه‌ها

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

اگر به این نتیجه رسیدید که برنامه‌تان باید اجازه‌های زمان اجرا را اعلام و درخواست کند، این مراحل را تکمیل کنید:

  1. اجازه‌هایی را که ممکن است برنامه‌تان نیاز به درخواست آن‌ها داشته باشد در فایل مانیفست برنامه‌تان اعلام کنید.
  2. تجربه کاربری (UX) برنامه‌تان را طوری طراحی کنید که کنش‌های خاص در برنامه‌تان با اجازه‌های زمان اجرای خاص مرتبط باشد. به کاربران اطلاع دهید که کدام کنش‌ها ممکن است نیاز داشته باشد که به برنامه شما اجازه دسترسی به داده‌های خصوصی کاربر را بدهند.
  3. منتظر بمانید تا کاربر تکلیف یا کنشی را در برنامه‌تان که نیاز به دسترسی به داده‌های خصوصی خاص کاربر دارد فراخوانی کند. در آن زمان، برنامه شما می‌تواند اجازه زمان اجرایی را که برای دسترسی به آن داده‌ها لازم است درخواست کند.
  4. بررسی کنید که آیا کاربر قبلاً اعطا کرده است یا نه

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

    هر بار که عملیاتی را انجام می‌دهید که به آن اجازه نیاز دارد، باید بررسی کنید که آیا آن اجازه را دارید یا نه.

  5. بررسی کنید که آیا برنامه‌تان باید منطقی را به کاربر نشان دهد، و توضیح دهد که چرا برنامه‌تان نیاز دارد که کاربر اجازه زمان اجرای خاصی را اعطا کند. اگر سیستم تشخیص دهد که برنامه‌تان نباید دلیل را نشان دهد، مستقیماً به مرحله بعدی بروید، بدون اینکه عنصر میانای کاربر را نشان دهید.

    بااین‌حال، اگر سیستم تشخیص دهد که برنامه‌تان باید دلیل منطقی را نشان دهد، دلیل منطقی را در عنصر میانای کاربر به کاربر ارائه دهید. در این منطق، به‌وضوح توضیح دهید برنامه‌تان می‌خواهد به چه داده‌هایی دسترسی پیدا کند و اگر کاربر اجازه زمان اجرا را اعطا کند، برنامه چه مزایایی می‌تواند برای کاربر فراهم کند. پس‌از اینکه کاربر دلیل را تأیید کرد، به مرحله بعدی بروید.

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

  7. پاسخ کاربر را بررسی کنید—اینکه آیا اجازه زمان اجرا را اعطا کرده است یا رد کرده است.

  8. اگر کاربر به برنامه شما اجازه داده باشد، می‌توانید به داده‌های خصوصی کاربر دسترسی داشته باشید. اگر کاربر اجازه را رد کرد، تجربه برنامه‌تان را به‌طور متین تنزل دهید تا بدون اطلاعاتی که با آن اجازه محافظت می‌شود، عملکرد را به کاربر ارائه دهد.

شکل ۱ گردش کار و مجموعه تصمیمات مرتبط با این فرایند را نشان می‌دهد:

روندنمایی که فرایند تصمیم‌گیری برای درخواست اجازه‌های زمان اجرا را نشان می‌دهد، با کنش برنامه شروع می‌شود، بررسی می‌کند که آیا اجازه اعطا شده است یا نه، بررسی می‌کند که آیا منطق لازم است یا نه، اجازه را درخواست می‌کند، و پاسخ کاربر را مدیریت می‌کند.
شکل ۱. نموداری که گردش کار اعلام و درخواست اجازه‌های زمان اجرا در Android را نشان می‌دهد.

تشخیص اینکه آیا قبلاً به برنامه‌تان اجازه داده شده است یا نه

برای بررسی اینکه آیا کاربر قبلاً اجازه خاصی به برنامه شما اعطا کرده است یا نه، آن اجازه را به روش ContextCompat.checkSelfPermission() منتقل کنید. این روش بسته به اینکه برنامه‌تان اجازه را داشته باشد یا نه، PERMISSION_GRANTED یا PERMISSION_DENIED را برمی‌گرداند.

توضیح دهید چرا برنامه‌تان به این اجازه نیاز دارد

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

پژوهش‌ها نشان می‌دهد که اگر کاربران بدانند چرا برنامه به اجازه‌ها نیاز دارد، مثلاً اینکه آیا اجازه برای پشتیبانی از ویژگی اصلی برنامه لازم است یا برای تبلیغات، با درخواست‌های اجازه بسیار راحت‌تر کنار می‌آیند. درنتیجه، اگر فقط از بخشی از فراخوانی‌های میانای برنامه‌سازی کاربردی که تحت گروه اجازه‌ها قرار می‌گیرند استفاده می‌کنید، به‌طور صریح فهرست کنید که از کدام‌یک از این اجازه‌ها استفاده می‌کنید و چرا. برای مثال، اگر فقط از مکان غیردقیق استفاده می‌کنید، این موضوع را در شرح برنامه یا در مقاله‌های راهنما درباره برنامه‌تان به کاربر اطلاع دهید.

در شرایط خاص، همچنین مفید است که کاربران را به‌طور هم‌زمان از دسترسی به داده‌های حساس مطلع کنید. برای مثال، اگر به دوربین یا میکروفون دسترسی دارید، بااستفاده از نماد اعلان در جایی از برنامه یا در سینی اعلان (اگر برنامه در پس‌زمینه اجرا می‌شود) به کاربر اطلاع دهید تا این‌طور به‌نظر نرسد که مخفیانه درحال جمع‌آوری داده هستید.

اگر برای عملکرد یک ویژگی باید اجازه‌ای درخواست کنید، اما دلیل آن برای کاربر واضح نیست، راهی پیدا کنید تا توضیح دهید چرا به اجازه‌های حساس نیاز دارید.

اگر روش ContextCompat.checkSelfPermission() مقدار PERMISSION_DENIED را برگرداند، shouldShowRequestPermissionRationale() را فراخوانی کنید. اگر این روش true را برگرداند، واسط کاربر آموزشی به کاربر نشان دهید. در این میانای کاربر، توضیح دهید چرا ویژگی‌ای که کاربر می‌خواهد فعال کند به اجازه خاصی نیاز دارد.

علاوه‌براین، اگر برنامه‌تان اجازه‌ای مربوط به مکان، میکروفون، یا دوربین درخواست می‌کند، توضیح دهید چرا برنامه‌تان به دسترسی به این اطلاعات نیاز دارد.

درخواست اجازه

پس‌از اینکه کاربر واسط کاربر آموزشی را مشاهده کرد، یا مقدار برگشتی shouldShowRequestPermissionRationale() نشان داد که نیازی به نمایش واسط کاربر آموزشی نیست، اجازه را درخواست کنید. کاربران کادر گفتگوی اجازه سیستم را می‌بینند که در آن می‌توانند انتخاب کنند آیا اجازه خاصی به برنامه شما اعطا شود یا نه.

برای انجام این کار، از قرارداد RequestPermission استفاده کنید که در کتابخانه AndroidX گنجانده شده است و در آن به سیستم اجازه می‌دهید کد درخواست اجازه را برای شما مدیریت کند. چون استفاده از قرارداد RequestPermission منطق شما را ساده می‌کند، راه‌حل توصیه‌شده درصورت امکان است. بااین‌حال، درصورت نیاز می‌توانید کد درخواست را خودتان به‌عنوان بخشی از درخواست اجازه مدیریت کنید و این کد درخواست را در منطق فراخوانی اجازه خود بگنجانید.

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

برای اینکه سیستم بتواند کد درخواست مرتبط با درخواست اجازه‌ها را مدیریت کند، وابستگی‌ها را به کتابخانه‌های زیر در فایل build.gradle پیمانه‌تان اضافه کنید:

سپس می‌توانید از یکی از کلاس‌های زیر استفاده کنید:

  • برای درخواست یک اجازه، از RequestPermission استفاده کنید.
  • برای درخواست چند اجازه به‌طور هم‌زمان، از RequestMultiplePermissions استفاده کنید.

مراحل زیر نحوه استفاده از قرارداد RequestPermission را نشان می‌دهد. روند قرارداد RequestMultiplePermissions تقریباً یکسان است.

  1. در منطق مقداردهی اولیه فعالیت یا قطعه، پیاده‌سازی ActivityResultCallback را به فراخوانی registerForActivityResult() ارسال کنید. ActivityResultCallback تعریف می‌کند برنامه شما چگونه پاسخ کاربر به درخواست اجازه را مدیریت می‌کند.

    مرجعی برای مقدار برگشتی registerForActivityResult() نگه دارید که از نوع ActivityResultLauncher است.

  2. برای نمایش کادر گفتگوی اجازه‌های سیستم درصورت لزوم، روش launch() را در نمونه ActivityResultLauncher که در مرحله قبلی ذخیره کردید فراخوانی کنید.

    پس‌از فراخوانی launch()، کادر گفتگوی اجازه‌های سیستم ظاهر می‌شود. وقتی کاربر انتخابی انجام می‌دهد، سیستم به‌طور ناهمگام پیاده‌سازی شما از ActivityResultCallback را که در مرحله قبل تعریف کرده‌اید فراخوانی می‌کند.

    توجه: برنامه شما نمی‌تواند کادر گفتگویی را که هنگام فراخوانی launch() ظاهر می‌شود سفارشی‌سازی کند. برای ارائه اطلاعات یا بافت بیشتر به کاربر، میانای کاربر برنامه‌تان را تغییر دهید تا کاربران راحت‌تر متوجه شوند چرا ویژگی‌ای در برنامه‌تان به اجازه خاصی نیاز دارد. برای مثال، می‌توانید نوشتار دکمه‌ای را که ویژگی را فعال می‌کند تغییر دهید.

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

تکه‌کد زیر نحوه مدیریت پاسخ اجازه‌ها را نشان می‌دهد:

کاتلین

when {
    ContextCompat.checkSelfPermission(
            CONTEXT,
            Manifest.permission.REQUESTED_PERMISSION
            ) == PackageManager.PERMISSION_GRANTED -> {
        // You can use the API that requires the permission.
        performAction(...)
    }
    ActivityCompat.shouldShowRequestPermissionRationale(
            this, Manifest.permission.REQUESTED_PERMISSION) -> {
        // In an educational UI, explain to the user why your app requires this
        // permission for a specific feature to behave as expected, and what
        // features are disabled if it's declined. In this UI, include a
        // "cancel" or "no thanks" button that lets the user continue
        // using your app without granting the permission.
        showInContextUI(...)
    }
    else -> {
        // You can directly ask for the permission.
        requestPermissions(CONTEXT,
                arrayOf(Manifest.permission.REQUESTED_PERMISSION),
                REQUEST_CODE)
    }
}

جاوا

if (ContextCompat.checkSelfPermission(
        CONTEXT, Manifest.permission.REQUESTED_PERMISSION) ==
        PackageManager.PERMISSION_GRANTED) {
    // You can use the API that requires the permission.
    performAction(...);
} else if (ActivityCompat.shouldShowRequestPermissionRationale(
        this, Manifest.permission.REQUESTED_PERMISSION)) {
    // In an educational UI, explain to the user why your app requires this
    // permission for a specific feature to behave as expected, and what
    // features are disabled if it's declined. In this UI, include a
    // "cancel" or "no thanks" button that lets the user continue
    // using your app without granting the permission.
    showInContextUI(...);
} else {
    // You can directly ask for the permission.
    requestPermissions(CONTEXT,
            new String[] { Manifest.permission.REQUESTED_PERMISSION },
            REQUEST_CODE);
}

و این تکه‌کد فرایند توصیه‌شده را برای بررسی اجازه و درخواست اجازه از کاربر درصورت لزوم نشان می‌دهد:

کاتلین

when {
    ContextCompat.checkSelfPermission(
            CONTEXT,
            Manifest.permission.REQUESTED_PERMISSION
            ) == PackageManager.PERMISSION_GRANTED -> {
        // You can use the API that requires the permission.
    }
    ActivityCompat.shouldShowRequestPermissionRationale(
            this, Manifest.permission.REQUESTED_PERMISSION) -> {
        // In an educational UI, explain to the user why your app requires this
        // permission for a specific feature to behave as expected, and what
        // features are disabled if it's declined. In this UI, include a
        // "cancel" or "no thanks" button that lets the user continue
        // using your app without granting the permission.
        showInContextUI(...)
    }
    else -> {
        // You can directly ask for the permission.
        // The registered ActivityResultCallback gets the result of this request.
        requestPermissionLauncher.launch(
                Manifest.permission.REQUESTED_PERMISSION)
    }
}

جاوا

if (ContextCompat.checkSelfPermission(
        CONTEXT, Manifest.permission.REQUESTED_PERMISSION) ==
        PackageManager.PERMISSION_GRANTED) {
    // You can use the API that requires the permission.
    performAction(...);
} else if (ActivityCompat.shouldShowRequestPermissionRationale(
        this, Manifest.permission.REQUESTED_PERMISSION)) {
    // In an educational UI, explain to the user why your app requires this
    // permission for a specific feature to behave as expected, and what
    // features are disabled if it's declined. In this UI, include a
    // "cancel" or "no thanks" button that lets the user continue
    // using your app without granting the permission.
    showInContextUI(...);
} else {
    // You can directly ask for the permission.
    // The registered ActivityResultCallback gets the result of this request.
    requestPermissionLauncher.launch(
            Manifest.permission.REQUESTED_PERMISSION);
}

کد درخواست اجازه را خودتان مدیریت کنید

به‌عنوان جایگزینی برای اجازه دادن به سیستم برای مدیریت کد درخواست اجازه، می‌توانید کد درخواست اجازه را خودتان مدیریت کنید. برای انجام این کار، کد درخواست را در تماس با requestPermissions() اضافه کنید.

تکه‌کد زیر نحوه درخواست اجازه بااستفاده از کد درخواست را نشان می‌دهد:

کاتلین

when {
    ContextCompat.checkSelfPermission(
            CONTEXT,
            Manifest.permission.REQUESTED_PERMISSION
            ) == PackageManager.PERMISSION_GRANTED -> {
        // You can use the API that requires the permission.
        performAction(...)
    }
    ActivityCompat.shouldShowRequestPermissionRationale(
            this, Manifest.permission.REQUESTED_PERMISSION) -> {
        // In an educational UI, explain to the user why your app requires this
        // permission for a specific feature to behave as expected, and what
        // features are disabled if it's declined. In this UI, include a
        // "cancel" or "no thanks" button that lets the user continue
        // using your app without granting the permission.
        showInContextUI(...)
    }
    else -> {
        // You can directly ask for the permission.
        requestPermissions(CONTEXT,
                arrayOf(Manifest.permission.REQUESTED_PERMISSION),
                REQUEST_CODE)
    }
}

جاوا

if (ContextCompat.checkSelfPermission(
        CONTEXT, Manifest.permission.REQUESTED_PERMISSION) ==
        PackageManager.PERMISSION_GRANTED) {
    // You can use the API that requires the permission.
    performAction(...);
} else if (ActivityCompat.shouldShowRequestPermissionRationale(
        this, Manifest.permission.REQUESTED_PERMISSION)) {
    // In an educational UI, explain to the user why your app requires this
    // permission for a specific feature to behave as expected, and what
    // features are disabled if it's declined. In this UI, include a
    // "cancel" or "no thanks" button that lets the user continue
    // using your app without granting the permission.
    showInContextUI(...);
} else {
    // You can directly ask for the permission.
    requestPermissions(CONTEXT,
            new String[] { Manifest.permission.REQUESTED_PERMISSION },
            REQUEST_CODE);
}

پس‌از اینکه کاربر به کادر گفتگوی اجازه‌های سیستم پاسخ داد، سیستم پیاده‌سازی onRequestPermissionsResult() برنامه‌تان را فراخوانی می‌کند. سیستم پاسخ کاربر به کادر گفتگوی اجازه و همچنین کد درخواست تعریف‌شده توسط شما را ارسال می‌کند، همان‌طور که در تکه‌کد زیر نشان داده شده است:

کاتلین

override fun onRequestPermissionsResult(requestCode: Int,
        permissions: Array<String>, grantResults: IntArray) {
    when (requestCode) {
        PERMISSION_REQUEST_CODE -> {
            // If request is cancelled, the result arrays are empty.
            if ((grantResults.isNotEmpty() &&
                    grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
                // Permission is granted. Continue the action or workflow
                // in your app.
            } else {
                // Explain to the user that the feature is unavailable because
                // the feature requires a permission that the user has denied.
                // At the same time, respect the user's decision. Don't link to
                // system settings in an effort to convince the user to change
                // their decision.
            }
            return
        }

        // Add other 'when' lines to check for other
        // permissions this app might request.
        else -> {
            // Ignore all other requests.
        }
    }
}

جاوا

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
        int[] grantResults) {
    switch (requestCode) {
        case PERMISSION_REQUEST_CODE:
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0 &&
                    grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Permission is granted. Continue the action or workflow
                // in your app.
            }  else {
                // Explain to the user that the feature is unavailable because
                // the feature requires a permission that the user has denied.
                // At the same time, respect the user's decision. Don't link to
                // system settings in an effort to convince the user to change
                // their decision.
            }
            return;
        }
        // Other 'case' lines to check for other
        // permissions this app might request.
    }
}

درخواست اجازه‌های مکان

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

مکان پیش‌زمینه‌ای

اگر برنامه‌تان حاوی ویژگی‌ای است که اطلاعات مکان را فقط یک‌بار یا برای مدت زمان مشخصی هم‌رسانی یا دریافت می‌کند، آن ویژگی به دسترسی به مکان در پیش‌زمینه نیاز دارد. چند نمونه در زیر آمده است:

  • در برنامه ناوبری، ویژگی‌ای به کاربران امکان می‌دهد مسیرهای گام‌به‌گام را دریافت کنند.
  • در یک برنامه پیام‌رسانی، ویژگی‌ای به کاربران اجازه می‌دهد مکان فعلی‌شان را با کاربر دیگری هم‌رسانی کنند.

اگر یکی از ویژگی‌های برنامه‌تان در یکی از شرایط زیر به مکان فعلی دستگاه دسترسی پیدا کند، سیستم برنامه‌تان را درحال استفاده از مکان پیش‌زمینه درنظر می‌گیرد:

  • فعالیتی که متعلق به برنامه شما است قابل‌مشاهده است.
  • برنامه‌تان درحال اجرای سرویس پیش‌زمینه‌ای است. وقتی سرویس پیش‌زمینه‌ای درحال اجرا است، سیستم با نشان دادن اعلان دائمی، آگاهی کاربر را افزایش می‌دهد. برنامه شما وقتی در پس‌زمینه قرار می‌گیرد، دسترسی را حفظ می‌کند، مثلاً وقتی کاربر دکمه صفحه اصلی را در دستگاهش فشار می‌دهد یا نمایشگر دستگاهش را خاموش می‌کند.

    در Android 10 (سطح API‏ ۲۹) و بالاتر، باید نوع سرویس پیش‌زمینه‌ای location را اعلام کنید، همان‌طور که در قطعه کد زیر نشان داده شده است. در نسخه‌های قدیمی‌تر Android، توصیه می‌کنیم این نوع سرویس پیش‌زمینه‌ای را اعلام کنید.

    <!-- Recommended for Android 9 (API level 28) and lower. -->
    <!-- Required for Android 10 (API level 29) and higher. -->
    <service
        android:name="MyNavigationService"
        android:foregroundServiceType="location" ... >
        <!-- Any inner elements go here. -->
    </service>

وقتی برنامه‌تان اجازه ACCESS_COARSE_LOCATION یا اجازه ACCESS_FINE_LOCATION را درخواست می‌کند، همان‌طور که در قطعه کد زیر نشان داده شده است، نیاز به مکان در پیش‌نما را اعلام می‌کنید:

<manifest ... >
  <!-- Include this permission any time your app needs location information. -->
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

  <!-- Include only if your app benefits from precise location access. -->
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>

مکان پس‌زمینه‌ای

اگر ویژگی‌ای در برنامه به‌طور مداوم مکان را با کاربران دیگر هم‌رسانی کند یا از Geofencing API استفاده کند، برنامه به دسترسی به مکان در پس‌زمینه نیاز دارد. چند نمونه شامل موارد زیر است:

  • در برنامه هم‌رسانی مکان خانواده، ویژگی‌ای به کاربران امکان می‌دهد به‌طور مداوم مکانشان را با اعضای خانواده هم‌رسانی کنند.
  • در یک برنامه اینترنت اشیا، ویژگی‌ای به کاربران امکان می‌دهد دستگاه‌های خانه‌شان را به‌گونه‌ای پیکربندی کنند که وقتی کاربر خانه را ترک می‌کند خاموش شوند و وقتی کاربر به خانه برمی‌گردد دوباره روشن شوند.

اگر برنامه شما در شرایطی غیراز شرایط شرح‌داده‌شده در بخش مکان پیش‌زمینه‌ای به مکان فعلی دستگاه دسترسی پیدا کند، سیستم برنامه شما را به‌عنوان برنامه‌ای که از مکان پس‌زمینه‌ای استفاده می‌کند درنظر می‌گیرد. دقت مکان پس‌زمینه‌ای با دقت مکان پیش‌زمینه‌ای یکسان است که به اجازه‌های مکان اعلام‌شده توسط برنامه شما بستگی دارد.

در Android 10 (سطح API‏ ۲۹) و بالاتر، باید اجازه ACCESS_BACKGROUND_LOCATION را در مانیفست برنامه‌تان اعلام کنید تا بتوانید در زمان اجرا، دسترسی به مکان پس‌زمینه‌ای را درخواست کنید. در نسخه‌های قدیمی‌تر Android، وقتی برنامه‌تان دسترسی به مکان در پیش‌نما را دریافت می‌کند، به‌طور خودکار دسترسی به مکان در پس‌زمینه را نیز دریافت می‌کند.

<manifest ... >
  <!-- Required only when requesting background location access on
       Android 10 (API level 29) and higher. -->
  <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
</manifest>

رسیدگی به رد اجازه

اگر کاربر درخواست اجازه را رد کند، برنامه‌تان باید به او کمک کند تا پیامدهای رد کردن اجازه را درک کند. به‌ویژه، برنامه‌تان باید کاربران را از ویژگی‌هایی که به‌دلیل نداشتن اجازه کار نمی‌کنند مطلع کند. وقتی این کار را انجام می‌دهید، روال‌های مطلوب زیر را به‌خاطر داشته باشید:

  • ازدست رفتن عملکرد را به‌حداقل برسانید. کاربران باید بتوانند تا حد امکان بدون اجازه‌های درخواست‌شده به برنامه دسترسی داشته باشند. اگر عملکرد حداقل تا حدودی با داده‌های دردسترس کار می‌کند، حتی اگر درمقایسه با آنچه با اجازه امکان‌پذیر بود کاهش یافته باشد، روشن نگه داشتن آن بهترین گزینه است.
  • توجه کاربر را جلب کنید. بخش خاصی از واسط کاربر برنامه‌تان را که به‌دلیل نداشتن اجازه لازم عملکرد محدودی دارد برجسته کنید. نمونه‌هایی از کارهایی که می‌توانید انجام دهید شامل موارد زیر است:

    • پیامی را در جایی که نتایج یا داده‌های ویژگی ظاهر می‌شد نشان دهید.
    • دکمه دیگری را نمایش دهید که حاوی نماد و رنگ خطا باشد.
  • دقیق باشید. پیام عمومی نمایش ندهید. درعوض، مشخص کنید کدام ویژگی‌ها دردسترس نیستند چون برنامه‌تان اجازه لازم را ندارد.

  • میانای کاربر را مسدود نکنید. به‌عبارت دیگر، پیام هشدار تمام‌صفحه‌ای نمایش ندهید که مانع از ادامه استفاده کاربران از برنامه‌تان شود.

  • اولویت کاربر را بپذیرید: هرچند اشکالی ندارد به کاربران اطلاع دهید که عملکرد برنامه به‌دلیل عدم دسترسی به اجازه‌های درخواست‌شده چگونه تحت‌تأثیر قرار می‌گیرد، اما نباید احساس کنند که برای تغییر نظرشان تحت فشار هستند. مطلع کردن کاربر از اینکه به همه ویژگی‌ها دسترسی ندارد در زمان مناسب (مثلاً وقتی می‌خواهد از بخشی از برنامه استفاده کند که بدون اجازه مسدود شده است) مهم است، اما اصرار مداوم برای تجدیدنظر کردن به انتخاب او احترام نمی‌گذارد.

دنبال کردن این دستورالعمل‌ها می‌تواند به کاربران کمک کند تا احساس کنند که می‌توانند دسترسی به داده‌های خصوصی خود را به‌گونه‌ای مدیریت کنند که با ارزش‌های آن‌ها همسو باشد. عدم پذیرش محترمانه تصمیمات بسیار آشکار حریم خصوصی کاربر، به اعتماد و اعتبار نه‌تنها برنامه شما، بلکه کل بوم‌سازگان آسیب می‌رساند.

علاوه‌براین، اگر کاربر درطول مدت نصب برنامه‌تان در دستگاه بیش‌از یک‌بار روی «رد کردن» برای مجوز خاصی تک‌ضرب بزند، اگر برنامه‌تان دوباره آن مجوز را درخواست کند، کاربر دیگر کادر گفتگوی اجازه‌های سیستم را نخواهد دید. کنش کاربر به‌معنای «دیگر نپرس» است و رد دائمی درنظر گرفته می‌شود. بسیار مهم است که فقط زمانی از کاربران درخواست اجازه‌ها شود که به دسترسی به ویژگی خاصی نیاز داشته باشند؛ درغیراین‌صورت، ممکن است به‌طور ناخواسته توانایی درخواست مجدد اجازه‌ها را ازدست بدهید. در شرایط خاص، ممکن است اجازه به‌طور خودکار و بدون اینکه کاربر اقدامی انجام دهد رد شود. (ممکن است اجازه‌ای به‌طور خودکار نیز اعطا شود.) مهم است که درباره رفتار خودکار هیچ فرضی نداشته باشید. هربار که برنامه‌تان نیاز به دسترسی به عملکردی دارد که به اجازه نیاز دارد، بررسی کنید که برنامه‌تان همچنان آن اجازه را داشته باشد. برای ارائه بهترین تجربه کاربری هنگام درخواست اجازه‌های برنامه، روال‌های مطلوب اجازه‌های برنامه را نیز ببینید.

بررسی وضعیت رد شدن هنگام آزمایش و اشکال‌زدایی

برای تشخیص اینکه آیا اجازه‌های برنامه‌ای برای همیشه رد شده است (برای اهداف اشکال‌زدایی و آزمایش)، از فرمان زیر استفاده کنید:

adb shell dumpsys package PACKAGE_NAME

که PACKAGE_NAME نام بسته‌ای است که باید بازرسی شود.

برونداد فرمان حاوی بخش‌هایی است که شبیه این است:

...
runtime permissions:
  android.permission.POST_NOTIFICATIONS: granted=false, flags=[ USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED]
  android.permission.ACCESS_FINE_LOCATION: granted=false, flags=[ USER_SET|USER_FIXED|USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED]
  android.permission.BLUETOOTH_CONNECT: granted=false, flags=[ USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED]
...

اجازه‌هایی که یک‌بار توسط کاربر رد شده‌اند با USER_SET پرچم‌گذاری می‌شوند. اجازه‌هایی که با دو بار انتخاب کردن رد کردن برای همیشه رد شده‌اند با USER_FIXED پرچم‌گذاری می‌شوند.

برای اطمینان از اینکه آزمایش‌کنندگان درطول آزمایش کادر گفتگوی درخواست را می‌بینند، وقتی اشکال‌زدایی برنامه‌تان تمام شد، این پرچم‌ها را بازنشانی کنید. برای انجام این کار، از این فرمان استفاده کنید:

adb shell pm clear-permission-flags PACKAGE_NAME PERMISSION_NAME user-set user-fixed

PERMISSION_NAME نام اجازه‌ای است که می‌خواهید بازنشانی کنید.

PERMISSION_NAME نام اجازه‌ای است که می‌خواهید بازنشانی کنید.

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

اجازه دسترسی یک‌باره

گزینه «فقط این‌بار» دومین دکمه از سه دکمه موجود در کادر گفتگو است.
شکل ۲. کادر گفتگوی سیستم که وقتی برنامه‌ای درخواست اجازه دسترسی یک‌باره می‌کند ظاهر می‌شود.

از Android نسخه ۱۱ (سطح API‏ ۳۰) به بعد، هروقت برنامه‌تان اجازه‌ای مرتبط با مکان، میکروفون، یا دوربین درخواست کند، کادر گفتگوی اجازه‌های سَمت کاربر حاوی گزینه‌ای به‌نام فقط این بار است، همان‌طور که در شکل ۲ نشان داده شده است. اگر کاربر این گزینه را در کادر گفتگو انتخاب کند، به برنامه شما اجازه دسترسی یک‌باره موقت اعطا می‌شود.

سپس برنامه‌تان می‌تواند برای مدت زمانی که به رفتار برنامه‌تان و کنش‌های کاربر بستگی دارد به داده‌های مربوطه دسترسی پیدا کند:

  • وقتی فعالیت برنامه‌تان نمایان باشد، برنامه‌تان می‌تواند به داده‌ها دسترسی داشته باشد.
  • اگر کاربر برنامه شما را به پس‌زمینه بفرستد، برنامه شما می‌تواند برای مدت کوتاهی همچنان به داده‌ها دسترسی داشته باشد.
  • اگر سرویس پیش‌زمینه‌ای را درحالی‌که فعالیت نمایان است راه‌اندازی کنید و سپس کاربر برنامه‌تان را به پس‌زمینه منتقل کند، برنامه‌تان می‌تواند تا زمانی که سرویس پیش‌زمینه‌ای متوقف شود به دسترسی به داده‌ها ادامه دهد.

وقتی اجازه لغو شود، فرایند برنامه خاتمه می‌یابد

اگر کاربر اجازه دسترسی یک‌باره را لغو کند، مثلاً در تنظیمات سیستم، برنامه شما نمی‌تواند به داده‌ها دسترسی داشته باشد، صرف‌نظر از اینکه سرویس پیش‌زمینه‌ای را راه‌اندازی کرده باشید یا نه. مانند هر اجازه دیگری، اگر کاربر اجازه یک‌باره برنامه‌تان را لغو کند، فرایند برنامه‌تان پایان می‌یابد.

وقتی کاربر دفعه بعد برنامه‌تان را باز می‌کند و ویژگی‌ای در برنامه‌تان دسترسی به مکان، میکروفون، یا دوربین را درخواست می‌کند، دوباره از کاربر درخواست می‌شود اجازه دهد.

بازنشانی اجازه‌های استفاده‌نشده

Android چند روش برای بازنشانی اجازه‌های زمان اجرای استفاده‌نشده به حالت پیش‌فرض و ردشده ارائه می‌دهد:

برداشتن دسترسی برنامه

در Android 13 (سطح میانای برنامه‌سازی کاربردی ۳۳) و بالاتر، می‌توانید دسترسی برنامه‌تان به اجازه‌های زمان اجرا را که برنامه‌تان دیگر به آن‌ها نیاز ندارد بردارید. وقتی برنامه‌تان را به‌روز می‌کنید، این مرحله را انجام دهید تا کاربران بهتر متوجه شوند چرا برنامه‌تان همچنان اجازه‌های خاصی را درخواست می‌کند. این دانش به ایجاد اعتماد کاربر در برنامه‌تان کمک می‌کند.

برای برداشتن دسترسی به اجازه زمان اجرا، نام آن اجازه را به revokeSelfPermissionOnKill() منتقل کنید. برای برداشتن دسترسی به گروهی از اجازه‌های زمان اجرا به‌طور هم‌زمان، مجموعه‌ای از نام‌های اجازه را به revokeSelfPermissionsOnKill() ارسال کنید. فرایند برداشتن اجازه به‌صورت ناهمگام اتفاق می‌افتد و همه فرایندهای مرتبط با شناسه کاربری برنامه‌تان را ازبین می‌برد.

برای اینکه سیستم دسترسی برنامه‌تان به اجازه‌ها را بردارد، همه فرایندهای مرتبط با برنامه‌تان باید متوقف شوند. وقتی میانای برنامه‌سازی کاربردی را فراخوانی می‌کنید، سیستم تعیین می‌کند چه زمانی برای متوقف کردن این فرایندها ایمن است. معمولاً سیستم منتظر می‌ماند تا برنامه‌تان به‌جای پیش‌زمینه، مدت زمان طولانی‌ای را در پس‌زمینه اجرا شود.

برای اطلاع دادن به کاربر درباره اینکه برنامه‌تان دیگر به اجازه‌های زمان اجرای خاصی نیاز ندارد، دفعه بعدی که کاربر برنامه‌تان را راه‌اندازی می‌کند کادر گفتگویی نشان دهید. این کادر گفتگو می‌تواند شامل فهرست اجازه‌ها باشد.

بازنشانی خودکار اجازه‌های برنامه‌های استفاده‌نشده

اگر برنامه شما Android 11 (سطح میانای برنامه‌سازی کاربردی 30) یا بالاتر را هدف قرار می‌دهد و برای چند ماه استفاده نشود، سیستم با بازنشانی خودکار اجازه‌های حساس زمان اجرا که کاربر به برنامه شما اعطا کرده است، از داده‌های کاربر محافظت می‌کند. در راهنمای خواب موقت برنامه بیشتر بدانید.

درصورت لزوم، درخواست کنید که کنترل‌کننده پیش‌فرض شوید

برخی‌از برنامه‌ها به دسترسی به اطلاعات حساس کاربر مربوط به گزارش‌های تماس و پیامک‌ها وابسته هستند. اگر می‌خواهید اجازه‌های مختص گزارش‌های تماس و پیامک‌ها را درخواست کنید و برنامه‌تان را در «فروشگاه Play» منتشر کنید، باید قبل‌از درخواست این اجازه‌های زمان اجرا، از کاربر بخواهید برنامه‌تان را به‌عنوان کنترل‌كننده پیش‌فرض برای عملکرد اصلی سیستم تنظیم کند.

برای اطلاعات بیشتر درباره گرداننده‌های پیش‌فرض، ازجمله راهنمایی درباره نمایش پیام‌واره گرداننده پیش‌فرض به کاربران، راهنمای مربوط به اجازه‌هایی را که فقط در گرداننده‌های پیش‌فرض استفاده می‌شوند ببینید.

اعطا کردن همه اجازه‌های زمان اجرا برای اهداف آزمایشی

برای اعطای خودکار همه اجازه‌های زمان اجرا هنگام نصب برنامه در شبیه‌ساز یا دستگاه آزمایشی، از گزینه -g برای فرمان adb shell install استفاده کنید، همان‌طور که در تکه‌کد زیر نشان داده شده است:

adb shell install -g PATH_TO_APK_FILE

منابع بیشتر

برای اطلاعات بیشتر درباره اجازه‌ها، این مقاله‌ها را بخوانید:

برای کسب اطلاعات بیشتر درباره درخواست اجازه‌ها، نمونه‌های اجازه‌ها را مرور کنید.

همچنین می‌توانید این codelab را که بهترین روش‌های حریم خصوصی را نشان می‌دهد تکمیل کنید.