طلب أذونات التشغيل

يتم تشغيل كل تطبيق Android في وضع حماية ذي وصول محدود. إذا كان تطبيقك بحاجة إلى استخدام موارد أو معلومات خارج بيئة الاختبار المعزولة الخاصة به، يمكنك تضمين إذن وقت التشغيل في بيان التطبيق وإعداد طلب إذن يتيح هذا الوصول. هذه الخطوات هي جزء من عملية استخدام الأذونات.

إذا أعلنت عن أي أذونات خطيرة، وتم تثبيت تطبيقك على جهاز يعمل بالإصدار 6.0 من نظام التشغيل Android (المستوى 23 من واجهة برمجة التطبيقات) أو إصدار أحدث، عليك طلب الأذونات الخطيرة في وقت التشغيل باتّباع الخطوات الواردة في هذا الدليل.

إذا لم تحدّد أي أذونات خطيرة، أو إذا تم تثبيت تطبيقك على جهاز يعمل بالإصدار 5.1 من نظام التشغيل Android (المستوى 22 من واجهة برمجة التطبيقات) أو إصدار أقدم، سيتم منح الأذونات تلقائيًا، ولن تحتاج إلى إكمال أي من الخطوات المتبقية في هذه الصفحة.

المبادئ الأساسية

في ما يلي المبادئ الأساسية لطلب الأذونات في وقت التشغيل:

  • اطلب الحصول على إذن في السياق المناسب، أي عندما يبدأ المستخدم التفاعل مع الميزة التي تتطلّب هذا الإذن.
  • لا تحظر المستخدم. يجب دائمًا توفير خيار لإلغاء مسار واجهة المستخدم التعليمية، مثل المسار الذي يوضّح الأساس المنطقي لطلب الأذونات.
  • إذا رفض المستخدم الإذن الذي تطلبه إحدى الميزات أو أبطله، يمكنك خفض إصدار تطبيقك على نحو ملائم مع السماح للمستخدم بمواصلة استخدام التطبيق، ربما عن طريق إيقاف الميزة التي تتطلّب الإذن.
  • لا تفترض أي سلوك للنظام. على سبيل المثال، لا تفترض أنّ الأذونات تظهر في مجموعة الأذونات نفسها. لا تساعد مجموعة الأذونات النظام إلا في تقليل عدد مربّعات حوار النظام التي تظهر للمستخدم عندما يطلب تطبيق أذونات ذات صلة وثيقة.

سير العمل لطلب الأذونات

قبل الإفصاح عن أذونات التشغيل وطلبها في تطبيقك، عليك تقييم ما إذا كان تطبيقك يحتاج إلى ذلك. يمكنك تنفيذ العديد من حالات الاستخدام في تطبيقك، مثل التقاط الصور وإيقاف تشغيل الوسائط مؤقتًا وعرض الإعلانات ذات الصلة، بدون الحاجة إلى الإفصاح عن أي أذونات.

إذا تبيّن لك أنّ تطبيقك يحتاج إلى الإفصاح عن أذونات التشغيل وطلبها، أكمِل الخطوات التالية:

  1. تحديد الأذونات التي قد يحتاج تطبيقك إلى طلبها في ملف بيان التطبيق
  2. صمِّم تجربة المستخدم (UX) في تطبيقك بحيث تكون الإجراءات المحدّدة في تطبيقك مرتبطة بأذونات محدّدة أثناء التشغيل. أخبِر المستخدمين بالإجراءات التي قد تتطلّب منهم منح تطبيقك الإذن بالوصول إلى بيانات المستخدمين الخاصة.
  3. انتظِر أن يطلب المستخدم تنفيذ المهمة أو الإجراء في تطبيقك الذي يتطلّب الوصول إلى بيانات مستخدم خاصة محدّدة. في ذلك الوقت، يمكن لتطبيقك طلب إذن وقت التشغيل اللازم للوصول إلى تلك البيانات.
  4. تحقَّق مما إذا كان المستخدم قد منح إذن التشغيل الذي يتطلبه تطبيقك. وفي هذه الحالة، يمكن لتطبيقك الوصول إلى بيانات المستخدم الخاصة. وإذا استمرت المشكلة، فانتقِل إلى الخطوة التالية.

    عليك التحقّق مما إذا كان لديك إذن في كل مرة تنفّذ فيها عملية تتطلّب هذا الإذن.

  5. تحقَّق مما إذا كان تطبيقك بحاجة إلى عرض سبب للمستخدم يوضّح سبب طلب تطبيقك من المستخدم منح إذن تشغيل معيّن. إذا حدّد النظام أنّ تطبيقك لا يحتاج إلى عرض سبب وجيه، انتقِل إلى الخطوة التالية مباشرةً بدون عرض عنصر واجهة مستخدم.

    ومع ذلك، إذا حدّد النظام أنّ تطبيقك يجب أن يعرض سببًا، يجب عرض هذا السبب للمستخدم في أحد عناصر واجهة المستخدِم. في هذا السبب، وضِّح البيانات التي يحاول تطبيقك الوصول إليها والفوائد التي يمكن أن يقدّمها التطبيق للمستخدم إذا منح إذن التشغيل. بعد أن يقرّ المستخدم بالأساس المنطقي، انتقِل إلى الخطوة التالية.

  6. اطلب إذن وقت التشغيل الذي يحتاج إليه تطبيقك للوصول إلى بيانات المستخدم الخاصة. يعرض النظام طلبًا للحصول على إذن تشغيل، مثل الطلب الموضّح في صفحة نظرة عامة على الأذونات.

  7. تحقَّق من استجابة المستخدم، أي ما إذا اختار منح إذن وقت التشغيل أو رفضه.

  8. إذا منح المستخدم الإذن لتطبيقك، يمكنك الوصول إلى بيانات المستخدم الخاصة. إذا رفض المستخدم الإذن بدلاً من ذلك، عليك تخفيض مستوى تجربة تطبيقك بشكل سلس لكي يوفّر للمستخدم وظائف بدون المعلومات المحمية بموجب هذا الإذن.

يوضّح الشكل 1 سير العمل ومجموعة القرارات المرتبطة بهذه العملية:

مخطط انسيابي يوضّح عملية اتخاذ القرار بشأن طلب أذونات التشغيل، بدءًا بإجراء أحد التطبيقات، والتحقّق مما إذا تم منح الإذن، والتحقّق مما إذا كان هناك حاجة إلى تقديم سبب، وطلب الإذن، والتعامل مع رد المستخدم.
الشكل 1. مخطّط يوضّح سير العمل الخاص بتحديد أذونات وقت التشغيل وطلبها على Android

تحديد ما إذا كان تطبيقك قد سبق له الحصول على الإذن

للتحقّق ممّا إذا كان المستخدم قد منح تطبيقك إذنًا معيّنًا، مرِّر هذا الإذن إلى طريقة [ContextCompat.checkSelfPermission()][12]. تعرض هذه الطريقة إما PERMISSION_GRANTED أو PERMISSION_DENIED، وذلك حسب ما إذا كان تطبيقك لديه الإذن أم لا.

توضيح سبب احتياج تطبيقك إلى الإذن

يعرض مربّع حوار الأذونات الذي يظهره النظام عند طلب [requestPermissions()][15] الأذونات، الأذونات التي يريدها تطبيقك، ولكنّه لا يوضّح سبب طلبها. في بعض الحالات، قد يجد المستخدم ذلك محيّرًا. من المستحسن أن توضّح للمستخدم سبب طلب تطبيقك للأذونات قبل استدعاء requestPermissions().

تشير الأبحاث إلى أنّ المستخدمين يكونون أكثر ارتياحًا لطلبات الأذونات إذا عرفوا سبب احتياج التطبيق إليها، مثل ما إذا كان الإذن مطلوبًا لدعم إحدى الميزات الأساسية للتطبيق أو لعرض الإعلانات. نتيجةً لذلك، إذا كنت تستخدم جزءًا فقط من طلبات البيانات من واجهة برمجة التطبيقات التي تندرج ضمن مجموعة أذونات، عليك إدراج الأذونات التي تستخدمها بوضوح وتوضيح سبب استخدامها. على سبيل المثال، إذا كنت تستخدم الموقع الجغرافي التقريبي فقط، عليك إعلام المستخدم بذلك في وصف تطبيقك أو في مقالات المساعدة حول تطبيقك.

في ظروف معيّنة، من المفيد أيضًا إعلام المستخدمين في الوقت الفعلي بشأن الوصول إلى البيانات الحساسة. على سبيل المثال، إذا كنت بصدد الوصول إلى الكاميرا أو الميكروفون، ننصحك بإعلام المستخدم بذلك من خلال استخدام رمز إشعار في مكان ما في تطبيقك أو في لوحة الإشعارات (إذا كان التطبيق يعمل في الخلفية)، وذلك حتى لا يبدو أنّك تجمع البيانات بشكل سرّي.

إذا كنت بحاجة إلى طلب إذن لتفعيل إحدى الميزات، ولكن السبب غير واضح للمستخدم، عليك إيجاد طريقة لتوضيح سبب حاجتك إلى أذونات حساسة.

إذا عرضت الطريقة ContextCompat.checkSelfPermission() القيمة PERMISSION_DENIED، استدعِ [shouldShowRequestPermissionRationale()][16]. إذا عرضت هذه الطريقة true، اعرض واجهة مستخدم تعليمية للمستخدم. في واجهة المستخدم هذه، وضِّح سبب احتياج الميزة التي يريد المستخدم تفعيلها إلى إذن معيّن.

بالإضافة إلى ذلك، إذا كان تطبيقك يطلب إذنًا متعلقًا بالموقع الجغرافي أو الميكروفون أو الكاميرا، ننصحك بتوضيح سبب حاجة تطبيقك إلى الوصول إلى هذه المعلومات.

طلب الحصول على الأذونات

بعد أن يعرض المستخدم واجهة مستخدم تعليمية، أو إذا كانت القيمة المعروضة من shouldShowRequestPermissionRationale() تشير إلى أنّه لا حاجة إلى عرض واجهة مستخدم تعليمية، اطلب الإذن. سيظهر للمستخدمين مربّع حوار خاص بأذونات النظام، حيث يمكنهم اختيار ما إذا كانوا يريدون منح تطبيقك إذنًا معيّنًا.

لإجراء ذلك، استخدِم عقد RequestPermission المضمّن في إحدى مكتبات AndroidX، حيث تسمح للنظام بإدارة رمز طلب الإذن نيابةً عنك. بما أنّ استخدام العقد RequestPermission يسهّل منطقك، ننصحك باستخدامه عند الإمكان. ومع ذلك، يمكنك أيضًا إدارة رمز الطلب بنفسك إذا لزم الأمر كجزء من طلب الإذن، ويمكنك تضمين رمز الطلب هذا في منطق معاودة الاتصال الخاص بالإذن.

السماح للنظام بإدارة رمز طلب الإذن

للسماح للنظام بإدارة رمز الطلب المرتبط بطلب أذونات، أضِف عناصر تابعة للمكتبات التالية في ملف build.gradle الخاص بالوحدة:

يمكنك بعد ذلك استخدام إحدى الفئات التالية:

توضّح الخطوات التالية كيفية استخدام العقد RequestPermission. تكون عملية إعداد عقد RequestMultiplePermissions مشابهة تقريبًا.

  1. في منطق تهيئة النشاط أو الجزء، مرِّر تنفيذًا لواجهة ActivityResultCallback إلى استدعاء registerForActivityResult(). يحدّد ActivityResultCallback الطريقة التي يتعامل بها تطبيقك مع رد المستخدم على طلب الإذن.

    احتفظ بمرجع إلى القيمة المعروضة من registerForActivityResult()، والتي تكون من النوع ActivityResultLauncher.

  2. لعرض مربّع حوار أذونات النظام عند الضرورة، استدعِ الطريقة launch() على مثيل ActivityResultLauncher الذي حفظته في الخطوة السابقة.

    بعد استدعاء launch()، يظهر مربّع حوار أذونات النظام. عندما يتّخذ المستخدم قرارًا، يستدعي النظام بشكل غير متزامن عملية التنفيذ الخاصة بك للدالة ActivityResultCallback التي حدّدتها في الخطوة السابقة.

    ملاحظة: لا يمكن لتطبيقك تخصيص مربّع الحوار الذي يظهر عند استدعاء launch(). لتقديم المزيد من المعلومات أو السياق للمستخدم، يمكنك تغيير واجهة مستخدم تطبيقك لتسهيل فهم المستخدمين لسبب حاجة إحدى الميزات في تطبيقك إلى إذن معيّن. على سبيل المثال، يمكنك تغيير النص في الزر الذي يفعّل الميزة.

    بالإضافة إلى ذلك، يشير النص في مربّع حوار أذونات النظام إلى مجموعة الأذونات المرتبطة بالإذن الذي طلبته. تم تصميم تجميع الأذونات هذا لتسهيل استخدام النظام، ويجب ألا يعتمد تطبيقك على الأذونات التي تندرج ضمن مجموعة أذونات معيّنة أو خارجها.

يوضّح مقتطف الرمز التالي كيفية التعامل مع استجابة الأذونات:

Kotlin

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

Java

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);
}

يوضّح مقتطف الرمز البرمجي التالي العملية المقترَحة للتحقّق من توفّر إذن وطلب إذن من المستخدم عند الضرورة:

Kotlin

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

Java

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()][15].

يوضّح مقتطف الرمز التالي كيفية طلب إذن باستخدام رمز طلب:

Kotlin

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

Java

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(). يُدخل النظام استجابة المستخدم في مربّع حوار الأذونات، بالإضافة إلى رمز الطلب الذي حدّدته، كما هو موضّح في مقتطف الرمز التالي:

Kotlin

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

Java

@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 (المستوى 29 من واجهة برمجة التطبيقات) والإصدارات الأحدث، يجب تعريف نوع خدمة تعمل في المقدّمة بقيمة 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. في ما يلي بعض الأمثلة:

  • ضمن تطبيق لمشاركة الموقع الجغرافي مع العائلة، تتيح إحدى الميزات للمستخدمين مشاركة الموقع الجغرافي بشكل مستمر مع أفراد العائلة.
  • في أحد تطبيقات إنترنت الأشياء، تتيح إحدى الميزات للمستخدمين ضبط أجهزة المنزل على أن يتم إيقافها عندما يغادر المستخدم المنزل وإعادة تشغيلها عندما يعود إليه.

يصنّف النظام تطبيقك على أنّه يستخدم بيانات الموقع الجغرافي في الخلفية إذا كان يصل إلى الموقع الجغرافي الحالي للجهاز في أي حالة أخرى غير الحالات الموضّحة في قسم الموقع الجغرافي في المقدّمة. تكون دقة الموقع الجغرافي في الخلفية هي نفسها دقة الموقع الجغرافي في المقدّمة، والتي تعتمد على أذونات الموقع الجغرافي التي يحدّدها تطبيقك.

في الإصدار 10 من نظام التشغيل Android (المستوى 29 لواجهة برمجة التطبيقات) والإصدارات الأحدث، يجب الإفصاح عن إذن 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>

التعامل مع رفض الإذن

إذا رفض المستخدم طلب الحصول على إذن، يجب أن يوضّح تطبيقك للمستخدمين الآثار المترتبة على رفض الإذن. وعلى وجه الخصوص، يجب أن يوضّح تطبيقك للمستخدمين الميزات التي لا تعمل بسبب عدم توفّر الإذن. عند إجراء ذلك، يُرجى مراعاة أفضل الممارسات التالية:

  • توجيه انتباه المستخدم: يُرجى إبراز جزء معيّن من واجهة مستخدم تطبيقك تتوفّر فيه وظائف محدودة لأنّ تطبيقك لا يملك الإذن اللازم. تشمل الأمثلة على ما يمكنك فعله ما يلي:

    • عرض رسالة في المكان الذي كان من المفترض أن تظهر فيه نتائج الميزة أو بياناتها
    • اعرض زرًا مختلفًا يحتوي على رمز خطأ ولون.
  • أضِف معلومات دقيقة. لا تعرض رسالة عامة. بدلاً من ذلك، يجب توضيح الميزات غير المتاحة لأنّ تطبيقك لا يملك الإذن اللازم.

  • لا تحظر واجهة المستخدم. بعبارة أخرى، لا تعرض رسالة تحذير بملء الشاشة تمنع المستخدمين من مواصلة استخدام تطبيقك نهائيًا.

