أذونات AndroidManifest هي تصريحات الأذونات في ملف AndroidManifest.xml التي تحدد موارد النظام والبيانات التي يمكن للتطبيق الوصول إليها. تتطلب Android الإعلان عن كل إذن في البيان قبل استخدام واجهة API المقابلة: من الكاميرا والموقع الجغرافي إلى إرسال الرسائل القصيرة والوصول إلى جهات الاتصال. وفقًا لوثائق مطوري Android، ينقسم كل إذن إلى أحد مستويات الحماية الأربعة: normal وdangerous وsignature وspecial.
الرئيسية
أذونات AndroidManifest هي آلية الأمان في Android التي تتحكم في وصول التطبيقات إلى البيانات المحمية ووظائف النظام. يجب على كل تطبيق الإعلان عن الأذونات اللازمة في ملف AndroidManifest.xml باستخدام العنصر
مر نموذج أذونات Android بعدة مراحل من التطور. قبل Android 6.0 (API 23)، كانت جميع الأذونات تُمنح عند التثبيت — كان المستخدم يرى القائمة الكاملة ويوافق أو يرفض تثبيت التطبيق. بدءًا من Android 6.0، يتم طلب الأذونات من مستوى dangerous أثناء التشغيل (أذونات وقت التشغيل)، مما يمنح المستخدم تحكمًا أكثر مرونة.
تنقسم الأذونات إلى أربعة مستويات حماية: normal (تُمنح تلقائيًا عند التثبيت)، وdangerous (تتطلب طلبًا في وقت التشغيل)، وsignature (متاحة فقط للتطبيقات الموقعة بنفس الشهادة)، وspecial (تتطلب تفعيلًا منفصلًا في الإعدادات). كل مستوى له آلية منح وإلغاء خاصة به.
وفقًا لـ Google I/O 2024، تخطط Android 15 لتقديم أذونات أكثر تفصيلًا — سيتمكن المستخدم من منح الوصول إلى ملفات محددة فقط في مكتبة الوسائط، وليس إلى المجموعة بأكملها. وهذا يستمر في توجه Android نحو تقليل كمية البيانات المقدمة افتراضيًا.
على عكس iOS، حيث يتم طلب جميع الأذونات أثناء التشغيل (runtime)، تقسم Android الأذونات إلى أذونات وقت التثبيت (install-time) وأذونات وقت التشغيل (runtime). يتم منح المستوى normal تلقائيًا عند التثبيت دون إخطار المستخدم. يتطلب المستوى dangerous حوارًا صريحًا، كما في iOS.
فرق آخر: في Android، يتم تجميع الأذونات في مجموعات أذونات. إذا وافق المستخدم على الوصول إلى الكاميرا، يحصل التطبيق تلقائيًا على الوصول إلى الميكروفون — فهما في نفس مجموعة MICROPHONE. في iOS، يتم طلب كل إذن بشكل مستقل بغض النظر عن المجموعات.
| إصدار Android | التغيير في نموذج الأذونات |
|---|---|
| Android 1.0–5.x | جميع الأذونات تُمنح عند التثبيت |
| Android 6.0 (API 23) | تقديم أذونات وقت التشغيل للمستوى dangerous |
| Android 10 (API 29) | التخزين المقيد — وصول محدود لنظام الملفات |
| Android 11 (API 30) | إعادة تعيين تلقائي للأذونات — إعادة تعيين الأذونات غير المستخدمة |
| Android 14 (API 34) | أذونات وقت التشغيل للوصول إلى الوسائط (صور، فيديو، صوت) |
يحدد Android أربعة مستويات حماية للأذونات، لكل منها قواعد منح خاصة به. دعنا نستعرض كل مستوى بالتفصيل.
تُمنح الأذونات العادية تلقائيًا عند تثبيت التطبيق دون إخطار أو طلب من المستخدم. تغطي الوظائف منخفضة المخاطر التي لا تهدد خصوصية المستخدم: INTERNET وACCESS_NETWORK_STATE وVIBRATE وBLUETOOTH. لا يرى المستخدم حوار موافقة — يعتبر الإذن ممنوحًا بمجرد التثبيت.
لا يحتاج المطور إلى معالجة الطلب في الكود للأذونات العادية — يكفي الإعلان عنها في البيان. ومع ذلك، في Android 12+، عند التثبيت من Google Play، يرى المستخدم علامة تبويب «الأذونات» التي تسرد جميع الأذونات العادية، مما يزيد من الشفافية. وفقًا لـ Statista (2024)، يستخدم أكثر من 90% من التطبيقات في Google Play INTERNET كأكثر إذن عادي شيوعًا.
تغطي الأذونات الخطيرة الوصول إلى البيانات والوظائف التي قد تنتهك الخصوصية: الكاميرا والميكروفون والموقع الجغرافي وجهات الاتصال والرسائل القصيرة والهاتف والتقويم وأجهزة الاستشعار الجسدية. تتطلب هذه الأذونات آلية من خطوتين: الإعلان في البيان + الطلب أثناء التشغيل عبر ActivityCompat.requestPermissions().
يمكن للمستخدم رفض الإذن الخطير، ويجب على التطبيق معالجة هذا السيناريو بشكل صحيح. في Android 11+، إذا رفض المستخدم مرتين، لا تظهر الطلبات اللاحقة حوار النظام — يعيد النظام تلقائيًا DENIED. في هذه الحالة، يجب توجيه المستخدم إلى الإعدادات.
مستوى signature — يُمنح الإذن تلقائيًا إذا كان التطبيق موقعًا بنفس الشهادة مثل النظام أو تطبيق آخر حدد الإذن. يُستخدم للتطبيقات النظامية والمؤسسية. مثال: BIND_ACCESSIBILITY_SERVICE — متاح فقط لتطبيقات النظام.
مستوى special (SYSTEM_ALERT_WINDOW وWRITE_SETTINGS وREQUEST_INSTALL_PACKAGES وMANAGE_EXTERNAL_STORAGE) — يتطلب إجراءً صريحًا من المستخدم عبر إعدادات النظام. يمكن للتطبيق فتح صفحة الإعدادات باستخدام Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION). تقيّد Google Play استخدام الأذونات الخاصة وتتطلب تبريرًا في نموذج النشر.
منذ Android 6.0، تتطلب جميع الأذونات الخطيرة طلبًا أثناء التشغيل. دعنا نستعرض دورة العمل الكاملة مع أذونات وقت التشغيل في Kotlin.
قبل استدعاء API يتطلب إذنًا خطيرًا، تحقق دائمًا من الحالة الحالية عبر ContextCompat.checkSelfPermission(). إذا كانت الحالة PERMISSION_GRANTED، يمكنك استدعاء API. إذا كانت PERMISSION_DENIED، فأنت بحاجة إلى طلب الإذن عبر ActivityResultContract RequestPermission (AndroidX) أو requestPermissions() القديم.
يُوصى باستخدام ActivityResultContracts.RequestMultiplePermissions لطلب أذونات متعددة في وقت واحد. توصي Google بتجميع الأذونات ذات الصلة (مثل الكاميرا + الميكروفون لتسجيل الفيديو) في حوار واحد، حتى يرى المستخدم السياق الكامل للطلب.
import android.Manifest
import android.content.pm.PackageManager
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat
class CameraActivity : AppCompatActivity() {
private val requestPermissionLauncher =
registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
if (isGranted) {
openCamera()
} else {
explainWhyPermissionNeeded()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
checkCameraPermission()
}
private fun checkCameraPermission() {
when {
ContextCompat.checkSelfPermission(this,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED -> {
openCamera()
}
shouldShowRequestPermissionRationale(
Manifest.permission.CAMERA
) -> {
showRationale()
}
else -> {
requestPermissionLauncher.launch(
Manifest.permission.CAMERA
)
}
}
}
}
إذا رفض المستخدم مرتين، ينقل Android الطلب إلى حالة «لا تسأل مرة أبدًا». في هذه الحالة، يُرجع shouldShowRequestPermissionRationale() القيمة false، ولن يظهر حوار النظام. يجب على التطبيق توجيه المستخدم إلى إعدادات النظام عبر Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).
مهم: لا تظهر حوارًا يعرض فتح الإعدادات فورًا بعد الرفض الأول — فهذا يُنظر إليه على أنه سلوك عدواني. استخدم shouldShowRequestPermissionRationale() لتحديد ما إذا كانت هناك حاجة لشرح. توصي إرشادات Material Design بعرض شاشة تشرح قيمة الوصول، وليس مجرد زر «فتح الإعدادات».
private fun openAppSettings() {
Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts("package", packageName, null)
).also { intent ->
startActivity(intent)
}
}
private fun showPermissionSettings() {
AlertDialog.Builder(this)
.setTitle("الوصول إلى الكاميرا")
.setMessage("اسمح بالوصول إلى الكاميرا في الإعدادات، "
+ "لالتقاط صور الملف الشخصي")
.setPositiveButton("فتح الإعدادات") { _, _ ->
openAppSettings()
}
.setNegativeButton("إلغاء", null)
.show()
}
يحتوي ملف AndroidManifest.xml على العنصر
يتم الإعلان عن كل إذن بعنصر
على سبيل المثال، إذن WRITE_EXTERNAL_STORAGE غير مطلوب في Android 10+ (التخزين المقيد)، لذا حدد maxSdkVersion="28" (Android 9). هذا يمنع الأسئلة غير الضرورية من المستخدمين في الإصدارات الأحدث. يحذر Android Studio من maxSdkVersion الموصى بها عبر Lint.
<!-- AndroidManifest.xml -->
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Normal permissions (install-time) -->
<uses-permission
android:name="android.permission.INTERNET" />
<uses-permission
android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Dangerous permissions (runtime) -->
<uses-permission
android:name="android.permission.CAMERA" />
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- Legacy storage permission limited to API 28 and below -->
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<application>
<!-- ... -->
</application>
</manifest>
يشير العنصر
يُوصى بتعيين required="false" لجميع ميزات الأجهزة والتحقق من التوفر برمجيًا عبر PackageManager.hasSystemFeature(). هذا يوسع جمهور تطبيقك. الاستثناء الوحيد هو إذا كانت الميزة حاسمة لتشغيل التطبيق (تطبيق طلب سيارة أجرة بدون GPS لا معنى له).
التعامل الصحيح مع الأذونات هو جانب رئيسي لجودة تطبيق Android. دعنا نستعرض التوصيات الرئيسية والأخطاء النموذجية.
اطلب فقط الأذونات الضرورية حقًا لتشغيل التطبيق. كل إذن إضافي يقلل من معدل تحويل التثبيت ويزيد من حالات الرفض. تعرض Google Play Console عدد المستخدمين الذين رفضوا التثبيت بسبب مجموعة الأذونات. وفقًا لـ AppBrain (2024)، فإن التطبيقات التي تحتوي على 10+ أذونات خطيرة لديها تثبيتات أقل بنسبة 35%.
راجع قائمة الأذونات بانتظام. قم بإزالة غير المستخدمة، خاصة عند الانتقال إلى إصدارات Android الأحدث حيث تصبح بعض الأذونات اختيارية. على سبيل المثال، مع منتقي الصور (ActivityResultContracts.PickVisualMedia) في Android 13+، يمكن الوصول إلى مكتبة الوسائط دون الإذن الخطير READ_MEDIA_IMAGES.
قبل طلب إذن خطير، اعرض للمستخدم شاشة تشرح سبب الحاجة إلى هذا الإذن وما القيمة التي يقدمها. يوصي Material Design باستخدام ورقة سفلية أو حوار مع أيقونة ونص مختصر وزر «متابعة». يزيد الشرح من الموافقة بنسبة 20-30% مقارنة بالطلب المباشر.
تحقق من shouldShowRequestPermissionRationale() قبل استدعاء launch(). إذا كان true، اعرض الشرح. إذا كان false، فإما أن الإذن قد مُنح بالفعل أو أن المستخدم رفضه نهائيًا (لا تسأل مرة أبدًا). في الحالة الأخيرة، اعرض زر «فتح الإعدادات» بدلاً من تكرار الطلب.
اختبر جميع السيناريوهات الممكنة: منح الإذن، الرفض، الرفض الدائم، إلغاء الإذن في الإعدادات، إعادة تعيين الأذونات (إعادة التعيين التلقائي في Android 11+). يجب معالجة كل سيناريو دون تعطل أو فقدان بيانات. يوصي دليل اختبار Android باستخدام مكتبة TestPermission لأتمتة الاختبار.
انتبه بشكل خاص للسيناريو الذي يقوم فيه المستخدم بإلغاء إذن أثناء تشغيل التطبيق (تطبيق مصغر ← الإعدادات ← إلغاء). عند العودة إلى التطبيق، تحقق من جميع الأذونات في onResume(). لا تعتمد على تخزين حالة الإذن مؤقتًا — يمكن للمستخدم تغييرها في أي وقت.
الأسئلة الشائعة
نعم، إذا تضمن SDK إذنًا في بيانه، فإنه يندمج مع بيان التطبيق أثناء البناء. يمكنك إزالة إذن SDK غير الضروري باستخدام tools:node="remove" في AndroidManifest.xml.
استدعاء API بدون إذن سيؤدي إلى SecurityException، مما يسبب تعطل التطبيق. تحقق دائمًا من حالة الإذن قبل استخدام API المقابلة وتعامل مع الرفض بشكل صحيح.
في إعدادات الجهاز: الإعدادات ← التطبيقات ← [تطبيقك] ← الأذونات. لإعادة تعيين جميع الأذونات، استخدم أمر adb: adb shell pm reset-permissions.
نعم، باستخدام ActivityResultLauncher في Fragment أو Service. ومع ذلك، يتطلب حوار الطلب دائمًا سياق واجهة مستخدم Activity. بالنسبة لـ Service، يمكنك عرض Notification مع Intent يفتح Activity الطلب.
على سبيل المثال، WRITE_EXTERNAL_STORAGE غير مطلوب في Android 10+ (التخزين المقيد). بتحديد android:maxSdkVersion="28"، تستبعد الإعلان عن الإذن في الإصدارات الأحدث، مما يحسن التوافق ويقلل قائمة الأذونات المطلوبة.
الخلاصة
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا