1. Firebase Cloud Messaging
class PushNotificationService {
final _messaging = FirebaseMessaging.instance;
Future<void> init() async {
// Xin quyền
final settings = await _messaging.requestPermission(
alert: true,
badge: true,
sound: true,
);
if (settings.authorizationStatus == AuthorizationStatus.authorized) {
final token = await _messaging.getToken();
debugPrint('FCM Token: $token');
// Token refresh
_messaging.onTokenRefresh.listen((newToken) {
// Gửi token mới lên server
});
}
// Foreground messages
FirebaseMessaging.onMessage.listen(_handleForegroundMessage);
// Background messages
FirebaseMessaging.onBackgroundMessage(_firebaseBackgroundHandler);
// User tapped notification
FirebaseMessaging.onMessageOpenedApp.listen(_handleNotificationTap);
}
void _handleForegroundMessage(RemoteMessage message) {
// Hiển thị local notification
_showLocalNotification(
title: message.notification?.title ?? '',
body: message.notification?.body ?? '',
payload: message.data['route'] ?? '',
);
}
void _handleNotificationTap(RemoteMessage message) {
final route = message.data['route'];
if (route != null) {
// Navigate to route
}
}
}
@pragma('vm:entry-point')
Future<void> _firebaseBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
// Handle background message
}
2. Local Notifications
class LocalNotificationService {
final _plugin = FlutterLocalNotificationsPlugin();
Future<void> init() async {
const androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher');
const iosSettings = DarwinInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true,
);
await _plugin.initialize(
const InitializationSettings(android: androidSettings, iOS: iosSettings),
onDidReceiveNotificationResponse: (response) {
// Handle tap
final payload = response.payload;
if (payload != null) {
// Navigate
}
},
);
}
Future<void> show({required String title, required String body, String? payload}) async {
await _plugin.show(
DateTime.now().millisecondsSinceEpoch ~/ 1000,
title,
body,
const NotificationDetails(
android: AndroidNotificationDetails(
'default_channel',
'Default',
importance: Importance.high,
priority: Priority.high,
),
),
payload: payload,
);
}
// Scheduled notification
Future<void> schedule({
required String title,
required String body,
required DateTime scheduledDate,
}) async {
await _plugin.zonedSchedule(
DateTime.now().millisecondsSinceEpoch ~/ 1000,
title,
body,
tz.TZDateTime.from(scheduledDate, tz.local),
const NotificationDetails(
android: AndroidNotificationDetails('scheduled', 'Scheduled'),
),
androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime,
);
}
}
3. Background Tasks với WorkManager
// Setup
Workmanager().initialize(callbackDispatcher, isInDebugMode: true);
// Register periodic task
Workmanager().registerPeriodicTask(
'sync-data',
'syncDataTask',
frequency: const Duration(hours: 1),
constraints: Constraints(
networkType: NetworkType.connected,
requiresBatteryNotLow: true,
),
);
@pragma('vm:entry-point')
void callbackDispatcher() {
Workmanager().executeTask((taskName, inputData) async {
switch (taskName) {
case 'syncDataTask':
await _syncData();
return true;
default:
return false;
}
});
}
Future<void> _syncData() async {
// Sync logic — chạy trong isolate riêng
}
Bài tiếp theo: Clean Architecture cho Flutter.