我一直在开发一个 Flutter 应用程序,它需要支持点击通知并将您带到应用程序中的某个位置。但是,当点击通知时,它不会调用我创建的任何回调。它只是正常打开应用程序到主页。我从 Node.js 后端发送通知,并使用
firebase-admin
npm 包发送通知。
我发送这样的通知:
/**
* Trigger sending a notification
*/
const sendNotification = async ({
title,
body,
data,
notificationType,
topic,
sendTo,
mediaUrl,
}) => {
let tokens = [];
if (sendTo) {
console.log(`sending targeted notitification to: ${sendTo}`);
tokens = await getUserFCMTokens(sendTo);
}
const notification = {
data: {
...data,
notificationType: NOTIFICATION_TYPE[notificationType].toString(),
title: title,
body: body,
},
...(topic && { topic: topic }),
...(tokens.length > 0 && { tokens }),
apns: {
headers: {
'apns-priority': '5',
},
payload: {
aps: {
contentAvailable: true,
},
},
},
android: {
priority: 'high',
notification: {
click_action: 'FLUTTER_NOTIFICATION_CLICK',
priority: 'high',
sound: 'default',
},
},
};
console.log(notification);
try {
if (tokens.length > 0) {
// Send to multiple devices
const response = await admin
.messaging()
.sendEachForMulticast(notification);
console.log(
`Successfully sent message to ${response.successCount} devices`
);
if (response.failureCount > 0) {
console.log(
`Failed to send message to ${response.failureCount} devices`
);
response.responses.forEach((resp, idx) => {
if (!resp.success) {
console.log(
`Failed to send to token at index ${idx}: ${resp.error}`
);
}
});
}
} else if (topic) {
// Send to topic
const response = await admin.messaging().send(notification);
console.log('Successfully sent message:', response);
} else {
console.log('No valid recipients (tokens or topic) specified');
}
} catch (error) {
console.error('Error sending notification:', error);
}
};
打印出来的通知可能看起来像这样:
{
data: {
group: '6716a89768497667e665546c',
media: '',
message: '6716a8d868497667e66554a4',
notificationType: '3',
title: 'title goes here',
body: '@zh22: Message goes here '
},
topic: 'group_6716a89768497667e665546c',
apns: { headers: { 'apns-priority': '5' }, payload: { aps: [Object] } },
android: {
priority: 'high',
notification: {
click_action: 'FLUTTER_NOTIFICATION_CLICK',
priority: 'high',
sound: 'default'
}
}
}
然后,在客户端的
main.dart
内部,我初始化 Firebase 后台处理程序,并设置 getInitialMessage
回调以在单击通知时打开应用程序中的某个屏幕。
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
await AppData.initiate();
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print("onMessage: $message");
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print("onMessageOpenedApp: $message");
NotificationHandler.handleNotificationOnTap(message);
});
FirebaseMessaging.onBackgroundMessage(_onBackgroundMessage);
FirebaseMessaging.instance
.getInitialMessage()
.then(NotificationHandler.handleNotificationOnTap);
runApp(
ShowCaseWidget(builder: (context) {
return const MyApp();
}),
);
}
@pragma("vm:entry-point")
Future<void> _onBackgroundMessage(RemoteMessage message) async {
print("onBackgroundMessage: $message");
print("data: ${message.data}");
final NotificationRepository notificationRepository =
NotificationRepositoryImpl();
final FlutterLocalNotificationsPlugin localNotificationsPlugin =
FlutterLocalNotificationsPlugin();
// show notification
const AndroidNotificationDetails androidNotificationDetails =
AndroidNotificationDetails(
"basecamp_notifications", "Basecamp Notifications",
importance: Importance.max,
priority: Priority.high,
ticker: 'ticker');
const DarwinNotificationDetails iosNotificationDetails =
DarwinNotificationDetails(
presentAlert: true,
presentSound: true,
interruptionLevel: InterruptionLevel.active);
int notificationId = 1;
const NotificationDetails platformSpecifics = NotificationDetails(
android: androidNotificationDetails, iOS: iosNotificationDetails);
await localNotificationsPlugin.initialize(
const InitializationSettings(
android: AndroidInitializationSettings("@mipmap/ic_launcher"),
iOS: DarwinInitializationSettings(),
),
onDidReceiveNotificationResponse: (NotificationResponse details) {
if (details.payload != null) {
final data = json.decode(details.payload!);
final message = RemoteMessage(data: Map<String, String>.from(data));
NotificationHandler.handleNotificationOnTap(message);
}
},
);
final title = message.data["title"];
final body = message.data["body"];
await localNotificationsPlugin.show(
notificationId, title, body, platformSpecifics,
payload: message.data.toString());
}
@pragma('vm:entry-point')
void notificationTapBackground(NotificationResponse notificationResponse) {
print(notificationResponse);
// NotificationHandler.handleNotificationOnTap();
}
我尝试将
NotificationHandler.handleNotificationTap()
设置为本地通知插件的 onDidReceiveNotificationResponse
属性以及 FirebaseMessaging.onBackgroundHandler
的回调。当我点击物理设备上收到的通知时,两者都不会被调用。
当我从后端收到通知时,应用程序端的输出如下所示:
flutter: onBackgroundMessage: Instance of 'RemoteMessage'
flutter: data: {body: @zh22: Message goes here, message: 6716a8d868497667e66554a4, title: @title goes here, group: 6716a89768497667e665546c, notificationType: 3, media: }
flutter: remoteMessage: null
请注意,收到通知时也会打印
remoteMessage: null
,我认为这很奇怪。
最后,当我点击通知时,没有打印任何内容,让我相信
getInitialMessage
没有在正确的时间被调用,并且onMessageOpenedApp
似乎根本没有被调用。我在NotificationHandler.handleNotificationTap()
内部还有一条打印语句,在整个过程中从未打印过该语句,这让我相信该函数从未被输入过。
目前在 iOS 上运行。确保包含推送通知功能和 Xcode。
FirebaseAppDelegateProxyEnabled
设置为 NO。
为什么当我点击通知时这些回调都不起作用?
Bro try this:-
import 'dart:developer';
import 'package:firebase_messaging/firebase_messaging.dart';
Future<void> BackgroundHandler(RemoteMessage remotemessage) async {
log("Message Received ${remotemessage.notification!.title}");
}
class NotificationService {
Future<void> initialize() async {
NotificationSettings notificationSettings =
await FirebaseMessaging.instance.requestPermission();
if (notificationSettings.authorizationStatus ==
AuthorizationStatus.authorized) {
FirebaseMessaging.onBackgroundMessage(BackgroundHandler);
FirebaseMessaging.onMessage.listen((message) {
log("Message Received ${message.notification!.title.toString()}");
});
}
}
}