Flutter - Firebase_messaging 从 v7 迁移到 v11 - onMessage 未被调用
Flutter - Firebase_messaging migrating from v7 to v11 - onMessage not being called
我在迁移项目时需要一些帮助。
基本上这个项目现在有点老了,它 运行 差不多 3 年了,直到现在它是用 flutter 1.22.6
构建的。现在我正在尝试将其迁移到 v2.10.3
并且迁移即将完成。最后一个不工作的部分是 iOS 推送通知。
旧版本是 firebase_messaging v.7.0.3
上的 运行,并且工作正常。
升级 flutter 需要 9.0.0
或更高版本。
我已经完成了基本的代码迁移并且 Android 没问题,但是在 iOS 上我的 onMessage
处理程序从未被调用。
当应用程序处于后台时,正在传递推送并正确显示通知。但是当它在前台时,或者我会点击那个通知,应用程序进入前台,但回调没有被触发。
我在日志中看到的唯一错误是:
nw_endpoint_handler_set_adaptive_read_handler [C6.1 216.58.212.42:443 ready channel-flow (satisfied (Path is satisfied), viable, interface: en0, ipv4, dns)] unregister notification for read_timeout failed
OFC 我浏览了关于堆栈和其他地方的大部分主题,但是 none 这些解决方案对我有用。
我没有使用任何其他插件,例如 flutter_local_notifications
或类似的,这可能会导致错误。
最重要的代码片段:
扑博士
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel unknown, 2.10.3, on macOS 11.6 20G165 darwin-x64, locale
pl-PL)
[✓] Android toolchain - develop for Android devices (Android SDK version
33.0.0-rc3)
[✓] Xcode - develop for iOS and macOS (Xcode 13.2)
[✓] Chrome - develop for the web
[✓] Android Studio (version 4.2)
[✓] VS Code (version 1.67.1)
[✓] Connected device (1 available)
[✓] HTTP Host Availability
pubspec.yaml
firebase_core: 1.16.0
firebase_messaging: 11.3.0
google_ml_kit: 0.7.3
AppDelegate.swift
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?
) -> Bool {
disableCache();
FirebaseConfiguration.shared.setLoggerLevel(.min)
FirebaseApp.configure()
self.SetupPushNotification(application: application)
func SetupPushNotification(application: UIApplication) -> () {
if #available(iOS 10, *){ UNUserNotificationCenter.current().requestAuthorization(options: [.alert,.sound,.badge])
{(granted,error) in
if granted{
DispatchQueue.main.async {
application.registerForRemoteNotifications()
}
} else {
print("User Notification permission denied: \(error?.localizedDescription ?? "error")")
}
}
}
}
override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
NotificationDeviceToken.sharedInstance.setToken(token: tokenString(deviceToken))
}
override func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Failed to register for remote notifications: \(error.localizedDescription)")
}
override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
print(userInfo)
}
func tokenString(_ deviceToken:Data) -> String{
let bytes = [UInt8](deviceToken)
var token = ""
for byte in bytes{
token += String(format: "%02x",byte)
}
return token
}
main.dart
void startApp(AppConfig config) async {
// add this, and it should be the first line in main method
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
...
}
app.dart
void init(BuildContext context, AppCubit cubit,
SubscriptionManager subscriptionManager) {
await FirebaseMessaging.instance.getToken();
FirebaseMessaging.onMessage.listen((map) {
_log.debug('onMessage: ${map.data}');
final push = Push(map.data, PushType.onMessage);
_streamController.add(push);
return Future<bool>.value(true);
});
FirebaseMessaging.onMessageOpenedApp.listen((map) {
_log.debug('onMessageOpenedApp: ${map.data}');
_startAppFromPush = true;
final push = Push(map.data, PushType.onLaunch);
_streamController.add(push);
return Future<bool>.value(true);
});
}
Info.plist
...
<key>FirebaseAppDelegateProxyEnabled<key/>
<false/>
...
如有任何帮助,我们将不胜感激。
提前致谢。
看来我找到了解决方案。
我在 github flutterfire 项目中发现了一个未解决的问题。
其中一个主题与我的麻烦非常相似。
https://github.com/firebase/flutterfire/issues/4300
事实是,从 FCM 发送的每个推送都会在负载中获得名为 gcm.message_id
的附加字段。
来自 APNS 的通知不会获取此字段。
从版本 9 到现在的插件 firebase_messaging
正在验证此字段,如果推送不包含它,则不会触发回调 onMessage
和 onMessageOpenedApp
。
如果您遇到类似的问题,您有两个选择:
- 在您的 APNS 消息负载中添加缺失的字段
- 使用 firebase_messaging 插件创建您自己的分支,并在 2 个位置修改 FLTFirebaseMessagingPlugin,其中包含正确的 if 语句。
我希望这对你们中的一些人有用。我花了很多时间研究这个问题。
我在迁移项目时需要一些帮助。
基本上这个项目现在有点老了,它 运行 差不多 3 年了,直到现在它是用 flutter 1.22.6
构建的。现在我正在尝试将其迁移到 v2.10.3
并且迁移即将完成。最后一个不工作的部分是 iOS 推送通知。
旧版本是 firebase_messaging v.7.0.3
上的 运行,并且工作正常。
升级 flutter 需要 9.0.0
或更高版本。
我已经完成了基本的代码迁移并且 Android 没问题,但是在 iOS 上我的 onMessage
处理程序从未被调用。
当应用程序处于后台时,正在传递推送并正确显示通知。但是当它在前台时,或者我会点击那个通知,应用程序进入前台,但回调没有被触发。
我在日志中看到的唯一错误是:
nw_endpoint_handler_set_adaptive_read_handler [C6.1 216.58.212.42:443 ready channel-flow (satisfied (Path is satisfied), viable, interface: en0, ipv4, dns)] unregister notification for read_timeout failed
OFC 我浏览了关于堆栈和其他地方的大部分主题,但是 none 这些解决方案对我有用。
我没有使用任何其他插件,例如 flutter_local_notifications
或类似的,这可能会导致错误。
最重要的代码片段:
扑博士
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel unknown, 2.10.3, on macOS 11.6 20G165 darwin-x64, locale
pl-PL)
[✓] Android toolchain - develop for Android devices (Android SDK version
33.0.0-rc3)
[✓] Xcode - develop for iOS and macOS (Xcode 13.2)
[✓] Chrome - develop for the web
[✓] Android Studio (version 4.2)
[✓] VS Code (version 1.67.1)
[✓] Connected device (1 available)
[✓] HTTP Host Availability
pubspec.yaml
firebase_core: 1.16.0
firebase_messaging: 11.3.0
google_ml_kit: 0.7.3
AppDelegate.swift
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?
) -> Bool {
disableCache();
FirebaseConfiguration.shared.setLoggerLevel(.min)
FirebaseApp.configure()
self.SetupPushNotification(application: application)
func SetupPushNotification(application: UIApplication) -> () {
if #available(iOS 10, *){ UNUserNotificationCenter.current().requestAuthorization(options: [.alert,.sound,.badge])
{(granted,error) in
if granted{
DispatchQueue.main.async {
application.registerForRemoteNotifications()
}
} else {
print("User Notification permission denied: \(error?.localizedDescription ?? "error")")
}
}
}
}
override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
NotificationDeviceToken.sharedInstance.setToken(token: tokenString(deviceToken))
}
override func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Failed to register for remote notifications: \(error.localizedDescription)")
}
override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
print(userInfo)
}
func tokenString(_ deviceToken:Data) -> String{
let bytes = [UInt8](deviceToken)
var token = ""
for byte in bytes{
token += String(format: "%02x",byte)
}
return token
}
main.dart
void startApp(AppConfig config) async {
// add this, and it should be the first line in main method
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
...
}
app.dart
void init(BuildContext context, AppCubit cubit,
SubscriptionManager subscriptionManager) {
await FirebaseMessaging.instance.getToken();
FirebaseMessaging.onMessage.listen((map) {
_log.debug('onMessage: ${map.data}');
final push = Push(map.data, PushType.onMessage);
_streamController.add(push);
return Future<bool>.value(true);
});
FirebaseMessaging.onMessageOpenedApp.listen((map) {
_log.debug('onMessageOpenedApp: ${map.data}');
_startAppFromPush = true;
final push = Push(map.data, PushType.onLaunch);
_streamController.add(push);
return Future<bool>.value(true);
});
}
Info.plist
...
<key>FirebaseAppDelegateProxyEnabled<key/>
<false/>
...
如有任何帮助,我们将不胜感激。 提前致谢。
看来我找到了解决方案。
我在 github flutterfire 项目中发现了一个未解决的问题。 其中一个主题与我的麻烦非常相似。 https://github.com/firebase/flutterfire/issues/4300
事实是,从 FCM 发送的每个推送都会在负载中获得名为 gcm.message_id
的附加字段。
来自 APNS 的通知不会获取此字段。
从版本 9 到现在的插件 firebase_messaging
正在验证此字段,如果推送不包含它,则不会触发回调 onMessage
和 onMessageOpenedApp
。
如果您遇到类似的问题,您有两个选择:
- 在您的 APNS 消息负载中添加缺失的字段
- 使用 firebase_messaging 插件创建您自己的分支,并在 2 个位置修改 FLTFirebaseMessagingPlugin,其中包含正确的 if 语句。
我希望这对你们中的一些人有用。我花了很多时间研究这个问题。