قنوات الإشعارات في Android
قنوات الإشعارات في Android
ابتداءً من Android 8.0 (مستوى API 26 / Oreo)، يجب تعيين جميع الإشعارات إلى قناة إشعارات. القناة هي تجميع مسمى يسمح للمستخدمين بالتحكم في سلوك الإشعارات — مثل مستوى الأهمية والصوت والأضواء والاهتزاز — بصورة مستقلة لكل فئة من فئات الإشعارات التي يُنتجها تطبيقك. بدون قناة، يتم تجاهل الإشعارات بصمت على Android 8 وما فوق.
في Flutter، تقوم بتكوين قنوات الإشعارات من خلال حزمة flutter_local_notifications ومن خلال ملف AndroidManifest.xml لـ FCM (Firebase Cloud Messaging). إن فهم كيفية إنشاء القنوات وتكوينها وتعيينها بشكل صحيح أمر ضروري لأي تطبيق Flutter إنتاجي يستهدف Android.
لماذا تهم القنوات؟
قبل Android Oreo، كانت التطبيقات تتحكم في سلوك الإشعارات بشكل عام. الآن، يتحكم المستخدمون في السلوك لكل قناة على حدة من الإعدادات. بمجرد إنشاء قناة، لا يستطيع تطبيقك تغيير أهميتها أو صوتها — فقط المستخدم يستطيع ذلك. هذا يعني أنك يجب أن تصمم قنواتك بعناية من البداية:
- تجميع الإشعارات المترابطة (مثل "الرسائل"، "العروض الترويجية"، "تنبيهات النظام")
- تعيين مستوى الأهمية الصحيح حتى تتصرف القناة بشكل مناسب بشكل افتراضي
- اختيار إعدادات الصوت والاهتزاز التي تتناسب مع إلحاحية الإشعار
- إعطاء كل قناة اسماً وصفاً واضحَين يظهران للمستخدم
مستويات الأهمية
يتطابق تعداد Importance في flutter_local_notifications مع ثوابت أهمية NotificationManager في Android:
- max / high — يصدر صوتاً ويظهر على الشاشة كـ إشعار رأسي. استخدمه للتنبيهات العاجلة مثل المكالمات الواردة أو المنبّهات.
- defaultImportance — يصدر صوتاً ويظهر في شريط الحالة. مناسب للرسائل والتذكيرات.
- low — لا صوت ولا مقاطعة بصرية؛ يظهر بصمت في درج الإشعارات.
- min — لا صوت ولا رمز في شريط الحالة؛ يظهر فقط عند سحب الدرج للأسفل.
- none — القناة معطلة فعلياً؛ لا تُعرض الإشعارات.
إنشاء قناة باستخدام flutter_local_notifications
الطريقة الأكثر اكتمالاً لتعريف قناة في Flutter هي عند تهيئة الإضافة. تُمرر كائن AndroidNotificationChannel وتستدعي createNotificationChannel قبل عرض أي إشعارات.
تعريف القنوات وتسجيلها عند بدء تشغيل التطبيق
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
/// استدعِ هذه الدالة مرة واحدة من main() قبل runApp().
Future<void> initNotifications() async {
// 1. تعريف كل قناة
const AndroidNotificationChannel messagesChannel = AndroidNotificationChannel(
'messages_channel', // معرف القناة (فريد لكل تطبيق)
'Messages', // الاسم المرئي للمستخدم
description: 'Notifications for new chat messages.',
importance: Importance.high, // إشعار رأسي + صوت
playSound: true,
enableVibration: true,
enableLights: true,
ledColor: Color(0xFF00BCD4), // LED بلون أزرق مخضر
);
const AndroidNotificationChannel promoChannel = AndroidNotificationChannel(
'promotions_channel',
'Promotions',
description: 'Deals, offers, and promotional content.',
importance: Importance.low, // صامت، بدون إشعار رأسي
playSound: false,
enableVibration: false,
);
// 2. تسجيل كل قناة مع نظام التشغيل
final androidPlugin =
flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>();
await androidPlugin?.createNotificationChannel(messagesChannel);
await androidPlugin?.createNotificationChannel(promoChannel);
// 3. تهيئة الإضافة نفسها
const AndroidInitializationSettings androidSettings =
AndroidInitializationSettings('@mipmap/ic_launcher');
await flutterLocalNotificationsPlugin.initialize(
const InitializationSettings(android: androidSettings),
);
}
createNotificationChannel على قناة موجودة بالفعل آمن — يقوم Android ببساطة بتحديث الخصائص القابلة للتعديل (مثل الوصف) ويتجاهل محاولات تغيير الأهمية أو الصوت إذا كانت القناة موجودة بالفعل. هذا يعني أنه يمكنك استدعاؤها بأمان في كل مرة يبدأ فيها التطبيق.تعيين قناة عند عرض إشعار محلي
في كل مرة تعرض فيها إشعاراً، يجب عليك تحديد channelId في AndroidNotificationDetails. يجب أن تكون القناة قد أُنشئت مسبقاً.
عرض إشعار على قناة محددة
Future<void> showMessageNotification({
required int id,
required String senderName,
required String messageText,
}) async {
const AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
'messages_channel', // يجب أن يطابق معرف القناة الذي سجّلته
'Messages', // اسم القناة (يظهر في الإعدادات)
channelDescription: 'Notifications for new chat messages.',
importance: Importance.high,
priority: Priority.high,
ticker: 'New message',
styleInformation: BigTextStyleInformation(''),
);
await flutterLocalNotificationsPlugin.show(
id,
senderName,
messageText,
const NotificationDetails(android: androidDetails),
);
}
Future<void> showPromoNotification({
required int id,
required String title,
required String body,
}) async {
const AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
'promotions_channel',
'Promotions',
channelDescription: 'Deals, offers, and promotional content.',
importance: Importance.low,
priority: Priority.low,
);
await flutterLocalNotificationsPlugin.show(
id,
title,
body,
const NotificationDetails(android: androidDetails),
);
}
تعيين إشعارات FCM إلى قناة
بالنسبة لإشعارات الدفع عبر Firebase Cloud Messaging (FCM)، يتم تعيين القناة في مكانين:
- AndroidManifest.xml — يضبط القناة الافتراضية لجميع رسائل FCM التي لا تحدد قناة
- حمولة FCM — يتجاوز الحقل
android.notification.channel_idفي الرسالة المرسلة من الخادم القناةَ الافتراضية لتلك الإشعارية المحددة
أضف القناة الافتراضية إلى ملف AndroidManifest.xml داخل وسم <application>:
AndroidManifest.xml — القناة الافتراضية لـ FCM
<!-- ضعها داخل <application> في android/app/src/main/AndroidManifest.xml -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="messages_channel" />
الصوت المخصص وأنماط الاهتزاز
تدعم القنوات أصواتاً مخصصة (مورد صوتي خام) وأنماط اهتزاز مخصصة (Int64List من مدد بالميلي ثانية تتناوب بين إيقاف وتشغيل):
- ضع ملف الصوت (مثل
notification_sound.mp3) في المجلدandroid/app/src/main/res/raw/ - أشر إليه بكائن
RawResourceAndroidNotificationSound - تتبع أنماط الاهتزاز الصيغة: تأخير، تشغيل، إيقاف، تشغيل، إيقاف …
حذف قناة
إذا أعدت تسمية قناة أو تركتها، فاحذف القديمة للحفاظ على إعدادات الإشعارات للمستخدم نظيفة. استخدم deleteNotificationChannel(channelId). لاحظ أنه بمجرد الحذف، تبدأ القناة الجديدة بنفس المعرف من الصفر — تضيع التخصيصات السابقة للمستخدم.
ملخص
قنوات الإشعارات في Android هي طبقة تحكم إلزامية قُدِّمت في Android 8.0. في Flutter، تعرّف القنوات باستخدام AndroidNotificationChannel، وتسجّلها عبر createNotificationChannel، وتشير إلى الـ channelId الصحيح في كل AndroidNotificationDetails تنشئها. بالنسبة لـ FCM، أعلن عن القناة الافتراضية في AndroidManifest.xml وتجاوزها اختيارياً لكل رسالة في حمولة الخادم. صمّم تصنيفات قنواتك بعناية — تصبح إعدادات الأهمية والصوت خاضعة لسيطرة المستخدم لحظة إنشاء القناة.