الإذن الخطير (Dangerous Permission) هو فئة من الأذونات في Android تتطلب موافقة صريحة من المستخدم عبر حوار وقت التشغيل أثناء عمل التطبيق. وفقاً لدليل مطوري Android، 2024، الأذونات الخطيرة لها ProtectionLevel dangerous وتوفر الوصول إلى بيانات حساسة: الكاميرا، الميكروفون، الموقع وجهات الاتصال. بدون موافقة صريحة من المستخدم، لا يمكن للتطبيق استخدام هذه الوظائف.
الملخص
الإذن الخطير هو فئة من أذونات نظام Android التي توفر الوصول إلى بيانات المستخدم الحساسة. على عكس الأذونات العادية، لا يتم منح الأذونات الخطيرة تلقائياً أثناء التثبيت — يجب على التطبيق طلبها صراحةً أثناء وقت التشغيل من خلال آلية وقت التشغيل التي تم تقديمها في Android 6.0 Marshmallow (API 23).
ترجع الحاجة إلى الطلب الصريح إلى طبيعة البيانات التي تحميها هذه الأذونات: موقع المستخدم، جهات الاتصال الشخصية، محتوى الكاميرا والميكروفون، سجل المكالمات والرسائل النصية. يعتبر Android هذه البيانات حساسة ويتطلب من المستخدم منح الوصول بوعي. وفقاً لـ Android Privacy Sandbox (2024)، يرفض المستخدمون حوالي 30 بالمائة من طلبات وقت التشغيل في المتوسط.
الميزة الرئيسية للإذن الخطير هي إمكانية إلغائه في أي وقت. يمكن للمستخدم الذهاب إلى الإعدادات — التطبيقات — الأذونات وإيقاف تشغيل أي إذن خطير. يجب أن يكون التطبيق مستعداً لإمكانية إلغاء الإذن الذي تم منحه سابقاً في أي وقت دون إعادة تشغيل.
يتم تعيين مستوى الحماية dangerous في تعريفات أذونات النظام على مستوى نظام التشغيل. عندما يعلن تطبيق عن uses-permission مع protectionLevel هذا، يقوم النظام بتعليم الإذن على أنه يتطلب طلب وقت التشغيل. على عكس normal، يتم عرض الأذونات الخطيرة دائماً في واجهة إدارة أذونات النظام ويمكن إلغاؤها.
يتم تجميع جميع الأذونات الخطيرة في مجموعات أذونات حسب الفئة الوظيفية. على سبيل المثال، CAMERA وCAMERA2 في مجموعة CAMERA، وACCESS_FINE_LOCATION وACCESS_COARSE_LOCATION في مجموعة LOCATION. إذا منح المستخدم إذناً واحداً من مجموعة، يتم منح الأذونات المتبقية في نفس المجموعة تلقائياً دون حوار إضافي.
طلب وقت التشغيل هو آلية يقوم فيها التطبيق باستدعاء API النظام لعرض حوار طلب الإذن. يرى المستخدم نافذة مشروطة تحتوي على اسم الإذن وزري السماح والرفض. بعد الرد، يستدعي النظام رد الاتصال onRequestPermissionsResult مع النتيجة.
تتضمن الدورة الكاملة ثلاث خطوات: التحقق من الحالة عبر checkSelfPermission، واستدعاء requestPermissions إذا لم يتم منح الإذن، ومعالجة النتيجة في onRequestPermissionsResult. التحقق من الحالة إلزامي لأن المستخدم قد ألغى الإذن في أي وقت من خلال الإعدادات، واستدعاء دالة دون تحقق سيؤدي إلى SecurityException.
fun checkAndRequestCameraPermission() {
when {
ContextCompat.checkSelfPermission(
this,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED -> {
openCamera()
}
else -> {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.CAMERA),
REQUEST_CAMERA_CODE
)
}
}
}
تتم معالجة النتيجة في ActivityResultLauncher أو onRequestPermissionsResult. النهج الحديث الموصى به هو استخدام ActivityResultContracts.RequestPermission، الذي يوفر API أنظف بدون رموز طلب صريحة. يعيد هذا العقد قيمة Boolean — ما إذا تم منح الإذن أم لا.
اطلب الأذونات الخطيرة بدقة في سياق استخدام الوظيفة، وليس عند بدء تشغيل التطبيق. إذا ضغط المستخدم على زر الكاميرا — اطلب CAMERA. إذا فتح خريطة — اطلب LOCATION. الطلبات السياقية تحقق ضعف عدد مرات المنح مقارنة بطلب جميع الأذونات عند الإطلاق الأول. يُوصى أيضاً بعدم طلب أكثر من إذن واحد في كل مرة حتى يفهم المستخدم أي وظيفة تتطلب الوصول.
يحدد Android عدة مجموعات من الأذونات الخطيرة، كل منها يحتوي على ثابت واحد أو أكثر. تتوفر القائمة الأكثر اكتمالاً في فئة Manifest.permission. فيما يلي المجموعات الرئيسية والأذونات المستخدمة في التطوير.
| مجموعة الأذونات | الأذونات | API الوصول |
|---|---|---|
| CAMERA | CAMERA | Camera API, CameraX |
| LOCATION | ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION | FusedLocationProvider, Geofence |
| MICROPHONE | RECORD_AUDIO | MediaRecorder, AudioRecord |
| PHONE | READ_PHONE_STATE, CALL_PHONE, READ_CALL_LOG | TelephonyManager |
| CONTACTS | READ_CONTACTS, WRITE_CONTACTS, GET_ACCOUNTS | ContactsContract |
| SMS | READ_SMS, SEND_SMS, RECEIVE_SMS | SmsManager |
| STORAGE | READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE | MediaStore, File API |
| CALENDAR | READ_CALENDAR, WRITE_CALENDAR | CalendarContract |
بدءاً من Android 12، شددت Google المتطلبات لبعض الأذونات. على سبيل المثال، أصبح BLUETOOTH_CONNECT وBLUETOOTH_SCAN خطيرين ويتطلبان طلب وقت التشغيل. كما تمت إضافة الإذن BODY_SENSORS_BACKGROUND للوصول الخلفي إلى أجهزة الاستشعار. يحتاج المطورون إلى تحديث targetSdkVersion واختبار الطلبات على إصدارات نظام التشغيل الحالية.
قدم Android 13 (API 33) أذونات جديدة للإشعارات (POST_NOTIFICATIONS) وملفات الوسائط (READ_MEDIA_IMAGES، READ_MEDIA_VIDEO، READ_MEDIA_AUDIO)، لتحل محل READ_EXTERNAL_STORAGE العام. الآن يتم طلب الوصول إلى الصور والفيديو والصوت بشكل منفصل من خلال أذونات متخصصة دون حوار واحد.
يختلف الإذن الخطير والإذن العادي اختلافاً جوهرياً في طريقة المنح وإمكانية الإلغاء وتجربة المستخدم. يُمنح العادي تلقائياً أثناء التثبيت، ويتطلب الخطير حواراً صريحاً في وقت التشغيل. لا يمكن إلغاء العادي من خلال الإعدادات، بينما يمكن تعطيل الخطير في أي وقت. هذا التباين يخلق أنماط تطوير مختلفة.
من منظور الكود، تتطلب الأذونات الخطيرة عملاً أكثر: checkSelfPermission وrequestPermissions ومعالجة الرفض. للأذونات العادية، يكفي سطر واحد في AndroidManifest.xml. ومع ذلك، فإن الإذن الخطير يمنح المستخدم التحكم، مما يزيد الثقة، خاصة للوظائف الحساسة مثل الكاميرا أو الموقع.
الاختيار بين الفئات ليس من اختصاص المطور — بل يحدده النظام. يعلن المطور فقط uses-permission، ويحدد النظام الفئة بناءً على protectionLevel. لكن استراتيجية طلب الأذونات الخطيرة تؤثر على تجربة المستخدم: الحوارات المتكررة أو غير المناسبة تقلل من تقييم التطبيق.
الطريقة الحديثة لطلب الأذونات في Kotlin هي استخدام ActivityResultContracts.RequestMultiplePermissions أو RequestPermission. هذه العقود جزء من مكتبة androidx.activity وتوفر API نظيفاً يعتمد على lambda، دون الحاجة إلى تجاوز onRequestPermissionsResult.
class CameraActivity : AppCompatActivity() {
private val requestPermissionLauncher =
registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
if (isGranted) {
openCamera()
} else {
showPermissionDeniedMessage()
}
}
fun requestCamera() {
when {
ContextCompat.checkSelfPermission(
this,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED ->
openCamera()
ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.CAMERA
) ->
showRationaleDialog()
else ->
requestPermissionLauncher.launch(
Manifest.permission.CAMERA
)
}
}
}
عندما يحتاج التطبيق إلى عدة أذونات خطيرة في وقت واحد، استخدم RequestMultiplePermissions. يعيد العقد Map<String, Boolean> حيث المفتاح هو اسم الإذن والقيمة هي النتيجة. هذا مفيد عند الإطلاق الأول عندما تحتاج إلى طلب CAMERA وRECORD_AUDIO لتسجيل الفيديو.
إذا رفض المستخدم الطلب، فإن طريقة shouldShowRequestPermissionRationale تعيد true. هذا يشير إلى ضرورة عرض شرح لسبب الحاجة إلى الإذن. أفضل ممارسة هي عرض حوار مخصص مع شرح وزر إعادة المحاولة. إذا رفض المستخدم الطلب مرة أخرى مع تحديد خانة Never Ask Again، ستعيد shouldShowRequestPermissionRationale false، وتحتاج إلى التوجيه إلى الإعدادات.
عدم السؤال مرة أخرى هو علامة يمكن للمستخدم تعيينها عند رفض حوار وقت التشغيل للمرة الثانية. بعد ذلك، لم يعد الحوار القياسي يظهر لهذا الإذن. الطريقة الوحيدة لمنح الوصول هي توجيه المستخدم إلى إعدادات النظام للتطبيقات.
يحتاج المطور إلى التمييز بين سيناريوهين للرفض: الأول، عندما تعيد shouldShowRequestPermissionRationale true (رفض المستخدم ولكن لا يزال من الممكن عرض الحوار)، والثاني، عندما تعيد الطريقة false (Never Ask Again نشط أو الإذن محظور بواسطة السياسة). في الحالة الثانية، يجب عرض زر فتح الإعدادات.
fun handlePermissionDenied(permission: String) {
if (ActivityCompat.shouldShowRequestPermissionRationale(
this, permission
)) {
showRationaleDialog(permission)
} else {
showSettingsRedirectDialog(permission)
}
}
private fun showSettingsRedirectDialog(permission: String) {
AlertDialog.Builder(this)
.setTitle("تم رفض الوصول")
.setMessage(
"تم حظر الإذن. افتح الإعدادات."
)
.setPositiveButton("الإعدادات") { _, _ ->
val intent = Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts(
"package", packageName, null
)
)
startActivity(intent)
}
.show()
}
من المهم عدم طلب الإذن مرة أخرى إذا أعادت shouldShowRequestPermissionRationale false. استدعاء متكرر لـ requestPermissions في هذه الحالة لن يعرض حواراً — ستأتي النتيجة فوراً مع DENIED دون شرح. سيواجه المستخدم سلوكاً غير واضح، مما يؤثر سلباً على تجربة استخدام التطبيق.
الأسئلة الشائعة
تشمل الأذونات الخطيرة الأذونات ذات ProtectionLevel dangerous: CAMERA وRECORD_AUDIO وACCESS_FINE_LOCATION وREAD_CONTACTS وREAD_SMS وREAD_CALENDAR وغيرها. القائمة الكاملة متاحة في فئة Manifest.permission.
استخدم ContextCompat.checkSelfPermission، مع تمرير السياق واسم الإذن. تعيد الطريقة PERMISSION_GRANTED أو PERMISSION_DENIED. يجب إجراء التحقق قبل كل استدعاء API يتطلب إذناً خطيراً.
مجموعة الأذونات تجمع الأذونات الخطيرة ذات الصلة. إذا منح المستخدم إذناً واحداً من مجموعة، يتم منح الباقي تلقائياً. على سبيل المثال، تتضمن LOCATION كلاً من ACCESS_FINE_LOCATION وACCESS_COARSE_LOCATION.
تحقق من shouldShowRequestPermissionRationale بعد الرفض. إذا أعادت الطريقة false وما زال الإذن غير ممنوح — فإن Never Ask Again نشط. وجه المستخدم إلى الإعدادات عبر Intent مع ACTION_APPLICATION_DETAILS_SETTINGS.
نعم، تظل إلزامية. على Android 13+، تغيرت بعض الأذونات: أصبح POST_NOTIFICATIONS إذن وقت تشغيل منفصل، وتم استبدال READ_EXTERNAL_STORAGE بـ READ_MEDIA_IMAGES للوصول الدقيق لملفات الوسائط.
الخلاصة
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.