طلب أذونات الإشعارات
طلب أذونات الإشعارات
قبل أن يتمكن تطبيق Flutter من عرض الإشعارات الفورية، يجب عليه طلب الإذن من المستخدم صراحةً. على iOS، كان هذا الأمر مطلوباً دائماً. بدءاً من Android 13 (مستوى API 33)، أدخلت Google إذن وقت التشغيل POST_NOTIFICATIONS، مما جعل طلبات الإذن الصريحة إلزامية على أجهزة Android الحديثة أيضاً. باستخدام حزمة firebase_messaging، يمكنك التعامل مع كامل تدفق المنح/الرفض/المؤقت في واجهة برمجة تطبيقات موحدة واحدة.
لماذا تهم الأذونات على كل منصة
تتعامل المنصتان المحمولتان الرئيسيتان مع أذونات الإشعارات بطرق مختلفة جوهرياً:
- iOS: الإشعارات دائماً تطلب موافقة المستخدم. يعرض نظام التشغيل موجهاً أصلياً في المرة الأولى التي تستدعي فيها
requestPermission(). يمكن للمستخدم منح إذن كامل، أو رفضه، أو (على iOS 12+) السماح بالتسليم المؤقت — تظهر الإشعارات بصمت في مركز الإشعارات دون لافتات أو أصوات حتى يتصرف المستخدم صراحةً. - Android أقل من 13: كانت الإشعارات اختيارية الخروج. يمكن للتطبيقات إرسالها دون طلب إذن. لم يكن هناك موجه وقت تشغيل.
- Android 13+: يُطلب إذن وقت تشغيل جديد
POST_NOTIFICATIONS، مشابه للكاميرا أو الموقع. إذا لم يُمنح، تُحجب الإشعارات على مستوى النظام.
firebase_messaging تلقائياً إذن POST_NOTIFICATIONS إلى ملف AndroidManifest.xml. لا تزال بحاجة إلى استدعاء requestPermission() في Dart لتشغيل مربع حوار وقت التشغيل.قائمة AuthorizationStatus
بعد طلب الإذن أو التحقق منه، تُرجع firebase_messaging كائن NotificationSettings. حقل authorizationStatus الخاص به هو إحدى أربع قيم:
AuthorizationStatus.authorized— منح المستخدم الإذن الكامل؛ اللافتات والأصوات والشارات كلها نشطة.AuthorizationStatus.denied— رفض المستخدم الإذن صراحةً. لا يمكنك إظهار موجه النظام مرة أخرى؛ يجب توجيه المستخدم إلى الإعدادات.AuthorizationStatus.provisional— iOS 12+ فقط؛ يُسمح بالتسليم الصامت إلى مركز الإشعارات لكن لا تنبيهات تدخلية.AuthorizationStatus.notDetermined— لم يُسأل المستخدم بعد (iOS) أو الحالة غير معروفة.
طلب الإذن في وقت التشغيل
استدعِ FirebaseMessaging.instance.requestPermission() لتشغيل مربع حوار المنصة. يمكنك تخصيص أنواع تنبيهات iOS التي تطلبها عن طريق تمرير معاملات مسماة. الطريقة لا تنفذ أي شيء على Android أقل من 13 لكنها لا تزال تُرجع الحالة الحالية، لذا يبقى مسار كودك موحداً.
طلب الإذن الأساسي
import 'package:firebase_messaging/firebase_messaging.dart';
Future<void> requestNotificationPermission() async {
final FirebaseMessaging messaging = FirebaseMessaging.instance;
final NotificationSettings settings = await messaging.requestPermission(
alert: true, // عرض لافتات التنبيه
announcement: false,
badge: true, // تحديث عدد شارة أيقونة التطبيق
carPlay: false,
criticalAlert: false,
provisional: false, // اضبط على true لطلب المؤقت على iOS
sound: true, // تشغيل أصوات الإشعارات
);
switch (settings.authorizationStatus) {
case AuthorizationStatus.authorized:
print('منح المستخدم إذن الإشعارات الكامل.');
break;
case AuthorizationStatus.provisional:
print('منح المستخدم إذناً مؤقتاً (تسليم صامت على iOS).');
break;
case AuthorizationStatus.denied:
print('رفض المستخدم إذن الإشعارات.');
break;
case AuthorizationStatus.notDetermined:
print('لم يتم تحديد حالة الإذن بعد.');
break;
}
}
requestPermission() فقط بعد أن يُقرّ المستخدم مبررك.التحقق من حالة الإذن الحالية دون المطالبة
أحياناً تحتاج إلى التحقق من حالة الإذن الحالية دون إعادة تشغيل مربع حوار النظام — على سبيل المثال، لتقرير ما إذا كنت ستعرض لافتة "إعادة تفعيل الإشعارات". استخدم getNotificationSettings() لقراءة غير تدخلية للحالة الحالية.
التحقق من حالة الإذن بصمت
Future<AuthorizationStatus> checkNotificationPermissionStatus() async {
final NotificationSettings settings =
await FirebaseMessaging.instance.getNotificationSettings();
final AuthorizationStatus status = settings.authorizationStatus;
if (status == AuthorizationStatus.authorized) {
// آمن للحصول على رمز FCM والاشتراك في المواضيع
final String? token = await FirebaseMessaging.instance.getToken();
print('رمز FCM: $token');
} else if (status == AuthorizationStatus.denied) {
// توجيه المستخدم لإعادة التفعيل في إعدادات الجهاز
print('الإشعارات معطلة. حث المستخدم على فتح الإعدادات.');
}
return status;
}
التعامل مع حالة الرفض: الربط العميق بالإعدادات
بمجرد رفض المستخدم للإذن، لا يمكن إظهار مربع حوار النظام مرة أخرى. خيارك الوحيد هو توجيه المستخدم إلى إعدادات إشعارات الجهاز. استخدم حزمة app_settings (أو permission_handler) لفتح شاشة الإعدادات الصحيحة مباشرةً.
- اعرض تفسيراً واضحاً داخل التطبيق لما سيفوتهم بدون الإشعارات.
- قدم زراً يحمل تسمية "فتح الإعدادات" يرتبط مباشرةً بإعدادات إشعارات التطبيق.
- بعد العودة من الإعدادات، استدعِ
getNotificationSettings()مرة أخرى لتحديث الحالة.
طلب الإذن المؤقت على iOS
التفويض المؤقت ميزة خاصة بـ iOS تتيح وصول الإشعارات بصمت إلى مركز الإشعارات دون إظهار موجه النظام أبداً. يقلل هذا من الاحتكاك للمستخدمين لأول مرة: يرون محتوى الإشعارات الفعلي قبل تقرير ما إذا كانوا سيختارون "الاحتفاظ" أو "إيقاف" الإشعارات. لطلبه، اضبط provisional: true:
الإذن المؤقت (iOS فقط)
Future<void> requestProvisionalPermission() async {
final NotificationSettings settings =
await FirebaseMessaging.instance.requestPermission(
alert: true,
badge: true,
sound: true,
provisional: true, // iOS 12+ فقط؛ يُتجاهل بصمت على Android
);
if (settings.authorizationStatus == AuthorizationStatus.provisional) {
// تسليم إشعارات هادئة؛ سيطلب iOS من المستخدم
// الترقية إلى إذن كامل عند التفاعل مع أحدها.
print('تم منح الإذن المؤقت على iOS.');
}
}
الخلاصة
إدارة أذونات الإشعارات بشكل صحيح هي أساس نظام إشعارات فوري موثوق. استخدم requestPermission() لتشغيل مربع حوار المنصة (مطلوب على iOS دائماً، وعلى Android 13+)، وافحص AuthorizationStatus لتفريع منطقك، واستخدم getNotificationSettings() لقراءة الحالة بصمت دون مطالبة. احترم دائماً قرار المستخدم: وجّه المستخدمين الرافضين إلى الإعدادات، وفكر في الإذن المؤقت على iOS لبناء الثقة قبل طلب الموافقة الكاملة.