في الوقت نفسه، يجب أن يحترم تطبيقك قرار المستخدم برفض منح أحد الأذونات. بدءًا من نظام التشغيل Android 11 (المستوى 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 علامة على الأذونات التي رفضها المستخدم مرة واحدة. يتم وضع علامة USER_FIXED على الأذونات التي تم رفضها نهائيًا من خلال النقر على رفض مرتين.

للتأكّد من أنّ المختبِرين يرون مربّع حوار الطلب أثناء الاختبار، عليك إعادة ضبط هذه العلامات بعد الانتهاء من تصحيح أخطاء تطبيقك. ولإجراء ذلك، استخدِم الأمر التالي:

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

PERMISSION_NAME هو اسم الإذن الذي تريد إعادة ضبطه.

PERMISSION_NAME هو اسم الإذن الذي تريد إعادة ضبطه.

للاطّلاع على قائمة كاملة بأذونات تطبيقات Android، انتقِل إلى صفحة مرجع واجهة برمجة التطبيقات الخاصة بالأذونات.

أذونات لمرة واحدة

الخيار المسمّى &quot;هذه المرة فقط&quot; هو الزر الثاني من بين ثلاثة أزرار في مربّع الحوار.
الشكل 2. مربّع حوار النظام الذي يظهر عندما يطلب تطبيق إذنًا لمرة واحدة

بدءًا من الإصدار 11 من نظام التشغيل Android (المستوى 30 من واجهة برمجة التطبيقات)، عندما يطلب تطبيقك إذنًا متعلّقًا بالموقع الجغرافي أو الميكروفون أو الكاميرا، سيحتوي مربّع حوار الأذونات المعروض للمستخدمين على خيار باسم هذه المرة فقط، كما هو موضّح في الشكل 2. إذا اختار المستخدم هذا الخيار في مربّع الحوار، سيتم منح تطبيقك إذنًا مؤقتًا لمرة واحدة.

يمكن لتطبيقك بعد ذلك الوصول إلى البيانات ذات الصلة لمدة زمنية تعتمد على سلوك تطبيقك وإجراءات المستخدم:

  • عندما يكون نشاط تطبيقك مرئيًا، يمكن لتطبيقك الوصول إلى البيانات.
  • إذا أرسل المستخدم تطبيقك إلى الخلفية، يمكن لتطبيقك مواصلة الوصول إلى البيانات لفترة قصيرة من الوقت.
  • إذا شغّلت خدمة تعمل في المقدّمة أثناء ظهور النشاط، ثم نقل المستخدم تطبيقك إلى الخلفية، سيظل بإمكان تطبيقك الوصول إلى البيانات إلى أن تتوقف الخدمة التي تعمل في المقدّمة.

تنتهي عملية التطبيق عند إبطال الإذن

إذا ألغى المستخدم الإذن لمرة واحدة، مثلاً في إعدادات النظام، لن يتمكّن تطبيقك من الوصول إلى البيانات، بغض النظر عمّا إذا كنت قد شغّلت خدمة تعمل في المقدّمة. وكما هو الحال مع أي إذن، إذا أبطل المستخدم الإذن المؤقت الذي منحه لتطبيقك، سيتم إنهاء عملية تطبيقك.

عندما يفتح المستخدم تطبيقك في المرة التالية وتطلب إحدى الميزات في تطبيقك إذن الوصول إلى الموقع الجغرافي أو الميكروفون أو الكاميرا، سيُطلب من المستخدم منح الإذن مرة أخرى.

إعادة ضبط الأذونات غير المستخدَمة

يوفّر نظام التشغيل Android عدة طرق لإعادة ضبط أذونات وقت التشغيل غير المستخدَمة إلى حالتها التلقائية، أي حالة الرفض:

إزالة إذن وصول التطبيق

على نظام التشغيل Android 13 (المستوى 33 لواجهة برمجة التطبيقات) والإصدارات الأحدث، يمكنك إزالة إذن وصول تطبيقك إلى أذونات وقت التشغيل التي لم يعُد تطبيقك يحتاج إليها. عند تحديث تطبيقك، عليك تنفيذ هذه الخطوة لزيادة احتمالية فهم المستخدمين لسبب استمرار تطبيقك في طلب أذونات معيّنة. تساعد هذه المعرفة في بناء ثقة المستخدمين في تطبيقك.

لإزالة إذن الوصول إلى إذن وقت التشغيل، مرِّر اسم هذا الإذن إلى revokeSelfPermissionOnKill(). لإزالة إذن الوصول إلى مجموعة من أذونات وقت التشغيل في الوقت نفسه، مرِّر مجموعة من أسماء الأذونات إلى revokeSelfPermissionsOnKill(). تتم عملية إزالة الإذن بشكل غير متزامن، ويتم إيقاف جميع العمليات المرتبطة بمعرّف المستخدم (UID) لتطبيقك.

لكي يزيل النظام إذن وصول تطبيقك إلى الأذونات، يجب إيقاف جميع العمليات المرتبطة بتطبيقك. عند استدعاء واجهة برمجة التطبيقات، يحدّد النظام الوقت المناسب لإيقاف هذه العمليات. عادةً، ينتظر النظام إلى أن يقضي تطبيقك فترة طويلة من الوقت في التشغيل في الخلفية بدلاً من التشغيل في المقدّمة.

لإعلام المستخدم بأنّ تطبيقك لم يعُد يتطلّب الوصول إلى أذونات تشغيل معيّنة، اعرض مربّع حوار في المرة التالية التي يفتح فيها المستخدم تطبيقك. ويمكن أن يتضمّن مربّع الحوار هذا قائمة الأذونات.

إعادة ضبط أذونات التطبيقات غير المستخدَمة تلقائيًا

إذا كان تطبيقك يستهدف الإصدار 11 من نظام التشغيل Android (المستوى 30 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث ولم يتم استخدامه لعدة أشهر، سيحمي النظام بيانات المستخدم من خلال إعادة ضبط أذونات وقت التشغيل الحسّاسة التي منحها المستخدم لتطبيقك تلقائيًا. يمكنك الاطّلاع على مزيد من المعلومات في الدليل حول وضع التطبيقات في وضع السكون.

طلب أن يصبح التطبيق المعالج التلقائي إذا لزم الأمر

تعتمد بعض التطبيقات على الوصول إلى معلومات المستخدمين الحسّاسة المتعلقة بسجلات المكالمات ورسائل SMS. إذا كنت تريد طلب الأذونات الخاصة بسجلّات المكالمات ورسائل SMS ونشر تطبيقك على "متجر Play"، عليك أن تطلب من المستخدم ضبط تطبيقك كمعالِج تلقائي لإحدى وظائف النظام الأساسية قبل طلب أذونات التشغيل هذه.

لمزيد من المعلومات حول معالجات التطبيقات التلقائية، بما في ذلك إرشادات حول عرض طلب معالج التطبيق التلقائي للمستخدمين، راجِع الدليل حول الأذونات المستخدَمة فقط في معالجات التطبيقات التلقائية.

منح جميع أذونات التشغيل لأغراض الاختبار

لمنح جميع أذونات وقت التشغيل تلقائيًا عند تثبيت تطبيق على محاكي أو جهاز اختبار، استخدِم الخيار -g للأمر adb shell install، كما هو موضّح في مقتطف الرمز البرمجي التالي:

adb shell install -g PATH_TO_APK_FILE

مراجع إضافية

للحصول على معلومات إضافية حول الأذونات، يُرجى قراءة المقالات التالية:

لمزيد من المعلومات حول طلب الأذونات، راجِع أمثلة الأذونات.

يمكنك أيضًا إكمال الدرس التطبيقي حول الترميز الذي يوضّح أفضل ممارسات الخصوصية.

[12]: /reference/androidx/core/content/ContextCompat#checkSelfPermission(android.content.Context, java.lang.String)

[15]: /reference/androidx/core/app/ActivityCompat.html#requestPermissions(android.app.Activity, java.lang.String[], int) [16]: /reference/androidx/core/app/ActivityCompat#shouldShowRequestPermissionRationale(android.app.Activity, java.lang.String)