firebase / flutterfire

🔥 A collection of Firebase plugins for Flutter apps.
https://firebase.google.com/docs/flutter/setup
BSD 3-Clause "New" or "Revised" License
8.46k stars 3.91k forks source link

[firebase_messaging] iOS 13 push notification NOT working #1041

Closed kroikie closed 3 years ago

kroikie commented 4 years ago

Push notification does not seem to work on iOS 13 device nor on my iOS 12.4.1 device on stable 1.9.1. Seems to be 2 separate issues as well.

1) in Flutter Stable 1.9.1, push notifications do not appear on my iOS 12.4.1 device, when the always worked before on older flutter versions. 2) iOS 13 device does not receive push notifications at all

Some reading available from oneSignal https://onesignal.com/blog/ios-13-introduces-4-breaking-changes-to-notifications/

I updated my device OS(personal) version to 13, cannot further test without downgrading it back to 12.4.1. and I do not have a spare iPhone available.

Thank you

Also for other users, can you please input our own issue related to the mentioned. Things such as current physical device iOS software version and flutter channel along with its version number. so we can compile a list of where in flutter and iOS(versions) things just stopped working.

Push notification is and should be very ### critical part of a persons or companies application when used right. I hope we can address the issues and come up with a solution.

BansookNam commented 4 years ago

@marinat @ninnepinne In my case, "flutter_local_notifications" plugin had a conflict with "firebase_messaging" So I had to remove it. I hope it is the same problem.

fpv999 commented 4 years ago

try adding: "content_available" : true to "notification" section of the json. In my case it helped.

SebastienMelki commented 4 years ago

Anyone found a solution for this? FCM pushes work when the iOS app is on FOREGROUND (I can log onMessage), but nothing appears on the tray when the app is in BACKGROUND or TERMINATED...

This is critical, push notifications are very important. Help is much appreciated

Thanks

jfdeveloper92 commented 4 years ago

Anyone found a solution for this? FCM pushes work when the iOS app is on FOREGROUND (I can log onMessage), but nothing appears on the tray when the app is in BACKGROUND or TERMINATED...

This is critical, push notifications are very important. Help is much appreciated

Thanks

I'm about to try the solution above removing the platform code: I know I didn't have this when I originally had mine working.

*if (@available(iOS 10.0, )) { [UNUserNotificationCenter currentNotificationCenter].delegate = (id) self; }**

jfdeveloper92 commented 4 years ago

Anyone found a solution for this? FCM pushes work when the iOS app is on FOREGROUND (I can log onMessage), but nothing appears on the tray when the app is in BACKGROUND or TERMINATED... This is critical, push notifications are very important. Help is much appreciated Thanks

I'm about to try the solution above removing the platform code: I know I didn't have this when I originally had mine working.

*if (@available(iOS 10.0, )) { [UNUserNotificationCenter currentNotificationCenter].delegate = (id) self; }__

This solution did not work for me.

fpv999 commented 4 years ago

@SebastienMelki can you show JSON content you're sending?

rignaneseleo commented 4 years ago

This is what worked with me using: firebase_messaging 6.0.9 Flutter Channel dev, v1.13.6, on Mac OS X 10.15.2 19C57 Dart version 2.8.0 (build 2.8.0-dev.0.0 c547f5d933):

AppDelegate.swift

import UIKit
import Flutter
import flutter_downloader

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

and then a static class named FirebaseNotifications:

class FirebaseNotifications {
  static FirebaseMessaging _firebaseMessaging;

  static setup(ctx) async {
    _firebaseMessaging = FirebaseMessaging();
    if (!kReleaseMode) _firebaseMessaging.subscribeToTopic('debug');
    startListener(ctx);
  }

  static getToken() async {
    return await _firebaseMessaging.getToken();
  }

