TF-1202: Configure FCM
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:tmail_ui_user/features/base/base_bindings.dart';
|
||||
import 'package:tmail_ui_user/features/push_notification/data/datasource/firebase_datasource.dart';
|
||||
import 'package:tmail_ui_user/features/push_notification/data/datasource_impl/hive_account_datasource_impl.dart';
|
||||
import 'package:tmail_ui_user/features/push_notification/data/local/firebase_cache_manager.dart';
|
||||
import 'package:tmail_ui_user/features/push_notification/data/repository/firebase_repository_impl.dart';
|
||||
import 'package:tmail_ui_user/features/push_notification/domain/repository/firebase_repository.dart';
|
||||
import 'package:tmail_ui_user/features/push_notification/domain/usecases/delete_firebase_cache_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/push_notification/domain/usecases/get_firebase_cache_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/push_notification/domain/usecases/save_firebase_cache_interactor.dart';
|
||||
import 'package:tmail_ui_user/main/exceptions/cache_exception_thrower.dart';
|
||||
|
||||
class FireBaseBindings extends BaseBindings {
|
||||
@override
|
||||
void bindingsController() {}
|
||||
|
||||
@override
|
||||
void bindingsDataSource() {
|
||||
Get.put<FirebaseDatasource>(Get.find<HiveFirebaseDatasourceImpl>());
|
||||
}
|
||||
|
||||
@override
|
||||
void bindingsDataSourceImpl() {
|
||||
Get.put(HiveFirebaseDatasourceImpl(
|
||||
Get.find<FirebaseCacheManager>(),
|
||||
Get.find<CacheExceptionThrower>(),
|
||||
));
|
||||
}
|
||||
|
||||
@override
|
||||
void bindingsInteractor() {
|
||||
Get.put(DeleteFirebaseCacheInteractor(Get.find<FirebaseRepositoryImpl>()));
|
||||
Get.put(SaveFirebaseCacheInteractor(Get.find<FirebaseRepositoryImpl>()));
|
||||
Get.put(GetFirebaseCacheInteractor(Get.find<FirebaseRepositoryImpl>()));
|
||||
}
|
||||
|
||||
@override
|
||||
void bindingsRepository() {
|
||||
Get.put<FirebaseRepository>(Get.find<FirebaseRepositoryImpl>());
|
||||
}
|
||||
|
||||
@override
|
||||
void bindingsRepositoryImpl() {
|
||||
Get.put(FirebaseRepositoryImpl(Get.find<FirebaseDatasource>()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:model/firebase/firebase_dto.dart';
|
||||
import 'package:rxdart/rxdart.dart';
|
||||
import 'package:tmail_ui_user/features/push_notification/domain/usecases/save_firebase_cache_interactor.dart';
|
||||
import 'package:tmail_ui_user/firebase_options.dart';
|
||||
import 'notification_strings.dart';
|
||||
|
||||
final StreamController<NotificationResponse?> selectNotificationStream =
|
||||
StreamController<NotificationResponse?>.broadcast();
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
||||
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
|
||||
await NotificationService.displayPushNotification(message);
|
||||
}
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
void notificationTapBackground(NotificationResponse notificationResponse) {
|
||||
//handle action
|
||||
}
|
||||
|
||||
void onDidReceiveNotificationResponse(
|
||||
NotificationResponse details,
|
||||
) {
|
||||
selectNotificationStream.add(details);
|
||||
}
|
||||
|
||||
class NotificationService {
|
||||
factory NotificationService() => _instance;
|
||||
|
||||
NotificationService._internal();
|
||||
|
||||
static final NotificationService _instance = NotificationService._internal();
|
||||
|
||||
static get _firebaseMessaging => FirebaseMessaging.instance;
|
||||
|
||||
static get _flutterLocalNotificationsPlugin =>
|
||||
FlutterLocalNotificationsPlugin();
|
||||
|
||||
static final BehaviorSubject<NotificationResponse?>
|
||||
_notificationActionStream =
|
||||
BehaviorSubject<NotificationResponse?>.seeded(null);
|
||||
|
||||
static Stream<NotificationResponse?> get notificationActionStream =>
|
||||
_notificationActionStream.stream;
|
||||
|
||||
static Stream<String> get onTokenRefresh => _firebaseMessaging.onTokenRefresh;
|
||||
static bool _isFlutterLocalNotificationsInitialized = false;
|
||||
|
||||
static Future<void> initializeNotificationService(
|
||||
Function(NotificationResponse)? onDidReceiveNotificationResponse,
|
||||
) async {
|
||||
if (_isFlutterLocalNotificationsInitialized) return;
|
||||
final _saveFirebaseCacheInteractor = Get.find<SaveFirebaseCacheInteractor>();
|
||||
final token = await _firebaseMessaging.getToken();
|
||||
_saveFirebaseCacheInteractor.execute(FirebaseDto(token));
|
||||
await _initFirebaseMessaging();
|
||||
await _flutterLocalNotificationsPlugin.initialize(
|
||||
InitializationSettings(
|
||||
android: androidInitializationSettings,
|
||||
iOS: iosInitializationSettings,
|
||||
),
|
||||
onDidReceiveNotificationResponse: onDidReceiveNotificationResponse,
|
||||
onDidReceiveBackgroundNotificationResponse: notificationTapBackground,
|
||||
);
|
||||
await _requestPermissions();
|
||||
await _createNotificationChannels();
|
||||
_listenNotificationActionStream();
|
||||
_isFlutterLocalNotificationsInitialized = true;
|
||||
}
|
||||
|
||||
static Future<void> displayPushNotification(
|
||||
RemoteMessage notification,
|
||||
) async {
|
||||
try {
|
||||
await _flutterLocalNotificationsPlugin.show(
|
||||
createUniqueId,
|
||||
channelName,
|
||||
notification.data.toString(),
|
||||
pushNotificationDetails,
|
||||
);
|
||||
} catch (e) {
|
||||
debugPrint(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> cancelAllNotifications() async {
|
||||
await _flutterLocalNotificationsPlugin.cancelAll();
|
||||
}
|
||||
|
||||
static Future<void> _initFirebaseMessaging() async {
|
||||
FirebaseMessaging.onMessage.listen(_handleIncomingForegroundNotification);
|
||||
FirebaseMessaging.onMessageOpenedApp.listen(_handleOpenedAppNotification);
|
||||
}
|
||||
|
||||
static Future<void> _handleIncomingForegroundNotification(
|
||||
RemoteMessage remoteMessage,
|
||||
) async {
|
||||
await displayPushNotification(remoteMessage);
|
||||
}
|
||||
|
||||
static void _handleOpenedAppNotification(RemoteMessage remoteMessage) {}
|
||||
|
||||
static Future<void> _requestPermissions() async {
|
||||
if (Platform.isAndroid) {
|
||||
await _flutterLocalNotificationsPlugin
|
||||
.resolvePlatformSpecificImplementation<
|
||||
AndroidFlutterLocalNotificationsPlugin>()
|
||||
?.requestPermission();
|
||||
} else {
|
||||
await _flutterLocalNotificationsPlugin
|
||||
.resolvePlatformSpecificImplementation<
|
||||
IOSFlutterLocalNotificationsPlugin>()
|
||||
?.requestPermissions(
|
||||
alert: true,
|
||||
badge: true,
|
||||
sound: true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> _listenNotificationActionStream() async {
|
||||
selectNotificationStream.stream
|
||||
.listen((event) => event)
|
||||
.onData((data) async {
|
||||
_notificationActionStream.add(data);
|
||||
switch (data?.notificationResponseType) {
|
||||
case NotificationResponseType.selectedNotification:
|
||||
break;
|
||||
case NotificationResponseType.selectedNotificationAction:
|
||||
break;
|
||||
default:
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static Future<void> _createNotificationChannels() async {
|
||||
await _flutterLocalNotificationsPlugin
|
||||
.resolvePlatformSpecificImplementation<
|
||||
AndroidFlutterLocalNotificationsPlugin>()
|
||||
?.createNotificationChannel(androidChannel);
|
||||
}
|
||||
|
||||
static Future<void> deleteToken() async => _firebaseMessaging.deleteToken();
|
||||
}
|
||||
|
||||
int get createUniqueId =>
|
||||
DateTime.now().millisecondsSinceEpoch.remainder(100000);
|
||||
@@ -0,0 +1,54 @@
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
|
||||
const channelId = 'team_mail_channel_id';
|
||||
const channelKey = 'team_mail_channel_key';
|
||||
const channelName = 'Team Mail notifications';
|
||||
const channelDescription = 'Team Mail notifications';
|
||||
|
||||
final iosInitializationSettings = DarwinInitializationSettings(
|
||||
notificationCategories: [
|
||||
DarwinNotificationCategory(
|
||||
channelId,
|
||||
actions: <DarwinNotificationAction>[
|
||||
DarwinNotificationAction.plain(
|
||||
channelKey,
|
||||
channelName,
|
||||
options: {
|
||||
DarwinNotificationActionOption.foreground,
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
onDidReceiveLocalNotification:
|
||||
(int id, String? title, String? body, String? payload) {},
|
||||
);
|
||||
|
||||
const androidInitializationSettings =
|
||||
AndroidInitializationSettings('background');
|
||||
|
||||
const androidChannel = AndroidNotificationChannel(
|
||||
channelId,
|
||||
channelName,
|
||||
description: channelDescription,
|
||||
importance: Importance.max,
|
||||
enableLights: true,
|
||||
);
|
||||
|
||||
const pushNotificationDetails = NotificationDetails(
|
||||
android: AndroidNotificationDetails(
|
||||
channelId,
|
||||
channelName,
|
||||
channelDescription: channelDescription,
|
||||
visibility: NotificationVisibility.public,
|
||||
importance: Importance.max,
|
||||
ledOnMs: 100,
|
||||
ledOffMs: 1000,
|
||||
category: AndroidNotificationCategory.message,
|
||||
),
|
||||
iOS: DarwinNotificationDetails(
|
||||
presentSound: true,
|
||||
presentAlert: true,
|
||||
presentBadge: true,
|
||||
),
|
||||
);
|
||||
Reference in New Issue
Block a user