يتم تشغيل كل تطبيق Android في وضع الحماية المحدود الوصول. إذا كان تطبيقك بحاجة إلى استخدام موارد أو معلومات خارج نطاق الحماية الخاص به، يمكنك الإعلان عن إذن التشغيل وإعداد طلب الحصول على إذن يوفّر إمكانية الوصول هذه. هذه الخطوات هي جزء من سير العمل لاستخدام الأذونات.
إذا أعلنت عن أي أذونات خطيرة، وإذا كان تطبيقك مثبّتًا على جهاز يعمل بنظام التشغيل Android 6.0 (مستوى واجهة برمجة التطبيقات 23) أو إصدار أحدث، عليك طلب الأذونات الخطيرة في وقت التشغيل باتّباع الخطوات الواردة في هذا الدليل.
إذا لم تطلب أي أذونات خطيرة، أو إذا كان تطبيقك مثبّتًا على جهاز يعمل بالإصدار 5.1 من نظام التشغيل Android (المستوى 22 لواجهة برمجة التطبيقات) أو إصدار أقدم، يتم منح الأذونات تلقائيًا، ولن تحتاج إلى إكمال أي من الخطوات المتبقية في هذه الصفحة.
المبادئ الأساسية
في ما يلي المبادئ الأساسية لطلب الأذونات أثناء وقت التشغيل:
- اطلب الإذن في السياق، عندما يبدأ المستخدم في التفاعل مع الميزة التي تتطلب ذلك.
- لا تحظر المستخدم. يجب دائمًا توفير خيار لإلغاء مسار واجهة المستخدم التعليمية، مثل المسار الذي يشرح سبب طلب الأذونات.
- إذا رفض المستخدم الإذن الذي تطلبه إحدى الميزات أو أبطله، يمكنك خفض إصدار تطبيقك على نحو ملائم مع السماح للمستخدم بمواصلة استخدام التطبيق، وذلك من خلال إيقاف الميزة التي تتطلّب الإذن.
- لا تفترض أي سلوك للنظام. على سبيل المثال، لا تفترض أنّ الأذونات تظهر في مجموعة الأذونات نفسها. تساعد مجموعة الأذونات النظام في تقليل عدد مربّعات الحوار التي تظهر للمستخدم عندما يطلب أحد التطبيقات أذونات وثيقة الصلة.
سير العمل لطلب الأذونات
قبل الإفصاح عن أذونات التشغيل وطلبها في تطبيقك، عليك تقييم ما إذا كان تطبيقك بحاجة إلى ذلك. يمكنك تنفيذ العديد من حالات الاستخدام في تطبيقك، مثل التقاط الصور وإيقاف تشغيل الوسائط مؤقتًا وعرض الإعلانات الملائمة، بدون الحاجة إلى الإفصاح عن أي أذونات.
إذا تبيّن لك أنّ تطبيقك يحتاج إلى تضمين أذونات التشغيل في نموذج البيان وطلبها، يُرجى إكمال الخطوات التالية:
- أعلِن عن الأذونات التي قد يحتاج تطبيقك إلى طلبها في ملف بيان التطبيق.
- صمِّم تجربة المستخدم (UX) في تطبيقك بحيث ترتبط إجراءات معيّنة في تطبيقك بأذونات تشغيل معيّنة. أعلِم المستخدمين بالإجراءات التي قد تتطلّب منهم منح تطبيقك الإذن بالوصول إلى بيانات المستخدمين الخاصة.
- انتظِر حتى يستدعي المستخدم المهمة أو الإجراء في تطبيقك الذي يتطلب الوصول إلى بيانات خاصة محدّدة للمستخدم. في ذلك الوقت، يمكن لتطبيقك طلب إذن التشغيل المطلوب للوصول إلى تلك البيانات.
thought التحقّق مما إذا كان المستخدم قد منح
إذن التشغيل الذي يتطلّبه تطبيقك إذا كان الأمر كذلك، يمكن لتطبيقك الوصول إلى بيانات المستخدم الخاصة. وإذا استمرت المشكلة، فانتقِل إلى الخطوة التالية.
يجب التحقّق مما إذا كان لديك إذن في كل مرة تنفّذ فيها عملية تتطلّب هذا الإذن.
التحقّق مما إذا كان يجب أن يعرض تطبيقك سببًا للمستخدم، يوضّح سبب حاجة تطبيقك إلى أن يمنحه المستخدم إذن تشغيل معيّنًا. إذا قرّر النظام أنّ تطبيقك لا يجب أن يعرض بيانًا منطقيًا، انتقِل إلى الخطوة التالية مباشرةً بدون عرض عنصر في واجهة المستخدم.
إذا قرّر النظام أنّ تطبيقك يجب أن يعرض سببًا، يجب عرض السبب للمستخدم في عنصر في واجهة المستخدم. في هذا البيان، يجب أن توضّح البيانات التي يحاول تطبيقك الوصول إليها والمزايا التي يمكن أن يقدّمها التطبيق للمستخدم إذا منح إذن التشغيل. بعد أن يقرّ المستخدم بالأساس المنطقي، انتقِل إلى الخطوة التالية.
طلب إذن التشغيل الذي يحتاجه تطبيقك للوصول إلى بيانات المستخدمين الخاصة يعرض النظام طلبًا للحصول على إذن التشغيل، مثل الطلب المعروض في صفحة نظرة عامة على الأذونات.
تحقَّق من استجابة المستخدم، سواء اختار منح إذن التشغيل أو رفضه.
إذا منح المستخدم الإذن لتطبيقك، يمكنك الوصول إلى بيانات المستخدم الخاصة. إذا رفض المستخدم منح الإذن، يجب أن يتكيّف تطبيقك مع الإصدارات الأقدم لكي يوفّر الوظائف للمستخدم بدون المعلومات المحمية بهذا الإذن.
يوضّح الشكل 1 سير العمل ومجموعة القرارات المرتبطة بهذه العملية:
تحديد ما إذا كان تطبيقك قد حصل على الإذن من قبل
للتحقّق مما إذا كان المستخدم قد منح تطبيقك إذنًا معيّنًا، يمكنك تمرير هذا الإذن إلى طريقة ContextCompat.checkSelfPermission().
تعرض هذه الطريقة إما PERMISSION_GRANTED أو PERMISSION_DENIED، بناءً على ما إذا كان تطبيقك يملك الإذن.
يُرجى توضيح سبب حاجة تطبيقك إلى الإذن
يوضّح مربّع حوار الأذونات الذي يعرضه النظام عند طلب
requestPermissions() الإذن الذي يريده تطبيقك، ولكنّه لا
يوضّح السبب. في بعض الحالات، قد يجد المستخدم ذلك محيرًا. من الأفضل أن توضّح للمستخدم سبب طلب تطبيقك للأذونات قبل استدعاء requestPermissions().
تُظهر الأبحاث أنّ المستخدمين يشعرون براحة أكبر تجاه طلبات الحصول على الأذونات إذا عرفوا سبب حاجة التطبيق إليها، مثلاً ما إذا كان الإذن مطلوبًا لإتاحة ميزة أساسية في التطبيق أو لأغراض إعلانية. لذلك، إذا كنت تستخدم جزءًا فقط من طلبات البيانات من واجهة برمجة التطبيقات التي تندرج ضمن مجموعة أذونات، عليك إدراج الأذونات التي تستخدمها صراحةً وسبب استخدامها. على سبيل المثال، إذا كنت تستخدم الموقع الجغرافي التقريبي فقط، عليك إعلام المستخدم بذلك في وصف تطبيقك أو في مقالات المساعدة حول تطبيقك.
في ظل ظروف معيّنة، من المفيد أيضًا إعلام المستخدمين بالوصول إلى البيانات الحسّاسة في الوقت الفعلي. على سبيل المثال، إذا كنت تصل إلى الكاميرا أو الميكروفون، ننصحك بإعلام المستخدم بذلك من خلال استخدام رمز إشعار في مكان ما في تطبيقك أو في لوحة الإشعارات (إذا كان التطبيق يعمل في الخلفية)، حتى لا يبدو أنّك تجمع البيانات سرًا.
إذا كنت بحاجة إلى طلب إذن لتشغيل ميزة معيّنة، ولكن السبب غير واضح للمستخدم، ابحث عن طريقة لتوضيح سبب حاجتك إلى أذونات الوصول إلى المعلومات الحساسة.
إذا عرضت الطريقة ContextCompat.checkSelfPermission() القيمة PERMISSION_DENIED،
يجب استدعاء shouldShowRequestPermissionRationale(). إذا عرضت هذه الطريقة القيمة
true، اعرض واجهة مستخدم تعليمية للمستخدم. في واجهة المستخدم هذه، وضِّح سبب احتياج الميزة التي يريد المستخدم تفعيلها إلى إذن معيّن.
بالإضافة إلى ذلك، إذا كان تطبيقك يطلب إذنًا متعلقًا بالموقع الجغرافي أو الميكروفون أو الكاميرا، ننصحك بتوضيح سبب حاجة تطبيقك إلى الوصول إلى هذه المعلومات.
طلب الحصول على الأذونات
بعد أن يطّلع المستخدم على واجهة مستخدم تعليمية، أو إذا كانت القيمة المعروضة من
shouldShowRequestPermissionRationale() تشير إلى أنّك لست بحاجة إلى عرض
واجهة مستخدم تعليمية، اطلب الإذن. يظهر للمستخدمين مربّع حوار أذونات النظام، حيث يمكنهم اختيار منح إذن معيّن لتطبيقك.
لإجراء ذلك، استخدِم عقد RequestPermission المضمَّن في مكتبة AndroidX، حيث تسمح للنظام بإدارة رمز طلب الحصول على الإذن نيابةً عنك. بما أنّ استخدام عقد RequestPermission يبسّط المنطق،
فهو الحلّ المقترَح عندما يكون ذلك ممكنًا. ومع ذلك، يمكنك أيضًا إذا لزم الأمر
إدارة رمز الطلب بنفسك كجزء من طلب الحصول على الإذن
وتضمين رمز الطلب هذا في منطق معاودة الاتصال الخاص بالإذن.
السماح للنظام بإدارة رمز طلب الحصول على الإذن
للسماح للنظام بإدارة رمز الطلب المرتبط بطلب الحصول على إذن، أضِف تبعيات على المكتبات التالية في ملف build.gradle الخاص بالوحدة:
androidx.activity، الإصدار 1.2.0 أو إصدار أحدثandroidx.fragment، الإصدار 1.3.0 أو إصدار أحدث
يمكنك بعد ذلك استخدام إحدى الفئات التالية:
- لطلب إذن واحد، استخدِم
RequestPermission. - لطلب أذونات متعددة في الوقت نفسه، استخدِم
RequestMultiplePermissions.
توضّح الخطوات التالية كيفية استخدام عقد RequestPermission. وتكون العملية مماثلة تقريبًا لعقد RequestMultiplePermissions.
في منطق الإعداد الخاص بالنشاط أو الجزء، أدخِل تنفيذًا لـ
ActivityResultCallbackفي طلب إلىregisterForActivityResult(). يحدّد الإذنActivityResultCallbackكيفية تعامل تطبيقك مع استجابة المستخدم لطلب الحصول على الإذن.احتفِظ بمرجع لقيمة الإرجاع لـ
registerForActivityResult()، وهي من النوعActivityResultLauncher.لعرض مربّع حوار أذونات النظام عند الضرورة، يمكنك استدعاء الطريقة
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().
يوضّح مقتطف الرمز التالي كيفية طلب إذن باستخدام رمز طلب:
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(). The
system passes in the user response to the permission dialog, as well as the
request code that you defined, as shown in the following code snippet:
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. } }
طلب أذونات تحديد الموقع الجغرافي
عند طلب أذونات تحديد الموقع الجغرافي، اتّبِع أفضل الممارسات نفسها المتّبعة مع أي إذن تشغيل آخر. يتمثّل أحد الاختلافات المهمة في ما يتعلق بأذونات تحديد الموقع الجغرافي في أنّ النظام يتضمّن أذونات متعددة متعلقة بالموقع الجغرافي. تعتمد الأذونات التي تطلبها وكيفية طلبها على متطلبات الموقع الجغرافي لحالة استخدام تطبيقك.
رصد الموقع الجغرافي في المقدّمة
إذا كان تطبيقك يتضمّن ميزة تشارك معلومات عن الموقع الجغرافي للجهاز أو تتلقّاها لمرة واحدة فقط أو لفترة زمنية محدّدة، فإنّ هذه الميزة تتطلّب الوصول إلى الموقع الجغرافي في المقدّمة. في ما يلي بعض الأمثلة:
- ضمن تطبيق التنقّل، تتيح ميزة للمستخدمين الحصول على اتجاهات مفصّلة.
- ضمن تطبيق مراسلة، تتيح ميزة للمستخدمين مشاركة موقعهم الجغرافي الحالي مع مستخدم آخر.
يعتبر النظام أنّ تطبيقك يستخدم الموقع الجغرافي في المقدّمة إذا كانت إحدى ميزات تطبيقك تصل إلى الموقع الجغرافي الحالي للجهاز في إحدى الحالات التالية:
- يظهر نشاط ينتمي إلى تطبيقك.
يُشغِّل تطبيقك خدمة تعمل في المقدّمة. عندما تكون الخدمة التي تعمل في المقدّمة قيد التشغيل، ينبّه النظام المستخدم من خلال عرض إشعار دائم. يحتفظ تطبيقك بإمكانية الوصول إلى الموقع الجغرافي عندما يكون في الخلفية، مثلاً عندما يضغط المستخدم على زر الشاشة الرئيسية على جهازه أو يطفئ شاشة جهازه.
على الإصدار 10 من نظام التشغيل Android (المستوى 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>
التعامل مع رفض الإذن
إذا رفض المستخدم طلب الحصول على إذن، يجب أن يساعده تطبيقك في فهم الآثار المترتبة على رفض الإذن. وعلى وجه الخصوص، يجب أن يُعلم تطبيقك المستخدمين بالميزات التي لا تعمل بسبب عدم توفّر الإذن. عند إجراء ذلك، يُرجى مراعاة أفضل الممارسات التالية:
- الحدّ من فقدان الوظائف: يجب أن يتمكّن المستخدمون من الوصول إلى التطبيق إلى أقصى حد ممكن بدون الأذونات المطلوبة. إذا كانت الوظيفة تعمل إلى حدّ ما على الأقل مع البيانات المتاحة، حتى إذا كانت أقل كفاءة مقارنةً بما كان يمكن أن يكون متاحًا مع الإذن، فإنّ إبقاءها مفعَّلة هو الخيار الأفضل.
وجِّه انتباه المستخدم. يُرجى إبراز جزء معيّن من واجهة مستخدم تطبيقك حيث تكون الوظائف محدودة لأنّ تطبيقك لا يملك الإذن اللازم. تشمل الأمثلة على ما يمكنك فعله ما يلي:
- عرض رسالة في المكان الذي كان من المفترض أن تظهر فيه نتائج الميزة أو بياناتها
- عرض زر مختلف يحتوي على رمز خطأ ولون مختلف
أضِف معلومات دقيقة. لا تعرض رسالة عامة. بدلاً من ذلك، وضِّح الميزات غير المتاحة بسبب عدم حصول تطبيقك على الإذن اللازم.
لا تحظر واجهة المستخدم. بمعنى آخر، لا تعرض رسالة تحذير بملء الشاشة تمنع المستخدمين من مواصلة استخدام تطبيقك على الإطلاق.
قبول خيار المستخدم: على الرغم من أنّه من المقبول إبلاغ المستخدمين بكيفية تأثّر وظائف التطبيق بعدم منح الأذونات المطلوبة، يجب ألا يشعروا بالضغط لتغيير رأيهم. من المهم إعلام المستخدم بأنّه لا يمكنه الوصول إلى الميزات الكاملة عندما يكون ذلك مناسبًا (مثلاً عند محاولة استخدام جزء من التطبيق محظور بدون إذن)، ولكن الإلحاح المستمر لإعادة النظر في قراره لا يحترم اختياره.
يمكن أن يساعد اتّباع هذه الإرشادات في ضمان شعور المستخدمين بالقدرة على إدارة الوصول إلى بياناتهم الخاصة بطريقة تتوافق مع قيمهم. إنّ عدم قبول قرارات خصوصية المستخدمين الواضحة بشكل سلس يضر بالثقة والسمعة ليس فقط لتطبيقك، بل للمنظومة المتكاملة ككل.
بالإضافة إلى ذلك، إذا نقر المستخدم على "رفض" لمنح إذن معيّن أكثر من مرة خلال فترة تثبيت تطبيقك على جهاز، لن يظهر للمستخدم مربّع حوار أذونات النظام إذا طلب تطبيقك هذا الإذن مرة أخرى. يشير إجراء المستخدم إلى "عدم السؤال مجددًا"، ويُعتبر رفضًا دائمًا. من المهم جدًا أن تطلب من المستخدمين منح الأذونات فقط عندما يحتاجون إلى الوصول إلى ميزة معيّنة، وإلا قد تفقد عن غير قصد إمكانية إعادة طلب الأذونات. في بعض الحالات، قد يتم رفض الإذن تلقائيًا بدون أن يتّخذ المستخدم أي إجراء. (قد يتم منح الإذن تلقائيًا أيضًا). من المهم عدم افتراض أي شيء حول السلوك التلقائي. في كل مرة يحتاج فيها تطبيقك إلى الوصول إلى وظيفة تتطلّب إذنًا، تأكَّد من أنّ تطبيقك لا يزال يملك هذا الإذن. لتقديم أفضل تجربة للمستخدم عند طلب أذونات التطبيق، يُرجى أيضًا الاطّلاع على أفضل الممارسات المتعلّقة بأذونات التطبيق.
فحص حالة الرفض عند الاختبار وتصحيح الأخطاء
لتحديد ما إذا كان قد تم رفض أذونات تطبيق بشكل دائم (لأغراض تصحيح الأخطاء والاختبار)، استخدِم الأمر التالي:
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، يُرجى الانتقال إلى صفحة مرجع واجهة برمجة التطبيقات للأذونات.
الأذونات لمرة واحدة
بدءًا من الإصدار 11 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 30)، عندما يطلب تطبيقك إذنًا يتعلّق بالموقع الجغرافي أو الميكروفون أو الكاميرا، يحتوي مربّع حوار الأذونات الموجَّه للمستخدمين على خيار باسم هذه المرة فقط، كما هو موضّح في الشكل 2. إذا اختار المستخدم هذا الخيار في مربّع الحوار، سيتم منح تطبيقك إذنًا مؤقتًا لمرة واحدة.
ويمكن لتطبيقك بعد ذلك الوصول إلى البيانات ذات الصلة لفترة زمنية تعتمد على سلوك تطبيقك وإجراءات المستخدم:
- ويمكن لتطبيقك الوصول إلى البيانات عندما يكون نشاطه مرئيًا.
- إذا أرسل المستخدم تطبيقك إلى الخلفية، يمكن لتطبيقك مواصلة الوصول إلى البيانات لفترة قصيرة.
- إذا أطلقت خدمة تعمل في المقدّمة أثناء ظهور النشاط، ثم نقل المستخدم تطبيقك إلى الخلفية، سيظل بإمكان تطبيقك الوصول إلى البيانات إلى أن تتوقف الخدمة التي تعمل في المقدّمة.
إنهاء عملية التطبيق عند إبطال الإذن
إذا ألغى المستخدم الإذن لمرة واحدة، مثلاً في إعدادات النظام، لن يتمكّن تطبيقك من الوصول إلى البيانات، بغض النظر عمّا إذا كنت قد أطلقت خدمة تعمل في المقدّمة. كما هو الحال مع أي إذن، إذا ألغى المستخدم الإذن لمرة واحدة الخاص بتطبيقك، ستنتهي عملية تطبيقك.
عندما يفتح المستخدم تطبيقك في المرة التالية وتطلب إحدى الميزات في تطبيقك الوصول إلى الموقع الجغرافي أو الميكروفون أو الكاميرا، سيُطلب من المستخدم منح الإذن مرة أخرى.
إعادة ضبط الأذونات غير المستخدَمة
يوفّر Android عدة طرق لإعادة ضبط أذونات التشغيل غير المستخدَمة على حالتها التلقائية، وهي حالة الرفض:
- واجهة برمجة تطبيقات يمكنك من خلالها إزالة إذن وصول تطبيقك إلى إذن تشغيل غير مستخدَم بشكل استباقي.
- آلية نظام تعمل تلقائيًا على إعادة ضبط أذونات التطبيقات غير المستخدَمة
إزالة إمكانية وصول التطبيقات إلى حسابك
في الإصدار 13 من نظام التشغيل Android (المستوى 33 لواجهة برمجة التطبيقات) والإصدارات الأحدث، يمكنك إزالة إمكانية وصول تطبيقك إلى أذونات التشغيل التي لم يعُد تطبيقك بحاجة إليها. عند تحديث تطبيقك، يجب تنفيذ هذه الخطوة لكي يفهم المستخدمون سبب استمرار تطبيقك في طلب أذونات معيّنة. وتساعد هذه المعرفة في بناء ثقة المستخدمين في تطبيقك.
لإزالة إذن التشغيل، أدخِل اسم هذا الإذن في
revokeSelfPermissionOnKill(). لإزالة إمكانية الوصول إلى مجموعة من أذونات التشغيل في الوقت نفسه، عليك تمرير مجموعة من أسماء الأذونات إلى revokeSelfPermissionsOnKill(). تتم عملية إزالة الأذونات بشكل غير متزامن وتؤدي إلى إيقاف جميع العمليات المرتبطة بمعرّف UID الخاص بتطبيقك.
لكي يزيل النظام إمكانية وصول تطبيقك إلى الأذونات، يجب إنهاء جميع العمليات المرتبطة بتطبيقك. عند استدعاء واجهة برمجة التطبيقات، يحدّد النظام الوقت المناسب لإنهاء هذه العمليات. عادةً ما ينتظر النظام حتى يقضي تطبيقك فترة طويلة في الخلفية بدلاً من المقدّمة.
لإبلاغ المستخدم بأنّ تطبيقك لم يعُد يتطلّب الوصول إلى أذونات تشغيل معيّنة، يمكنك عرض مربّع حوار في المرة التالية التي يشغّل فيها المستخدم تطبيقك. يمكن أن يتضمّن مربّع الحوار هذا قائمة بالأذونات.
إعادة ضبط أذونات التطبيقات غير المستخدَمة تلقائيًا
إذا كان تطبيقك يستهدف الإصدار 11 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 30) أو الإصدارات الأحدث ولم يتم استخدامه لبضعة أشهر، سيحمي النظام بيانات المستخدم من خلال إعادة ضبط أذونات التشغيل الحساسة التي منحها المستخدم لتطبيقك تلقائيًا. يمكنك الاطّلاع على مزيد من المعلومات في الدليل حول إسبات التطبيق.
طلب أن يصبح التطبيق المعالِج التلقائي إذا لزم الأمر
تعتمد بعض التطبيقات على الوصول إلى معلومات المستخدمين الحسّاسة ذات الصلة بسجلّات المكالمات ورسائل SMS. إذا أردت طلب الأذونات الخاصة بسجلّات المكالمات ورسائل SMS ونشر تطبيقك على متجر Google Play، عليك أن تطلب من المستخدم ضبط تطبيقك على أنّه المعالِج التلقائي لوظيفة أساسية في النظام قبل طلب أذونات التشغيل هذه.
لمزيد من المعلومات حول المعالِجات التلقائية، بما في ذلك إرشادات حول عرض طلب المعالِج التلقائي للمستخدمين، يُرجى الاطّلاع على الدليل حول الأذونات المستخدَمة فقط في المعالِجات التلقائية.
منح جميع أذونات التشغيل لأغراض الاختبار
لمنح جميع أذونات التشغيل تلقائيًا عند تثبيت تطبيق على محاكي أو جهاز اختبار، استخدِم الخيار -g للأمر adb shell install، كما هو موضّح في مقتطف الرمز التالي:
adb shell install -g PATH_TO_APK_FILE
مراجع إضافية
للحصول على معلومات إضافية حول الأذونات، يُرجى الاطّلاع على المقالات التالية:
لمزيد من المعلومات حول طلب الأذونات، يُرجى مراجعة نماذج الأذونات.
يمكنك أيضًا إكمال هذا الدرس التطبيقي حول الترميز الذي يوضّح أفضل ممارسات الخصوصية.