  static startListener(ctx) {
    if (Platform.isIOS) getApplePermission();

    _firebaseMessaging.configure(
      onMessage: (Map<String, dynamic> message) {
        showToast("New notification");
        print('Received notification: $message');
        _notificationHandler(message, ctx);
        return;
      },
      onResume: (Map<String, dynamic> message) {
        showToast("New notification");
        print('on resume $message');
        _notificationHandler(message, ctx);
        return;
      },
      onLaunch: (Map<String, dynamic> message) {
        showToast("New notification");
        print('on launch $message');
        _notificationHandler(message, ctx);
        return;
      },
    );
  }

  static getApplePermission() {
    _firebaseMessaging.requestNotificationPermissions(
        IosNotificationSettings(sound: true, badge: true, alert: true));
    _firebaseMessaging.onIosSettingsRegistered
        .listen((IosNotificationSettings settings) {
      print("Settings registered on iOS: $settings");
    });
  }

  static _notificationHandler(Map<String, dynamic> message, ctx) async {
    String foo = getData(message, "foo");
    //read here all the fields of the map
  }

  static getData(message, String field) {
    //to fix the bug in firebase_messages
    return Platform.isIOS ? message[field] : message["data"][field];
  }
}

I call the setup in the init method of the splash screen. I turned on some settings on Xcode like they say in the README of this library.

Watch out, there is a bug when you get the data from the map called message, I fixed it with the method getData

rignaneseleo commented 4 years ago

me too, firebase_messaging 6.0.9

jfdeveloper92 commented 4 years ago

Where are you using the firebase class that you created... (FirebaseNotifications)

rignaneseleo commented 4 years ago

In my splashscreen I call the method FirebaseNotifications.setup(context) and that's it.

jfdeveloper92 commented 4 years ago

In my splashscreen I call the method FirebaseNotifications.setup(context) and that's it.

Does it work sending the messages from the firebase console?

SebastienMelki commented 4 years ago

@SebastienMelki can you show JSON content you're sending?

hey @fpv999,

This is the JSON that I'm sending { "registration_ids": [ "fwhinrEW5xU:APA91bG92YYiguC-u2bmGqvipKJAOsc-Hq0p5Ea8Jd4GKFzR-RZpz_8XUeXYlEakAfqroLpVWOMpvK4p1j9EfClBmtan29CnQ4jFC_nypbrMyDwkH5fFU7lu8tWFp_jAFOV3ujHC-RQC" ], "data": { "body": "Your new songs was just released, check out what fans are saying!", "click_action": "FLUTTER_NOTIFICATION_CLICK", "id": "1", "status": "done", "title": "Hey Nancy" } }

When my iOS app is in the foreground in receive everything perfectly on the dart side 2020-01-15 11:35:15.093058+0200 Runner[1746:507304] flutter: onMessage: {from: 1074302196996, status: done, id: 1, title: Hey Nancy, body: Your new songs was just released, check out what fans are saying!, click_action: FLUTTER_NOTIFICATION_CLICK}

But when my app goes to the background I don't receive anything :(

If it can help as soon as my app goes to the background I get this warning, could it be related?

2020-01-15 11:35:20.847051+0200 Runner[1746:507072] Can't end BackgroundTask: no background task exists with identifier 8 (0x8), or it may have already been ended. Break in UIApplicationEndBackgroundTaskError() to debug.

fpv999 commented 4 years ago

@SebastienMelki ok, in my case I'm adding "notification" section next to "data", and it works for both. Did you try to setup onBackgroundMessage handler in your code?

rignaneseleo commented 4 years ago

In my splashscreen I call the method FirebaseNotifications.setup(context) and that's it.

Does it work sending the messages from the firebase console?

Yes

rrarey02 commented 4 years ago

@jfdeveloper92 - Have you found a solution to this? It sounds like we are having the same problem. Notifications work properly when the iOS app is in the foreground, but in the background I am not receiving a notification. I've tried everything I can think of, the various suggestions in a few issue threads, and spent several hours on this. Nothing! Notifications work perfectly on both platforms for everything except iOS background.

jfdeveloper92 commented 4 years ago

