Last active
June 12, 2024 20:24
-
-
Save CoderNamedHendrick/d606754becad57a4238bcb0d87f5f69f to your computer and use it in GitHub Desktop.
Notification Integration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:async'; | |
import 'package:amplify_flutter/amplify_flutter.dart'; | |
import 'notification_dto.dart'; | |
import 'service.dart'; | |
Future<void> amplifyBackgroundNotificationReceivedHandler( | |
PushNotificationMessage notification) async { | |
NotificationService.backgroundNotificationReceivedHandler( | |
notification.toNotificationDto(), | |
); | |
} | |
final class AmplifyNotificationService implements NotificationService { | |
const AmplifyNotificationService([this._pushCategory]); | |
final PushNotificationsCategory? _pushCategory; | |
PushNotificationsCategory get _amplifyNotification => | |
_pushCategory ?? Amplify.Notifications.Push; | |
NotificationDto _onNotificationReceived(PushNotificationMessage message) { | |
return message.toNotificationDto(); | |
} | |
@override | |
Future<String?> get deviceToken async { | |
return await _amplifyNotification.onTokenReceived | |
.firstWhere((token) => token.isNotEmpty); | |
} | |
@override | |
Stream<NotificationDto> foregroundNotificationsHandler() async* { | |
yield* _amplifyNotification.onNotificationReceivedInForeground | |
.map(_onNotificationReceived); | |
} | |
@override | |
Stream<NotificationDto> foregroundNotificationReceivedHandler() async* { | |
yield* _amplifyNotification.onNotificationOpened | |
.map(_onNotificationReceived); | |
} | |
@override | |
Future<NotificationDto?> get launchNotification async => | |
_amplifyNotification.launchNotification?.toNotificationDto(); | |
@override | |
Future<void> requestPermission() async { | |
try { | |
final status = await _amplifyNotification.getPermissionStatus(); | |
switch (status) { | |
case PushNotificationPermissionStatus.granted: | |
case PushNotificationPermissionStatus.denied: | |
break; | |
case PushNotificationPermissionStatus.shouldRequest: | |
await _amplifyNotification.requestPermissions(); | |
case PushNotificationPermissionStatus.shouldExplainThenRequest: | |
await _amplifyNotification.requestPermissions(); | |
} | |
} catch (_) { | |
rethrow; | |
} | |
} | |
} | |
extension on PushNotificationMessage { | |
NotificationDto toNotificationDto() { | |
return NotificationDto( | |
id: hashCode, | |
title: title, | |
body: body, | |
deeplinkUrl: deeplinkUrl, | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:io'; | |
import 'package:amplify_auth_cognito/amplify_auth_cognito.dart'; | |
import 'package:amplify_flutter/amplify_flutter.dart' hide LogLevel; | |
import 'package:firebase_analytics/firebase_analytics.dart'; | |
import 'package:firebase_core/firebase_core.dart'; | |
import 'package:firebase_messaging/firebase_messaging.dart'; | |
import 'package:firebase_remote_config/firebase_remote_config.dart'; | |
import 'package:flutter/foundation.dart'; | |
import 'package:flutter/services.dart'; | |
import 'package:flutter/material.dart'; | |
import 'package:flutter_riverpod/flutter_riverpod.dart'; | |
import 'amplifyconfiguration.dart'; | |
import 'firebase_options.dart'; | |
import 'shared/services/services.dart'; | |
Future<void> main() async { | |
WidgetsFlutterBinding.ensureInitialized(); | |
await Firebase.initializeApp( | |
options: DefaultFirebaseOptions.currentPlatform, | |
); | |
await FirebaseMessaging.instance.setAutoInitEnabled(true); | |
await _configureAmplify(); | |
await LocalNotificationManager.initialise(); | |
NotificationService.initialise(const FirebaseNotificationService()); | |
await NotificationService.instance.requestPermission(); | |
FirebaseMessaging.onBackgroundMessage( | |
firebaseBackgroundNotificationReceivedHandler); | |
debugPrint = (String? message, {int? wrapWidth}) { | |
if (kDebugMode) { | |
debugPrintSynchronously(message, wrapWidth: wrapWidth); | |
} | |
}; | |
runApp(const ProviderScope(child: App())); | |
} | |
Future<void> _configureAmplify() async { | |
try { | |
final auth = AmplifyAuthCognito(); | |
notificationPlugin.onNotificationReceivedInBackground( | |
amplifyBackgroundNotificationReceivedHandler, | |
); | |
// await Amplify.addPlugins([auth]); | |
await Amplify.addPlugin(auth); | |
if (!Amplify.isConfigured) { | |
await Amplify.configure(amplifyconfig); | |
} | |
} on Exception catch (e) { | |
safePrint('An error occurred while configuring Amplify: $e'); | |
} | |
} | |
class App extends ConsumerStatefulWidget { | |
const App({super.key}); | |
@override | |
ConsumerState<App> createState() => _AppState(); | |
} | |
class _AppState extends ConsumerState<App> { | |
late final StreamSubscription<NotificationDto> | |
foregroundPushNotificationSubscription; | |
late final StreamSubscription<NotificationDto> | |
foregroundNotificationLaunchSubscription; | |
void onPushNotificationReceived(NotificationDto message) { | |
LocalNotificationManager.showNotification(message); | |
} | |
void onPushNotificationLaunched(NotificationDto message) {} | |
@override | |
void initState() { | |
super.initState(); | |
foregroundPushNotificationSubscription = NotificationService.instance | |
.foregroundNotificationsHandler() | |
.listen(onPushNotificationReceived); | |
foregroundNotificationLaunchSubscription = NotificationService.instance | |
.foregroundNotificationReceivedHandler() | |
.listen(onPushNotificationLaunched); | |
} | |
@override | |
void dispose() { | |
super.dispose(); | |
foregroundPushNotificationSubscription.cancel(); | |
foregroundNotificationLaunchSubscription.cancel(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
// code deleted to show example | |
return Container(); | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:companion/firebase_options.dart'; | |
import 'package:companion/shared/services/notification/notification.dart'; | |
import 'package:firebase_core/firebase_core.dart'; | |
import 'package:firebase_messaging/firebase_messaging.dart'; | |
Future<void> firebaseBackgroundNotificationReceivedHandler( | |
RemoteMessage message) async { | |
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); | |
NotificationService.backgroundNotificationReceivedHandler( | |
message.toNotificationDto(), | |
); | |
} | |
final class FirebaseNotificationService implements NotificationService { | |
const FirebaseNotificationService(); | |
static final _firebaseMessaging = FirebaseMessaging.instance; | |
NotificationDto _onRemoteMessageReceived(RemoteMessage message) { | |
if (message.notification == null && message.notification?.android == null) { | |
throw UnimplementedError(); | |
} | |
return message.toNotificationDto(); | |
} | |
@override | |
Future<String?> get deviceToken async => await _firebaseMessaging.getToken(); | |
@override | |
Stream<NotificationDto> foregroundNotificationReceivedHandler() async* { | |
yield* FirebaseMessaging.onMessageOpenedApp.map(_onRemoteMessageReceived); | |
} | |
@override | |
Stream<NotificationDto> foregroundNotificationsHandler() async* { | |
yield* FirebaseMessaging.onMessage.map(_onRemoteMessageReceived); | |
} | |
@override | |
Future<NotificationDto?> get launchNotification async => | |
(await _firebaseMessaging.getInitialMessage())?.toNotificationDto(); | |
@override | |
Future<void> requestPermission() async { | |
try { | |
await _firebaseMessaging.requestPermission( | |
alert: true, | |
announcement: false, | |
badge: true, | |
carPlay: false, | |
criticalAlert: false, | |
provisional: false, | |
sound: true, | |
); | |
await _firebaseMessaging.setForegroundNotificationPresentationOptions( | |
alert: true, | |
badge: true, | |
sound: true, | |
); | |
} catch (_) { | |
rethrow; | |
} | |
} | |
} | |
extension on RemoteMessage { | |
NotificationDto toNotificationDto() { | |
return NotificationDto( | |
id: hashCode, | |
title: notification?.title, | |
body: notification?.body, | |
deeplinkUrl: notification?.android?.clickAction, | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:equatable/equatable.dart'; | |
final class NotificationDto extends Equatable { | |
final int id; | |
final String? title; | |
final String? body; | |
final String? deeplinkUrl; | |
const NotificationDto({ | |
required this.id, | |
this.title, | |
this.body, | |
this.deeplinkUrl, | |
}); | |
@override | |
List<Object?> get props => [id, title, body, deeplinkUrl]; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:async'; | |
import 'amplify_notification_service.dart'; | |
import 'notification_dto.dart'; | |
abstract interface class NotificationService { | |
const NotificationService._(); | |
static Future<void> backgroundNotificationReceivedHandler( | |
NotificationDto message) async { | |
// TODO: handle background notification | |
} | |
static NotificationService? _instance; | |
static void initialise( | |
[NotificationService service = const AmplifyNotificationService()]) { | |
_instance ??= service; | |
} | |
static NotificationService get instance { | |
if (_instance == null) { | |
throw ArgumentError( | |
'No instance has been assigned, please call the initialise method before getting the instance'); | |
} | |
return _instance!; | |
} | |
Future<void> requestPermission(); | |
Stream<NotificationDto> foregroundNotificationsHandler(); | |
Stream<NotificationDto> foregroundNotificationReceivedHandler(); | |
Future<NotificationDto?> get launchNotification; | |
Future<String?> get deviceToken; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment