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

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

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

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

اصول اساسی

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

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

گردش کار درخواست مجوزها

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

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

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

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

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

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

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

  7. پاسخ کاربر را بررسی کنید - اینکه آیا آنها تصمیم به اعطای مجوز زمان اجرا یا رد آن گرفته‌اند.

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

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

شکل ۱. نموداری که گردش کار اعلان و درخواست مجوزهای زمان اجرا در اندروید را نشان می‌دهد.

تعیین کنید که آیا برنامه شما قبلاً مجوز دریافت کرده است یا خیر

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

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

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

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

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

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

اگر متد 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() ظاهر می‌شود، سفارشی کند. برای ارائه اطلاعات یا زمینه بیشتر به کاربر، رابط کاربری برنامه خود را تغییر دهید تا کاربران راحت‌تر بتوانند درک کنند که چرا یک ویژگی در برنامه شما به یک مجوز خاص نیاز دارد. به عنوان مثال، می‌توانید متن دکمه‌ای را که این ویژگی را فعال می‌کند، تغییر دهید.

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

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

کاتلین

// Register the permissions callback, which handles the user's response to the
// system permissions dialog. Save the return value, an instance of
// ActivityResultLauncher. You can use either a val, as shown in this snippet,
// or a lateinit var in your onAttach() or onCreate() method.
val requestPermissionLauncher =
    registerForActivityResult(RequestPermission()
    ) { isGranted: Boolean ->
        if (isGranted) {
            // 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.
        }
    }

جاوا

// Register the permissions callback, which handles the user's response to the
// system permissions dialog. Save the return value, an instance of
// ActivityResultLauncher, as an instance variable.
private ActivityResultLauncher<String> requestPermissionLauncher =
    registerForActivityResult(new RequestPermission(), isGranted -> {
        if (isGranted) {
            // 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.
        }
    });

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

کاتلین

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.
    }
}

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

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

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

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

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

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

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

    در اندروید ۱۰ (سطح API 29) و بالاتر، باید یک نوع سرویس پیش‌زمینه از location تعریف کنید، همانطور که در قطعه کد زیر نشان داده شده است. در نسخه‌های قبلی اندروید، توصیه می‌شود که این نوع سرویس پیش‌زمینه را تعریف کنید.

    <!-- 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>

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

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

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

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

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

<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>

مدیریت رد مجوز

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

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

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

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

در عین حال، برنامه شما باید به تصمیم کاربر برای رد یک مجوز احترام بگذارد. از اندروید ۱۱ (سطح API 30)، اگر کاربر در طول مدت نصب برنامه شما روی یک دستگاه، بیش از یک بار روی گزینه «رد کردن» برای یک مجوز خاص ضربه بزند، در صورت درخواست مجدد آن مجوز توسط برنامه، کاربر پنجره مجوزهای سیستم را نمی‌بیند. این اقدام کاربر به معنای «دیگر نپرس» است. در نسخه‌های قبلی، کاربران هر بار که برنامه شما درخواست مجوز می‌کرد، پنجره مجوزهای سیستم را می‌دیدند، مگر اینکه قبلاً کادر یا گزینه «دیگر نپرس» را انتخاب کرده باشند.

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

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

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

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

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

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 علامت‌گذاری می‌شوند. مجوزهایی که با دو بار انتخاب Deny به طور دائم رد شده‌اند، با USER_FIXED علامت‌گذاری می‌شوند.

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

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

PERMISSION_NAME نام مجوزی است که می‌خواهید آن را مجدداً تنظیم کنید.

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

مجوزهای یک‌بار مصرف

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

از اندروید ۱۱ (سطح API 30)، هر زمان که برنامه شما درخواست مجوزی مربوط به مکان، میکروفون یا دوربین را داشته باشد، پنجره مجوزهای کاربر شامل گزینه‌ای به نام «فقط این بار» است، همانطور که در شکل ۲ نشان داده شده است. اگر کاربر این گزینه را در پنجره انتخاب کند، به برنامه شما یک مجوز موقت یک‌باره اعطا می‌شود.

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

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

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

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

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

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

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

دسترسی برنامه را حذف کنید

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

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

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

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

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

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

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

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

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

اعطای تمام مجوزهای زمان اجرا برای اهداف آزمایشی

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

adb shell install -g PATH_TO_APK_FILE

منابع اضافی

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

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

شما همچنین می‌توانید این آزمایشگاه کد را که بهترین شیوه‌های حفظ حریم خصوصی را نشان می‌دهد، تکمیل کنید.