@jfdeveloper92 - Have you found a solution to this? It sounds like we are having the same problem. Notifications work properly when the iOS app is in the foreground, but in the background I am not receiving a notification. I've tried everything I can think of, the various suggestions in a few issue threads, and spent several hours on this. Nothing! Notifications work perfectly on both platforms for everything except iOS background.

I just realized I didnt properly enable notifications in xcode. I missed a step. Also from reason on the apple account it was also disabled.

jfdeveloper92 commented 4 years ago

@jfdeveloper92 - Have you found a solution to this? It sounds like we are having the same problem. Notifications work properly when the iOS app is in the foreground, but in the background I am not receiving a notification. I've tried everything I can think of, the various suggestions in a few issue threads, and spent several hours on this. Nothing! Notifications work perfectly on both platforms for everything except iOS background.

IT WORKS :) After enabling notifications in the capabilities tab and the background fetch in xcode. Also had to enable notifications in the Apple dev account. Not sure how that got unchecked though.

scognito commented 4 years ago

This is what worked with me using: firebase_messaging 6.0.9 Flutter Channel dev, v1.13.6, on Mac OS X 10.15.2 19C57 Dart version 2.8.0 (build 2.8.0-dev.0.0 c547f5d933):

AppDelegate.swift

import UIKit
import Flutter
import flutter_downloader

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

and then a static class named FirebaseNotifications:

class FirebaseNotifications {
  static FirebaseMessaging _firebaseMessaging;

  static setup(ctx) async {
    _firebaseMessaging = FirebaseMessaging();
    if (!kReleaseMode) _firebaseMessaging.subscribeToTopic('debug');
    startListener(ctx);
  }

  static getToken() async {
    return await _firebaseMessaging.getToken();
  }

  static startListener(ctx) {
    if (Platform.isIOS) getApplePermission();

    _firebaseMessaging.configure(
      onMessage: (Map<String, dynamic> message) {
        showToast("New notification");
        print('Received notification: $message');
        _notificationHandler(message, ctx);
        return;
      },
      onResume: (Map<String, dynamic> message) {
        showToast("New notification");
        print('on resume $message');
        _notificationHandler(message, ctx);
        return;
      },
      onLaunch: (Map<String, dynamic> message) {
        showToast("New notification");
        print('on launch $message');
        _notificationHandler(message, ctx);
        return;
      },
    );
  }

  static getApplePermission() {
    _firebaseMessaging.requestNotificationPermissions(
        IosNotificationSettings(sound: true, badge: true, alert: true));
    _firebaseMessaging.onIosSettingsRegistered
        .listen((IosNotificationSettings settings) {
      print("Settings registered on iOS: $settings");
    });
  }

  static _notificationHandler(Map<String, dynamic> message, ctx) async {
    String foo = getData(message, "foo");
    //read here all the fields of the map
  }

  static getData(message, String field) {
    //to fix the bug in firebase_messages
    return Platform.isIOS ? message[field] : message["data"][field];
  }
}

I call the setup in the init method of the splash screen. I turned on some settings on Xcode like they say in the README of this library.

Watch out, there is a bug when you get the data from the map called message, I fixed it with the method getData

@rignaneseleo does it work when app is closed / killed?

rrarey02 commented 4 years ago

@jfdeveloper92 - Have you found a solution to this? It sounds like we are having the same problem. Notifications work properly when the iOS app is in the foreground, but in the background I am not receiving a notification. I've tried everything I can think of, the various suggestions in a few issue threads, and spent several hours on this. Nothing! Notifications work perfectly on both platforms for everything except iOS background.

IT WORKS :) After enabling notifications in the capabilities tab and the background fetch in xcode. Also had to enable notifications in the Apple dev account. Not sure how that got unchecked though.

@jfdeveloper92 - Wow. My problem almost exactly. Push notifications were not enabled in Xcode, and I had to upload the APN auth key to Firebase. Background notifications are working properly for me now. Notification payload is slightly different than before but I can handle that easily enough. It's amazing to me that 83% of the expected functionality was working perfectly without this piece. Only iOS background notifications were impacted so I thought the problem was something more localized.

rignaneseleo commented 4 years ago

@scognito yes it does

scognito commented 4 years ago

Make it working me too, I compiled a checklist for help others.

https://github.com/FirebaseExtended/flutterfire/issues/1644#issuecomment-575594219

woprandi commented 4 years ago

Apparently push notifications doesn't work on iOS Simulator, it would be nice to specify it in the doc

scognito commented 4 years ago

Apparently push notifications doesn't work on iOS Simulator, it would be nice to specify it in the doc

They do work, tested many times.

woprandi commented 4 years ago

@scognito By working, you mean you get a notification when the app is on the background ? I can't get a notification appears on a Simulator (tested iOS 12 & 13).

quangduy-luong commented 4 years ago

Push notifications shouldn't work on the Simulator, since afaik APNS doesn't support it. Of course, if the app is in the foreground, onMessage will be called, as that doesn't appear to use APNS. From my experience, if you try to send a push notification to the Simulator, it will be displayed the next time you launch your app.

Also, for compatibility reasons, I've been using version 5.1.8 of the plugin. I don't recall making any modifications to the code other than following the integration guide at the time, and I am able to receive push notifications in the foreground/background/terminated state on both iOS 13 and 12.

scognito commented 4 years ago

Push notifications shouldn't work on the Simulator, since afaik APNS doesn't support it. Of course, if the app is in the foreground, onMessage will be called, as that doesn't appear to use APNS. From my experience, if you try to send a push notification to the Simulator, it will be displayed the next time you launch your app.

I confirm this behaviour. This is the code I use to manage notification both on simulator and real device:

AlertDialog showNotification(Map<String, dynamic> message) {
    String title, content;

    if (message.containsKey("aps")) {
      title = message["aps"]["alert"]["title"];
      content = message["aps"]["alert"]["body"];
    } else {
      title = message["notification"]["title"];
      content = message["notification"]["body"];
    }

    return AlertDialog(
      title: Text(title),
      content: Text(content),
      actions: <Widget>[
        GestureDetector(
            child: MaterialButton(
          child: Text("OK"),
          onPressed: () {
            Navigator.pop(context);
          },
        ))
      ],
    );
  }
sebbyjp commented 4 years ago

So I've found a solution that may work if you've been testing push notifications from the firebase console. The problem for me was that the payload was incorrect. Test by running the following in your terminal:

DATA='{"notification": {"body": "this is a body","title": "this is a title"}, "priority": "high", "aps": {"alert": {"title": "this is a title", "body": "this is a body"}},"data": {"click_action": "FLUTTER_NOTIFICATION_CLICK", "id": "1", "status": "done"}, "to": ""}'

curl https://fcm.googleapis.com/fcm/send -H "Content-Type:application/json" -X POST -d "$DATA" -H "Authorization: key="

Note that the aps key and value are what was missing from the firebase console. I was able to receive notifications in the background, foreground, and when the app was completely closed

RIddhiIroid commented 4 years ago

Upgrade firebase_messaging to 6.0.9 the latest version fixed the issue for ios 13

renoinn commented 4 years ago

same issue in my app.

using these package:

flutter version: Flutter (Channel stable, v1.12.13+hotfix.7)

leogny commented 4 years ago

Any update on this? Push notifications for me are only working in simulator foreground. On iOS device nothing is working foreground or background.

indigothm commented 4 years ago

Doesn't work neither in background nor foregrond. Followed the instructions from the repo.

scognito commented 4 years ago

Doesn't work neither in background nor foregrond. Followed the instructions from the repo.

Follow my checklist: https://github.com/FirebaseExtended/flutterfire/issues/1644#issuecomment-575594219

fracon commented 4 years ago

Doesn't work neither in background nor foregrond. Followed the instructions from the repo.

Follow my checklist: #1644 (comment)

I followed your checklist but even though the behavior mentioned by @sunnyseeds keeps happening

indigothm commented 4 years ago

Doesn't work neither in background nor foregrond. Followed the instructions from the repo.

