I need some help in migrating my project.
Basically project is a bit old now, its running for almost 3 years and until now it was built with flutter 1.22.6
. Now i am trying to migrate it to v2.10.3
and migration is almost done. Last not working piece is iOS Push Notifications.
Old version is running on firebase_messaging v.7.0.3
and it's working just fine.
Upgrading flutter demands version 9.0.0
or higher.
I've done basic code migration and Android is OK, but on iOS my onMessage
handler is never being called.
Push is being delivered and notification is being displayed correctly when app is in background. But when its in foreground, or i will click that notification, app comes into the foreground, but callbacks are not being triggered.
The only thing i see in logs is error like:
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 i've looked through most of topics on stack and other places, but none of these solutions worked for me.
I'm not using any other plugins, such as flutter_local_notifications
or similar, which could cause faults.
Most important pieces of code:
flutter doctor
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: "x",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/>
...
Any help will be appreciated. Thanks in advance.
CodePudding user response:
Looks like I've found solutions.
I've found an issue opened in github flutterfire project. One of topics was very similar to my trouble. https://github.com/firebase/flutterfire/issues/4300
The thing is that every push sent from FCM gets additional field in payload called gcm.message_id
.
Notifications from APNS do not get this field.
Plugin firebase_messaging
starting from version 9 up to now is validating this field and if push does not contain it, callbacks onMessage
and onMessageOpenedApp
are not being triggered.
If You are facing similar trouble You have 2 options:
- add missing field in Your APNS message payload
- create Your own fork with firebase_messaging plugin and modify FLTFirebaseMessagingPlugin in 2 places, where proper if statements are located.
I hope this will be useful to some of You. I've spent a lot of time researching this issue.