Skip to content

Commit

Permalink
feat(app): Support notifications in the foreground
Browse files Browse the repository at this point in the history
Without this, we'd miss the notifications sent via FCM if the user had the app open.

note: The android part has not been tested as I don't have Android.
  • Loading branch information
klochowicz committed Aug 14, 2023
1 parent 229ab56 commit ca1edd1
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 7 deletions.
9 changes: 8 additions & 1 deletion mobile/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,14 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>

<!-- Used by flutter_local_notifications -->
<receiver android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
</intent-filter>
</receiver>
<receiver android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" />
<!-- Used by social_share package -->
<provider
android:name="androidx.core.content.FileProvider"
Expand Down
6 changes: 6 additions & 0 deletions mobile/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ PODS:
- GoogleUtilities/UserDefaults (~> 7.8)
- nanopb (< 2.30910.0, >= 2.30908.0)
- Flutter (1.0.0)
- flutter_local_notifications (0.0.1):
- Flutter
- flutter_native_splash (0.0.1):
- Flutter
- GoogleDataTransport (9.2.5):
Expand Down Expand Up @@ -78,6 +80,7 @@ DEPENDENCIES:
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
- Flutter (from `Flutter`)
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
Expand All @@ -104,6 +107,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/firebase_messaging/ios"
Flutter:
:path: Flutter
flutter_local_notifications:
:path: ".symlinks/plugins/flutter_local_notifications/ios"
flutter_native_splash:
:path: ".symlinks/plugins/flutter_native_splash/ios"
package_info_plus:
Expand All @@ -126,6 +131,7 @@ SPEC CHECKSUMS:
FirebaseInstallations: b28af1b9f997f1a799efe818c94695a3728c352f
FirebaseMessaging: bb2c4f6422a753038fe137d90ae7c1af57251316
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
GoogleDataTransport: 54dee9d48d14580407f8f5fbf2f496e92437a2f2
GoogleUtilities: 13e2c67ede716b8741c7989e26893d151b2b2084
Expand Down
14 changes: 14 additions & 0 deletions mobile/ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,21 @@ import Flutter
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
print("dummy_value=\(dummy_method_to_enforce_bundling())");

// Set the delegate for the UNUserNotificationCenter
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self
}

GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

// Implement the method to handle the display of notifications in the foreground
@available(iOS 10.0, *)
override func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.sound, .alert, .badge])
}
}
74 changes: 68 additions & 6 deletions mobile/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import 'dart:convert';

import 'package:f_logs/f_logs.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter/material.dart';
import 'package:get_10101/firebase_options.dart';
import 'dart:io';
Expand Down Expand Up @@ -236,6 +236,11 @@ class _TenTenOneAppState extends State<TenTenOneApp> {
init(config);

WidgetsBinding.instance.addPostFrameCallback((_) async {
await initFirebase();
await requestNotificationPermission();
final flutterLocalNotificationsPlugin = initLocalNotifications();
await configureFirebase(flutterLocalNotificationsPlugin);

PackageInfo packageInfo = await PackageInfo.fromPlatform();

final messenger = scaffoldMessengerKey.currentState!;
Expand Down Expand Up @@ -503,19 +508,42 @@ Future<void> runBackend(bridge.Config config) async {

FLog.info(text: "App data will be stored in: $appDir");
FLog.info(text: "Seed data will be stored in: $seedDir");

await initFirebase();
await requestNotificationPermission();

await startBackend(config: config, appDir: appDir, seedDir: seedDir);
}

FlutterLocalNotificationsPlugin initLocalNotifications() {
final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
const androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher');
const darwinSettings = DarwinInitializationSettings();
const initializationSettings =
InitializationSettings(android: androidSettings, macOS: darwinSettings, iOS: darwinSettings);
flutterLocalNotificationsPlugin.initialize(initializationSettings);
return flutterLocalNotificationsPlugin;
}

Future<void> initFirebase() async {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
}

Future<void> configureFirebase(FlutterLocalNotificationsPlugin localNotifications) async {
// Configure message handler
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
// TODO: Handle messages from Firebase
FLog.debug(text: "Firebase message received: ${message.data}");

if (message.notification != null) {
FLog.debug(text: "Message also contained a notification: ${message.notification}");
showNotification(message.notification!.toMap(), localNotifications);
}
});

FirebaseMessaging messaging = FirebaseMessaging.instance;
// Subscribe to topic "all" to receive all messages
messaging.subscribeToTopic('all');
}

/// Ask the user for permission to send notifications via Firebase
Future<void> requestNotificationPermission() async {
FirebaseMessaging messaging = FirebaseMessaging.instance;
Expand Down Expand Up @@ -548,9 +576,43 @@ Future<void> startBackend({config, appDir, seedDir}) async {
if (i < retries - 1) {
await Future.delayed(const Duration(seconds: 5));
} else {
FLog.info(text: "Max retries reached, backend could not start.");
FLog.error(text: "Max retries reached, backend could not start.");
exit(-1);
}
}
}
}

/// Display notification inside the `message` using the local notification plugin
void showNotification(
Map<String, dynamic> message, FlutterLocalNotificationsPlugin localNotifications) async {
const androidPlatformChannelSpecifics = AndroidNotificationDetails(
'channel_id',
'channel_name',
channelDescription: 'channel_description',
importance: Importance.max,
priority: Priority.high,
);

const darwinPlatformChannelSpecifics = DarwinNotificationDetails(
presentAlert: true,
presentBadge: true,
presentSound: true,
);

const platformChannelSpecifics = NotificationDetails(
android: androidPlatformChannelSpecifics,
iOS: darwinPlatformChannelSpecifics,
macOS: darwinPlatformChannelSpecifics,
);

FLog.debug(text: "Showing notification: ${message['title']} with body ${message['body']}");

await localNotifications.show(
0,
message['title'],
message['body'],
platformChannelSpecifics,
payload: 'item x',
);
}
2 changes: 2 additions & 0 deletions mobile/macos/Flutter/GeneratedPluginRegistrant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Foundation

import firebase_core
import firebase_messaging
import flutter_local_notifications
import package_info_plus
import path_provider_foundation
import share_plus
Expand All @@ -15,6 +16,7 @@ import shared_preferences_foundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
Expand Down
40 changes: 40 additions & 0 deletions mobile/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.3.2"
dbus:
dependency: transitive
description:
name: dbus
sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263"
url: "https://pub.dev"
source: hosted
version: "0.7.8"
decimal:
dependency: "direct main"
description:
Expand Down Expand Up @@ -390,6 +398,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.2"
flutter_local_notifications:
dependency: "direct main"
description:
name: flutter_local_notifications
sha256: "3cc40fe8c50ab8383f3e053a499f00f975636622ecdc8e20a77418ece3b1e975"
url: "https://pub.dev"
source: hosted
version: "15.1.0+1"
flutter_local_notifications_linux:
dependency: transitive
description:
name: flutter_local_notifications_linux
sha256: "33f741ef47b5f63cc7f78fe75eeeac7e19f171ff3c3df054d84c1e38bedb6a03"
url: "https://pub.dev"
source: hosted
version: "4.0.0+1"
flutter_local_notifications_platform_interface:
dependency: transitive
description:
name: flutter_local_notifications_platform_interface
sha256: "7cf643d6d5022f3baed0be777b0662cce5919c0a7b86e700299f22dc4ae660ef"
url: "https://pub.dev"
source: hosted
version: "7.0.0+1"
flutter_native_splash:
dependency: "direct main"
description:
Expand Down Expand Up @@ -1069,6 +1101,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.3.0"
timezone:
dependency: transitive
description:
name: timezone
sha256: "1cfd8ddc2d1cfd836bc93e67b9be88c3adaeca6f40a00ca999104c30693cdca0"
url: "https://pub.dev"
source: hosted
version: "0.9.2"
timing:
dependency: transitive
description:
Expand Down
1 change: 1 addition & 0 deletions mobile/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ dependencies:
version: ^3.0.2
firebase_core: ^2.15.0
firebase_messaging: ^14.6.5
flutter_local_notifications: ^15.1.0+1
dev_dependencies:
flutter_launcher_icons: ^0.13.1
flutter_test:
Expand Down

0 comments on commit ca1edd1

Please sign in to comment.