Follow my checklist: #1644 (comment)

Doens't work

fpv999 commented 4 years ago
{
    "data": {
        "body": "body",
        "title": "title",
        "click_action": "FLUTTER_NOTIFICATION_CLICK"
    },
    "notification": {
        "body": "body",
        "title": "title",
        "click_action": "FLUTTER_NOTIFICATION_CLICK",
        "content_available": true
    },
    "options": {
        "mutableContent": true,
        "contentAvailable": true,
        "apnsPushType": "background"
    }
}

Adding options solved the issue for me. Anyone else can confirm?

juandiago commented 4 years ago

I got everything working following this: https://github.com/FirebaseExtended/flutterfire/issues/1644#issuecomment-575594219

It didn't worked at first, had to disable Xcode "Automatically manage signing" and create the provisioning profile manually. I suspect there's something going on with the AuthKey provided by Apple and FCM, haven't tried but I'll bet using Certs instead of AuthKey can also solve lots of issues.

robertohuertasm commented 4 years ago

For those who made this work, did you manage to make it work in stable or is dev channel mandatory for this to work?

juandiago commented 4 years ago

@robertohuertasm I'm on stable, v1.12.13+hotfix.5

btw - just tested with my prev conf using Certs instead of AuthKey and everything seems to be working perfect.

robertohuertasm commented 4 years ago

Thanks @juandiago! I just made it work. I suspect I had something wrong in the dependencies. I rm -rf ~/.pub_cache and then everything started to work.

juandiago commented 4 years ago

@robertohuertasm glad to hear it - also, when I build from Xcode, nothing works(presumably bcs of the removed statement), but when I build from VSCode everything is ok.

fracon commented 4 years ago

Hey guys! I tried every single possible solution mention in this thread and others but the max I reach was getting my notifications hit onMessage callback. When the app is in the background the notifications neither even display in the notifications tray. At this time my project has a manual signing with developer and distribution provisional profile and certs created and installed and all steps mentioned by @scognito comment verified a few times. I tried to debug the project in Xcode and what I see is that when my app goes to background it kind paused or don't run the tasks it supposed to run what makes the notification neither hit to project (I don't know how it's possible) and then when my app back to foreground immediately the breakpoint is hit and all the regular flow is called. I am at least 3 days on this and for sure have no clue in what is going on in the background thing. Did anyone experience something like this? @juandiago did you do something special to run your project with success in VSCode? Thanks in advance!

brooth commented 4 years ago

Nothing from this thread could help me with this issue, only after creating my project from the ground up, using the latest flutter SDK version did the trick. Push notifications are working now 🥳

juandiago commented 4 years ago

@fracon nothing especial, regular debug session using a real device and Certs uploaded to FCM instead of AuthKey.

VictorUvarov commented 4 years ago

I got the notification to show up in the background when i started using APNs Certificates instead of an APNs Authentication Key. But none of the firebase message callbacks got called. Guess i'll switch back to the key since it never expires, but only the onMessage callback gets fired. I used the fcm console to create the notifications.

VictorUvarov commented 4 years ago

My provisioning profile was expired and once I updated it, The notification appeared in the background but the callback functions did not fire.

furaiev commented 4 years ago

I have an issue that onLaunch fired fine, but onResume didn't fire. Only removing this part helped to get working both onLaunch and onResume.

5. Add the following lines to the (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method in the AppDelegate.m/AppDelegate.swift of your iOS project.

Objective-C:

if (@available(iOS 10.0, *)) {
  [UNUserNotificationCenter currentNotificationCenter].delegate = (id<UNUserNotificationCenterDelegate>) self;
}
Swift:

if #available(iOS 10.0, *) {
  UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
}
RanaOsamaAsif commented 4 years ago

Flutter version: Flutter 1.12.13+hotfix.8 Firebase cloud messaging: firebase_messaging: 6.0.12

Removing the line if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate } from ios/Runner/AppDelegate.swift fixed the issues for me.

PS. I'm not using any local notifications package in my app only firebase messaging is being used for push notifications.

