together_mobile/lib/notification_api.dart

217 lines
7.3 KiB
Dart
Raw Normal View History

2023-06-21 17:44:28 +08:00
import 'dart:async';
2023-09-09 16:48:47 +08:00
import 'dart:io';
2023-06-21 17:44:28 +08:00
2023-09-09 16:48:47 +08:00
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
2023-06-21 17:44:28 +08:00
import 'package:flutter/services.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
2023-09-09 16:48:47 +08:00
import 'package:flutter_timezone/flutter_timezone.dart';
2023-06-21 17:44:28 +08:00
2023-09-09 16:48:47 +08:00
import 'package:timezone/data/latest_all.dart' as tz;
import 'package:timezone/timezone.dart' as tz;
/// Before release build of app, read [Release build configuration]
/// https://pub-web.flutter-io.cn/packages/flutter_local_notifications
int id = 0;
/// Init notification plugin
2023-06-21 17:44:28 +08:00
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
/// Streams are created so that app can respond to notification-related events
/// since the plugin is initialised in the `main` function
2023-09-09 16:48:47 +08:00
/// Only be used in IOS?
final StreamController<ReceivedNotification?> didReceiveNotificationStream =
2023-06-21 17:44:28 +08:00
StreamController<ReceivedNotification>.broadcast();
final StreamController<String?> selectNotificationStream =
StreamController<String?>.broadcast();
const MethodChannel platform =
MethodChannel('dexterx.dev/flutter_local_notifications_example');
const String portName = 'notification_send_port';
2023-09-09 16:48:47 +08:00
/// Here, the first argument is the id of notification and is common to all
/// methods that would result in a notification being shown. This is typically
/// set a unique value per notification as using the same id multiple times
/// would result in a notification being updated/overwritten.
2023-06-21 17:44:28 +08:00
class ReceivedNotification {
final int id;
final String? title;
final String? body;
final String? payload;
const ReceivedNotification({
required this.id,
required this.title,
required this.body,
required this.payload,
});
}
String? selectedNotificationPayload;
2023-09-09 16:48:47 +08:00
late final NotificationAppLaunchDetails? notificationAppLaunchDetails;
2023-06-21 17:44:28 +08:00
/// A notification action which triggers a url launch event
const String urlLanunchActionId = 'id_1';
/// A notification action which triggers a App navigation event
const String navigationActionId = 'id-3';
/// Defines a iOS/MacOS notification category for text input actions.
const String darwinNotificationCategoryText = 'textCategory';
2023-09-09 16:48:47 +08:00
/// Defines a iOS/MacOS notification category for plain actions.
2023-06-21 17:44:28 +08:00
const String darwinNotificationCategoryPlain = 'plainCategory';
@pragma('vm:entry-point')
void notificationTapBackground(NotificationResponse notificationResponse) {
print('notification(${notificationResponse.id}) action tapped: '
'${notificationResponse.actionId} with'
' payload: ${notificationResponse.payload}');
if (notificationResponse.input?.isNotEmpty ?? false) {
2023-09-09 16:48:47 +08:00
print(
'notification action tapped with input: ${notificationResponse.input}');
}
}
/// Scheduling notifications now requires developers to specify a date and
/// time relative to a specific time zone.
/// This is to solve issues with daylight saving time that existed in the
/// schedule method that is now deprecated.
Future<void> _configureLocalTimeZone() async {
if (kIsWeb || Platform.isLinux) {
return;
2023-06-21 17:44:28 +08:00
}
2023-09-09 16:48:47 +08:00
tz.initializeTimeZones();
final String timeZoneName = await FlutterTimezone.getLocalTimezone();
tz.setLocalLocation(tz.getLocation(timeZoneName));
2023-06-21 17:44:28 +08:00
}
2023-09-09 16:48:47 +08:00
Future<void> initNotification() async {
WidgetsFlutterBinding.ensureInitialized();
await _configureLocalTimeZone();
// not null if platform is Linux
notificationAppLaunchDetails = !kIsWeb && Platform.isLinux
? null
// Use the getNotificationAppLaunchDetails method when the app starts
// if you need to handle when a notification triggering the launch for
// an app e.g. change the home route of the app for deep-linking.
: await flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails();
String initRouteName = 'Home';
2023-06-21 17:44:28 +08:00
2023-09-09 16:48:47 +08:00
if (notificationAppLaunchDetails?.didNotificationLaunchApp ?? false) {
// If the app was launched via notification
// (e.g. taps a notification out of the app).
// route change depends on what type message is. Such as receiving a chat
// message, this route should change to message screen, and receiving a apply
// request shuold change to apply screen
initRouteName = 'Message'; // TODO: Set the route according to message type
}
const AndroidInitializationSettings androidInitializationSettings =
AndroidInitializationSettings('app_icon');
final List<DarwinNotificationCategory> darwinNotificationCategories =
<DarwinNotificationCategory>[
DarwinNotificationCategory(
darwinNotificationCategoryText,
actions: <DarwinNotificationAction>[
DarwinNotificationAction.text(
'text_1',
'action 1',
buttonTitle: 'send',
placeholder: 'Placeholder',
),
],
),
DarwinNotificationCategory(
darwinNotificationCategoryPlain,
actions: <DarwinNotificationAction>[
DarwinNotificationAction.plain('id_1', 'Action 1'),
DarwinNotificationAction.plain(
'id_2',
'Action 2 (destructive)',
options: <DarwinNotificationActionOption>{
DarwinNotificationActionOption.destructive,
},
),
DarwinNotificationAction.plain(
navigationActionId,
'Action 3 (foreground)',
options: <DarwinNotificationActionOption>{
DarwinNotificationActionOption.foreground,
},
),
DarwinNotificationAction.plain(
'id_4',
'Action 4 (auth required)',
options: <DarwinNotificationActionOption>{
DarwinNotificationActionOption.authenticationRequired,
},
),
],
options: <DarwinNotificationCategoryOption>{
DarwinNotificationCategoryOption.hiddenPreviewShowTitle,
},
),
];
/// Note: permissions aren't requested here just to demonstrate that can be
/// done later
final DarwinInitializationSettings darwinInitializationSettings =
DarwinInitializationSettings(
requestAlertPermission: false,
requestBadgePermission: false,
requestSoundPermission: false,
onDidReceiveLocalNotification: (
int id,
String? title,
String? body,
String? payload,
) async {
didReceiveNotificationStream.add(
ReceivedNotification(
id: id,
title: title,
body: body,
payload: payload,
),
);
},
notificationCategories: darwinNotificationCategories,
);
final InitializationSettings initializationSettings = InitializationSettings(
android: androidInitializationSettings,
iOS: darwinInitializationSettings,
);
await flutterLocalNotificationsPlugin.initialize(
initializationSettings,
// This callback fire when a notification has tapped
onDidReceiveNotificationResponse: (NotificationResponse notificationRes) {
switch (notificationRes.notificationResponseType) {
case NotificationResponseType.selectedNotification:
selectNotificationStream.add(notificationRes.payload);
break;
case NotificationResponseType.selectedNotificationAction:
if (notificationRes.actionId == navigationActionId) {
selectNotificationStream.add(notificationRes.payload);
}
break;
}
},
onDidReceiveBackgroundNotificationResponse: notificationTapBackground,
);
}