yousifAlneamy commented 4 years ago

@RanaOsamaAsif, I did that also but it doesn't feel right to remove code that is required by a package in order to work correctly. what's the purpose of this code? It seems that it receives data in the foreground when using a simulator even when the above code is there !!!!!??

In short words, is it safe to remove the if statement from the swift code?

acoutts commented 4 years ago
firebase_messaging: ^6.0.12
Flutter 1.14.6 • channel beta • https://github.com/flutter/flutter.git
Framework • revision fabeb2a16f (6 weeks ago) • 2020-01-28 07:56:51 -0800
Engine • revision c4229bfbba
Tools • Dart 2.8.0 (build 2.8.0-dev.5.0 fc3af737c7

Android seems to be working okay but I can't get iOS real device to work with anything. No handlers are called, no messages come through. Doesn't matter if it's foregrounded or backgrounded. I can't get a single thing to work on a physical iOS device.

I've tried using an xcode automatic provisioning profile and also creating my own.

I've tried with APNs certificates and with a key, no luck. I've tried various versions of firebase_messaging, didn't fix anything.

I have push notifications, background fetch, and remote notifications enabled.

I've tried with/without this snippet:

if #available(iOS 10.0, *) {
  UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
}

I've tried adding/removing this entry in Info.plist:

FirebaseAppDelegateProxyEnabled
(Boolean)
NO

The only output I can get is this log message when I minimize the app:

2020-03-11 15:52:13.832707-0400 Runner[4935:1248181] Can't end BackgroundTask: no background task exists with identifier 9 (0x9), or it may have already been ended. Break in UIApplicationEndBackgroundTaskError() to debug.

I've tried on flutter stable and beta channels. Nothing changed.

EDIT In the end I got things working as expected after starting from scratch and following things very closely again. I hope others can solve their issues as well. What definitely fixed things for me was to abandon the APNs cert approach and use a key.

EDIT2 On closer look it seems like the onMessage handler fires in iOS physical device foreground only when I run via Xcode, but not via flutter run.

EDIT3 It doesn't work at all unless I remove this snippet from AppDelegate.swift:

if #available(iOS 10.0, *) {
    UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
}

If I remove that, then if I run via Xcode then I can see onMessage handler called while in foreground. While in background, the notification shows on the phone and when I click it then onResume is fired. This is exactly the behavior we want, so this works 100%.

If I try to run using flutter run then onMessage doesn't fire, and although I see the notification come through in the background, clicking it doesn't fire onResume either. This is a bug. I just opened https://github.com/FirebaseExtended/flutterfire/issues/2158 to report this issue.

Why would it work via Xcode but not via flutter run?

Edit4 Now it's broken again after doing a flutter clean and changing flutter channels. This time I'm able to make it fire the onMessage handler while running from both flutter and Xcode, but now the background behavior is completely broken! No popup notification goes happens now (and nothing to the notification tray) contrary to what it was just doing. Now when backgrounding the app, it just shows this log output in Xcode:

2020-03-11 18:21:16.377093-0400 Runner[5454:1311155] Can't end BackgroundTask: no background task exists with identifier 7 (0x7), or it may have already been ended. Break in UIApplicationEndBackgroundTaskError() to debug.

Edit5 I restarted the phone and now it works incredibly. The background task warning still prints but now I am receiving notifications again. This is when running from Xcode and Flutter.

My AppDelegate.swift file looks like this:

import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
}

I'm using Flutter beta:

Flutter 1.14.6 • channel beta • https://github.com/flutter/flutter.git
Framework • revision fabeb2a16f (6 weeks ago) • 2020-01-28 07:56:51 -0800
Engine • revision c4229bfbba
Tools • Dart 2.8.0 (build 2.8.0-dev.5.0 fc3af737c7)

And the latest firebase messaging library:

firebase_messaging: ^6.0.12

To be honest I have no idea what the issue was. What a crazy day!

right7ctrl commented 4 years ago

it doesn't work, the same with @acoutts