Skip to content

[firebase_messaging] iOS is not receiving apns payload and not showing notification when it is in background or killed #2854

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
FernandoUFS opened this issue Jun 27, 2020 · 54 comments
Labels
impact: crowd Affects many people, though not necessarily a specific customer with an assigned label. (P2) platform: ios Issues / PRs which are specifically for iOS. plugin: messaging type: bug Something isn't working

Comments

@FernandoUFS
Copy link

Describe the bug
A couple days ago I notice that my application stopped showing notifications from firebase just on iOS. I send a POST request to https://fcm.googleapis.com/fcm/send containing the payload, when the app is on background nothing happens, when I open the app the method onMessage is executed with few fields shown below.

The notification was working from about 2 months since first implementation, it was shown when the app was in background, my payload was not changed but it stopped working.

Expected Behaviour
Show notification when app is in background or killed (as before)

My request:
image

My alternative request with same result:

{
    "notification": {
        "title": "Title test",
        "body": "Body message"
    }
    "condition": "'match_1474' in topics"
}

My code for debug:

...
_firebaseMessaging.configure(
      onBackgroundMessage: myBackgroundMessageHandler, //static method printing message (not get called)
      onMessage: (Map<String, dynamic> message) async {
        Log.d("onMessage: ${jsonEncode(message)}");
      }
      onResume: (Map<String, dynamic> message) async {
        Log.d("onResume: ${jsonEncode(message)}");
      },
      onLaunch: (Map<String, dynamic> message) async {
        Log.d("onLaunch: ${jsonEncode(message)}");
      }
);
...

The console:
This message is print only when I receive the notification with app open or when I open the app after receive with app closed.

flutter: onMessage: {"collapse_key":"4cH4++Z1SUoDiUf9+l9DKFX/sc=","from":"50068760310"}

Additional context
I use AdminSDK for PHP for real use and the payload includes android specific data, but I tested on Postman to make sure the problem is not there.

The problem is occurring on production with all users I have checked (TestFlight Beta).
On Android it is working as expected.

If I send just data the app continues receiving only when the app is on foreground.
Example

{
    "data": {
        "title": "Title test",
        "body": "Body message"
    },
    "condition": "'match_1474' in topics"
}

The expected behaviour here is to receive the message in background executing immediately onMessage when it's not killed, but this happens only when app opens.

flutter doctor -v

[✓] Flutter (Channel stable, v1.17.4, on Mac OS X 10.15.3 19D76, locale pt-BR)
    • Flutter version 1.17.4 at /Users/fernando/Apps/flutter
    • Framework revision 1ad9baa8b9 (10 days ago), 2020-06-17 14:41:16 -0700
    • Engine revision ee76268252
    • Dart version 2.8.4
 
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
    • Android SDK at /Users/fernando/Library/Android/sdk
    • Platform android-29, build-tools 29.0.2
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 11.5)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 11.5, Build version 11E608c
    • CocoaPods version 1.8.4

[✓] Android Studio (version 4.0)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 46.0.2
    • Dart plugin version 193.7361
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)

[✓] VS Code (version 1.45.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.10.2

[✓] Connected device (1 available)
    • iPhone ... • ios • iOS 13.5.1

• No issues found!

pubspeck.yml dependencies

dependencies:
  flutter:
    sdk: flutter
  json_annotation: ^3.0.1
  jaguar_orm: ^2.2.7
  jaguar_query_sqflite: ^2.2.11
  device_info: ^0.4.2+4
  rxdart: ^0.22.2
  bloc_pattern: ^2.3.2
  dio: ^3.0.1
  intl: ^0.16.0
  sprintf: ^4.0.2
  firebase_messaging: ^6.0.16
  flutter_local_notifications: 1.4.3
  shared_preferences: ^0.5.6+1
  package_info: ^0.4.1
  mask_text_input_formatter: ^1.0.6
  admob_flutter: ^0.3.4
  archive: ^2.0.11
  appsflyer_sdk: ^5.2.0+1
  barcode_scan: ^1.0.0
  cached_network_image: ^2.0.0
  charts_flutter: ^0.8.1
  configurable_expansion_tile: ^1.0.0
  country_pickers: ^1.3.0
  cupertino_icons: ^0.1.3
  data_tables: ^1.0.3
  date_range_picker: ^1.0.5
  flare_flutter: ^1.0.2
  fl_chart: ^0.9.4
  flutter_cupertino_localizations: ^1.0.1
  flutter_slidable: ^0.5.3
  font_awesome_flutter: ^8.5.0
  image_picker: ^0.6.3+4
  path_provider: ^1.6.8
  provider: ^2.0.0
  pretty_qr_code: ^1.0.1
  share: ^0.6.3+6
  sqflite: ^1.2.0
  url_launcher: ^5.2.7
  webview_flutter: ^0.3.15+1
  google_sign_in: ^4.5.1
  flutter_svg: ^0.17.3+1
  flutter_localizations:
    sdk: flutter
@TahaTesser TahaTesser added platform: ios Issues / PRs which are specifically for iOS. plugin: messaging type: bug Something isn't working labels Jun 29, 2020
@vuvantoan95
Copy link

same issues :(. Please help!

@whatamelon
Copy link

you can set content_available and priority option
In my case it solve the background and killed problem

@edjostenes
Copy link

I`m facing the same problem right now, I tried the same request and the problem persists.

@FernandoUFS
Copy link
Author

you can set content_available and priority option
In my case it solve the background and killed problem

@whatamelon From apple, the content-available option is for:

content-available : The background notification flag. To perform a silent background update, specify the value 1 and don't include the alert, badge, or sound keys in your payload. See Pushing Background Updates to Your App.

I don't want a silent notification in background, I want a normal notification to show to the user. I need include "alert".
Anyway I tested content-available, it doesn't work :(

@TahaTesser TahaTesser added the impact: crowd Affects many people, though not necessarily a specific customer with an assigned label. (P2) label Jul 3, 2020
@robrichardson13
Copy link

robrichardson13 commented Jul 9, 2020

I had the same issue. Pushes once worked but then randomly stopped working and I couldn't figure out why.

Here is a decent blog post on how to debug FCM for iOS: https://firebase.googleblog.com/2017/01/debugging-firebase-cloud-messaging-on.html

After following along I realized that my app was successfully getting the device token in didRegisterForRemoteNotificationsWithDeviceToken and was able to send pushes to my device via the NWPusher App which to me meant that FCM was simply failing to send to my APNS token.

I wish there was a way to be able to verify that your APNS token was in sync with your FCM token, but I assumed this could be the problem anyway.

I found at that at some point I disabled Swizzling by adding this to my plist:

<key>FirebaseAppDelegateProxyEnabled</key>
<false/>

*Some people mentioned changing this bool to a string NO would solve it, which simply just disables the flag re-enabling swizzling which turns back on the default APNS token set + analytics which could solve your issue too

I did this because I needed to grab the deviceToken for another purpose (use with Mixpanel). So in my AppDelegate.swift I override the didRegisterForRemoteNotificationsWithDeviceToken like so:

This is outlined in the references here:

  import FirebaseMessaging
  ...

  override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    Mixpanel.mainInstance().people.addPushDeviceToken(deviceToken) //For Mixpanel purposes, not needed if not using
    Messaging.messaging().apnsToken = deviceToken //*THIS WAS MISSING*
    super.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken) //Not sure if calling super is required, but did anyway
  }

I realized that if you disable swizzling you must set the APNS token manually or FCM will never know the device token meaning remote or background notifications will never come to the app.

So simply adding this line into the didRegisterForRemoteNotificationsWithDeviceToken callback fixed my issue:

Messaging.messaging().apnsToken = deviceToken

Side note:

If you disable swizzling, the FCM analytics won't automatically work (for deliveries and opens) so you'll have to add this code in to ensure FCM knows about it.

This is outlined in the references here:

  override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Swift.Void) {
    Messaging.messaging().appDidReceiveMessage(userInfo)
    ///Not sure if calling super is required here
    super.application(application, didReceiveRemoteNotification: userInfo, fetchCompletionHandler: completionHandler)
  }

@kmdinake
Copy link

@robrichardson13 Thanks for your solution, I did not realize that by disabling method swizzling I had to implement or call the functions that Firebase Message was handling in the background. In addition to the above, I would also emphasize that people call application.registerForRemoteNotifications() in the didFinishLaunchingWithOptions method as follows:

override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
    if #available(iOS 10.0, *) {
      UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate
    }
    GeneratedPluginRegistrant.register(with: self)
    application.registerForRemoteNotifications()  //* I Forgot This Line *
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

@FernandoUFS
Copy link
Author

Hi @robrichardson13 thank's for your reply.

First, I didn't have <key>FirebaseAppDelegateProxyEnabled</key> on my Info.plist.
Then I override the didRegisterForRemoteNotificationsWithDeviceToken on my AppDelegate.swift to get my device token and test at Pusher. Sending a push from Pusher worked. My app received and showed the notification in background.

So I added the <key>FirebaseAppDelegateProxyEnabled</key> to my Info.plist (tried the bool value false, and string value NO).
This is my didRegisterForRemoteNotificationsWithDeviceToken function

override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
        print("==== didRegisterForRemoteNotificationsWithDeviceToken ====")
        print(deviceTokenString)
        Messaging.messaging().apnsToken = deviceToken
}

But after that, it happened exactly like before. The FCM can't deliver the notifications when the app is in background, only when it is in foreground.

Also I tested sending from FCM directly to my device token (not using topics), I get the same result.

I conclude that if the firebase can deliver notifications when app is in foreground, then it has the apn token registered successfully on its backend. @robrichardson13 Am I right about this conclusion?

I didn't solve my problem yet. I know that APN is working because I tested on Pusher, but when it is sent from FCM it's not working. I am not sure if it's related to firebase_messaging plugin. It seems like a problem between FCM and APN.

@curlyeto
Copy link

Hi everyone.

Works in all situations on android but On launch and on resume do not trigger when app is in background or terminated. @robrichardson13 I tired your solution but it hasn't changed.

Flutter doctor version

ertugrul@ertugruls-Mac ~ % flutter doctor -v
[✓] Flutter (Channel stable, v1.12.13+hotfix.8, on Mac OS X 10.15 19A602, locale
en-TR)
• Flutter version 1.12.13+hotfix.8 at /Users/ertugrul/flutter
• Framework revision 0b8abb4724 (5 months ago), 2020-02-11 11:44:36 -0800
• Engine revision e1e6ced81d
• Dart version 2.7.0

[!] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
• Android SDK at /Users/ertugrul/Library/Android/sdk
• Android NDK location not configured (optional; useful for native profiling
support)
• Platform android-28, build-tools 29.0.3
• Java binary at: /Applications/Android
Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build
1.8.0_212-release-1586-b4-5784211)
✗ Android license status unknown.
Try re-installing or updating your Android SDK Manager.
See https://developer.android.com/studio/#downloads or visit
https://flutter.dev/setup/#android-setup for detailed instructions.

App Delegate.swift

import UIKit
import Flutter
import FirebaseMessaging

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
print("==== didRegisterForRemoteNotificationsWithDeviceToken ====")
print(deviceTokenString)
Messaging.messaging().apnsToken = deviceToken
}
}

Fcm code

_fcm.configure(onMessage: (Map<String, dynamic> message) async {
print("onMessage tetkilendi: $message");
showNotification(message);
},
onBackgroundMessage: Platform.isIOS?null:myBackgroundMessageHandler,
onLaunch: (Map<String, dynamic> message) async {
print("onLaunch tetiklendi: $message");
showNotification(message);
},
onResume: (Map<String, dynamic> message) async {
print("onResume tetiklendi: $message");
showNotification(message);
},
);

Also Info.plist added

<key>FirebaseAppDelegateProxyEnabled</key> <string>NO</string>

Firebase messagin version is 6.0.16. Is there an error in the code I wrote or is it in the fcm package?

@saravananmnm
Copy link

Your android folder should be a Application.java file
`package in.tvs.iex_driver;

import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService;
import io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin;
import com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin;

public class Application extends FlutterApplication implements PluginRegistry.PluginRegistrantCallback {

@Override
public void onCreate() {
    super.onCreate();
    FlutterFirebaseMessagingService.setPluginRegistrant(this);
}

@Override
public void registerWith(PluginRegistry registry) {
    // I've only had to add this line to make it work
    FirebaseMessagingPlugin.registerWith(registry.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));
    FlutterLocalNotificationsPlugin.registerWith(registry.registrarFor("com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin"));
}

}
`

@hermitdave
Copy link

hermitdave commented Jul 15, 2020

We have been experiencing similar issue and thanks you my colleague @JanKn not upgrading the app on his iOS device, we realised that notifications worked on older builds. Trying various builds, I have come to the conclusion that the point it stopped working was when I upgraded my macOS to Catalina.

I am tempted to downgrade to Mojave to see if that really was the cause. At present nothing I have tried has worked with current xcode / macOS to build the app

@robrichardson13
Copy link

@robrichardson13 Thanks for your solution, I did not realize that by disabling method swizzling I had to implement or call the functions that Firebase Message was handling in the background. In addition to the above, I would also emphasize that people call application.registerForRemoteNotifications() in the didFinishLaunchingWithOptions method as follows:

@kmdinake You don't need to call application.registerForRemoteNotifications() because when you call _firebaseMessaging.configure() in Flutter this will call [[UIApplication sharedApplication] registerForRemoteNotifications];. You can see this if you look at the FLTFirebaseMessagingPlugin.m file in the source code. Also if you call _firebaseMessaging.requestNotificationPermissions(); this will call [[UIApplication sharedApplication] registerForRemoteNotifications]; for you as seen here, FLTFirebaseMessagingPlugin.m

I conclude that if the firebase can deliver notifications when app is in foreground, then it has the apn token registered successfully on its backend. @robrichardson13 Am I right about this conclusion?

@FernandoUFS FCM notifications being received in the foreground does NOT mean that the APN token is registered successfully. My assumption is that FCM in the foreground uses some sort of Socket to deliver in the foreground and uses the iOS APNS (Remote Notifications) for background delivery. So if background delivery isnt working, I would assume it means that the APN token is never being sent to FCM correctly.

@curlyeto try setting your .plist to the following to disable swizzling. Setting to a string value will not disable.

<key>FirebaseAppDelegateProxyEnabled</key>
<false/>

@curlyeto
Copy link

@robrichardson13 thanks for answering. I assigned a false value to FirebaseAppDelegateProxyEnabled. I am sending a notification from postman. When the application is open, response data type. When it is closed, reponse notificaiton type.

Postman json

{
	"to":"token",
	"data":{
		"title":"Data",
		"body":"data1",
		"photo":"https://i4.hurimg.com/i/hurriyet/75/750x422/5e5771550f254405d052eb10.jpg"
	},
	"notification":{
		"title":"Notification",
		"body":"Notification1",
		"photo":"https://i4.hurimg.com/i/hurriyet/75/750x422/5e5771550f254405d052eb10.jpg"
	}
}
_fcm.configure(onMessage: (Map<String, dynamic> message) async {
print("onMessage tetkilendi: $message");
showNotification(message);
},
onBackgroundMessage: Platform.isIOS?null:myBackgroundMessageHandler,
onLaunch: (Map<String, dynamic> message) async {
print("onLaunch tetiklendi: $message");
showNotification(message);
},
onResume: (Map<String, dynamic> message) async {
print("onResume tetiklendi: $message");
showNotification(message);
},
);

static void showNotification(Map<String,dynamic> message)async{

var largeIconPath = Platform.isIOS?await NotificationHandler()._downloadAndSaveFile(message["photo"], 'largeIcon'):
    await NotificationHandler()._downloadAndSaveFile(message["data"]["photo"], 'largeIcon');
var androidPlatformChannelSpecifics = AndroidNotificationDetails(
      '0',
      'Mesaj Bildirimleri',
      'Gelen Mesajlar',
      largeIcon: FilePathAndroidBitmap(largeIconPath),
      styleInformation: MediaStyleInformation(),
    );
var iOSPlatformChannelSpecifics = IOSNotificationDetails();
var platformChannelSpecifics = NotificationDetails(androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
Platform.isIOS?await flutterLocalNotificationsPlugin.show(0, message["title"], message["body"], platformChannelSpecifics):
await flutterLocalNotificationsPlugin.show(0, message["data"]["title"], message["data"]["body"], platformChannelSpecifics);
}

I want the data type from the data postman in the background. I've been dealing for 4 or 5 days and I couldn't solve the problem

@mintymac
Copy link

@curlyeto I have been running into a situation where if the code fails in the onMessage, onResume functions, that the application will not report the error. Is the error happening in an isolate?

Could you try stripping down the sendNotifications function to just print to console? Also, I ended up using conditional logic around the message map using message.containsKey('data') etc.

@FernandoUFS
Copy link
Author

Hi guys, after doing everything, the notification worked again, I had a particular problem that I didn't notice.
I have a common package shared between projects, and the firebase_messaging, and all configuration was there.
We removed firebase_messaging from project's pubspec.yml since it was on our own package:

dependencies:
  common:
    path: ../../common/
  (other packages, but not firebase_messaging) ...

I just added it again to the main project's pubspec.yml, also I did the same thing as @kmdinake and @robrichardson13 overriding those methods. Now firebase can deliver notifications in background. I didn't even remove the overrode code on iOS because it's working and tomorrow we will launch a new version. But it seems like the problem was just that.

@curlyeto
Copy link

Hi guys, @mintymac thanks for your answer. On message, on resume funtions is working. I added showNotficaiton function inside print but not working in the backgorund. When I open the app when I send a notification in the background, the on message function works.

  static void showNotification(Map<String,dynamic> message)async{
      print("Show notfication runing ${message}");
      // personel message
      var largeIconPath = Platform.isIOS?await NotificationHandler()._downloadAndSaveFile(message["photo"], 'largeIcon'):
      await NotificationHandler()._downloadAndSaveFile(message["data"]["photo"], 'largeIcon');
      var androidPlatformChannelSpecifics = AndroidNotificationDetails(
        '0',
        'Mesaj Bildirimleri',
        'Gelen Mesajlar',
        largeIcon: FilePathAndroidBitmap(largeIconPath),
        styleInformation: MediaStyleInformation(),
      );
      var iOSPlatformChannelSpecifics =IOSNotificationDetails();
      var platformChannelSpecifics = NotificationDetails(androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
      Platform.isIOS?await flutterLocalNotificationsPlugin.show(0, message["title"], message["body"], platformChannelSpecifics,):
      await flutterLocalNotificationsPlugin.show(0, message["data"]["title"], message["data"]["body"], platformChannelSpecifics,);
  }

App Delegate.swift

import UIKit
import Flutter
import Firebase
import FirebaseMessaging

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {

    FirebaseApp.configure()
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
  override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
           let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
           print("==== didRegisterForRemoteNotificationsWithDeviceToken ====")
           print(deviceTokenString)
           Messaging.messaging().apnsToken = deviceToken
   }
}

Firebase request json

{
	"to":"token",
	"data":{
		"title":"Data",
		"body":"data1",
		"photo":"https://i4.hurimg.com/i/hurriyet/75/750x422/5e5771550f254405d052eb10.jpg"
	}
}

FirebaseAppDelegateProxyEnabled boolean false and string NO I tried two status but noting changing.

I want the data type from the data postman in the background. What function is triggering in the background for ios ? Where am I doing wrong ? Firebase request json format it is correct ? Can you help me @FernandoUFS , @mintymac , @robrichardson13 ?

@adar2378
Copy link

adar2378 commented Jul 23, 2020

Hey guys, I've been having the same issue. Since I was using flutter_local_notification package to display notifications, I had to set the value of FirebaseProxyEnabled to false, For that reason, firebase auth wasn't working properly, so I followed these steps:https://firebase.google.com/docs/auth/ios/phone-auth#appendix:-using-phone-sign-in-without-swizzling
But now the notifications, only trigger onMessage callback whenever the I open the app, And notifications show properly when the app is on the foreground.
I know that firebase keeps the notifications in the queue for data message, and triggers when the app opens but for notification messages the same things are happening. I don't know what is wrong. So sad that I can't show notifications when the app is killed or on the background on iOS

@mintymac
Copy link

@curlyeto Of course, happy to. From my understanding, FirebaseMessaging delivers the data message in iOS via onMessage if the app is terminated. Is there something you can accompolish with in app messaging to fill the gap for Android?

@BouweCeunen
Copy link

None of the proposed resolutions are working here, not sure what to try next.

@curlyeto
Copy link

@mintymac I didn't understand this sentences. " Is there something you can accompolish with in app messaging to fill the gap for Android? " . Can you explain in detail?

@BouweCeunen
Copy link

I can confirm that It's also working for me on TestFlight.

@adar2378
Copy link

I can confirm that It's also working for me on TestFlight.

How?

@rize17
Copy link

rize17 commented Aug 7, 2020

Push is working fine for me on IOS using flutter, an APNs Authentication Key in the firebase console, and firebase_messaging: ^6.0.16 in my pubspec.yaml.

I am not using TestFlight.
I created a new flutter app on Android studio and added the https://pub.dev/packages/firebase_messaging example.
I did not add
FirebaseAppDelegateProxyEnabled
or
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
}

I used the console on firebase / Compose notification / "send test message". With only "Notification title" and "Notification text" fields filled in and I'm getting push notifications with the app closed coming through.

@ChoLianJiet
Copy link

For Firebase Messaging setting up i followed the steps from https://pub.dev/packages/firebase_messaging

And for local flutter notifications i followed the steps from https://pub.dev/packages/flutter_local_notifications

Previously, for Android side, it was working fine for me. Notifications was showing up when app is on foreground and background. However, for iOS side, notifications only showing up when app is on foreground, it was not showing when app is on background.

What i have done below has solved my problem.

When sending firebase message payload, make sure the title and the body of the message is nested under ['notification'] instead of ['data'] (I'm using node.js to code my functions). You can add additional data under ['data']

My node js code
Example:-

const payload = admin.messaging.MessagingPayload = {
     notification:{
          title: 'This is the title,
          body: 'This is the body,
     },
     data:{
          click_action: `FLUTTER_NOTIFICATION_CLICK`,
     },
}

What i have done previously that didn't work for iOS background is i put my title and body in ['data']

const payload = admin.messaging.MessagingPayload = {
     data:{
          title: 'This is the title,
          body: 'This is the body,
          click_action: `FLUTTER_NOTIFICATION_CLICK`,
     },
}

After you have put your title and body under ['notification'], next go to your dart code (Setting up FCM part).

When configuring FCM (The part where you initialize onMessage, onResume, onLaunch, onBackgroundMessage), make sure when your platform is iiOS, set onBackgroundMessage to null.

Dart code
Example:-

_fcm.configure(
     onMessage: (Map<String, dynamic> message) async {
          ///Print your fcm payload when app is on foreground
          print('foreground message $message');

          ///If platform is android the returned payload notification is nested under ['notification']
          if(Platform.isAndroid){
              _showAndroidFCMDialog(message['notification']);
          }

          ///If platform is android the returned notification is nested under ['aps']['alert']
          if(Platform.isIOS){
              _showIOSFCMDialog(message['aps']['alert']);
          }
     },
     onResume: (Map<String, dynamic> message) async {},
     onLaunch: (Map<String, dynamic> message) async {},
     ///When platform is iOS, set onBackgroundMessage to null, else call your background handler function
     onBackgroundMessage: Platform.isIOS? null : _backgroundMessageHandler
);

_My backgroundMessageHandler

Future<dynamic> _backgroundMessageHandler(Map<String, dynamic> message) async {
     print('background message $message');

     ///Specify android notification bar UI
     AndroidNotificationDetails androidPlatformChannelSpecifics =
     AndroidNotificationDetails(
     'Simply Better Channel Id',
     'Simply Better Channel Name',
     'Simply Better Channel Description',
     importance: Importance.Max,
     priority: Priority.High,
     sound: RawResourceAndroidNotificationSound('test_sound'),
     icon: 'app_icon',
     playSound: true,
     largeIcon: DrawableResourceAndroidBitmap('app_icon'),
     styleInformation: BigTextStyleInformation(''),
     timeoutAfter: 5000,
     ledColor: const Color(0xff8773FF),
     ledOnMs: 1000,
     ledOffMs: 500,
     color: Color(0xff8773FF),
     enableVibration: true,
     );

     ///Specify iOS notification bar UI
     ///iOS part is never called
     IOSNotificationDetails iOSPlatformChannelSpecifics = IOSNotificationDetails();

     ///Specify overall notification bar UI
     NotificationDetails platformChannelSpecifics = NotificationDetails(
     androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);

     ///Show notification bar
     if(Platform.isAndroid){
          return await flutterLocalNotificationsPlugin.show(0, message["data"]["title"],
          message["data"]["body"], platformChannelSpecifics,
          payload: 'payload');
     }

     ///iOS part is never called
     if(Platform.isIOS){
          return await flutterLocalNotificationsPlugin.show(0, message['aps']['alert']["title"],
          message['aps']['alert']["body"], platformChannelSpecifics,
          payload: 'payload');
     }
}

Finally, under XCode, under the tab Signing & Capabilities, i have ticked the Automatically manage signing. (You should have already enabled your Background Mode, ticked Background Fetch and Remote Notifications as well as enabled Push Notification if you have followed the setup procedures in the links above).

I hope these solutions help. It worked for me.

@huferry
Copy link

huferry commented Aug 12, 2020

This is what I experienced, the push message goes well when the app is running on the foreground, but not when it's on the background; both when using simulator or test device.
When I detached the device and run the application unconnectedly to Xcode (or Android Studio) then the notification gets through while the app is running on the background.

@roderikpeeters
Copy link

I fixed my problem by deleting the push notification capability because I saw that I had "(Profile)" next to the push notification capability. After that, I just added it back and the "(Profile)" was gone and the notification started working again!

Before:
Screenshot 2020-08-02 at 17 56 36

After:
Screenshot 2020-08-02 at 19 17 27

This fixed it for me, however I still don't hear any sound on the phone...

@tihhmachado
Copy link

Hello guys!

I'm having the same problem. On android everything works perfectly. In IOS, with the app in the foreground, notification messages trigger the onMessage callback, with the app in the background or closed, no notification is delivered to the IOS tray, but when opening the app, onMessage is triggered, as if the notification was being delivered at that time.

I created a new project just to test notifications on IOS, in this new project the behavior was the same.

Has anyone managed to find any solution? Any idea what is @TahaTesser? From what I see many people are facing this problem.

@Doetheman
Copy link

I have the exact opposite issue. FCM works in the background but not in the foreground. We followed https://pub.dev/packages/firebase_messaging.

@chornbe
Copy link

chornbe commented Aug 26, 2020

My app is literally useless without pushes being sent to the user when backgrounded or stopped (personal location-aware safety alert app), and they worked in previous versions using the exact same code. This new version cleans up a lot of silly Flutter mistakes we made while learning Flutter 2 years ago because we were desperate to get off React Native. This new version structurally looks exactly like the old version in the main.dart and dependencies in the YAML file. Something got updated, now this thread applies 100%. (sigh)

It's to the point where I'm dusting off the rev-1 product written in Swift to do a bunch of feature updates and push out because it works just fine using native APNS and 100% native code... which means we have to version freeze the Android version and React Native libraries.

I don't know at this point if it's some deep dependency somewhere, a breakage in some updates to FCM, or what's going on, but I'm stuck, and really don't have any more time to put into tracking this down when 100 threads just like this all end with dozens of people still looking for an answer.

(Note: FCM reports success on the push, so I am at a loss as to what to check next)

@chornbe
Copy link

chornbe commented Aug 26, 2020

holy crap.

this worked.

https://stackoverflow.com/questions/58198340/firebase-push-notifications-dont-work-on-ios-13

I did NOT expect that, and how can we control that without the user getting involved? Because that is simply NOT a scalable, viable solution. It simply isn't.

Quick Fix Solution:

If you are facing issue to receive push notification on iOS version 13.2.X, then do below change in device settings and check again:

Device > Settings > Search your AppName > Notifications > Banner Style > Change it to "Persistent" from "Temporary" or vise-versa one time.

Now send push notification again and its start receiving.

@chornbe
Copy link

chornbe commented Aug 26, 2020

Maybe this helps.

Running the app in XCode, I can see this response from the listener on the ios push notifications settings:
2020-08-26 18:37:05.129806-0400 Runner[42679:195091] flutter: Settings registered: PushNotificationSettings {sound: false, alert: false, badge: false, provisional: true}

However, the Flutter code CLEARLY asks for these settings to all be true.

    _firebaseMessaging.requestNotificationPermissions(
      const IosNotificationSettings(
        sound: true,
        badge: true,
        alert: true,
        provisional: true,
      ),
    );

Additionally, shouldn't that call to requestNotificationPermissions trigger the device's built-in dialog asking the user to approve notifications? I put it on one real device and a number of simulators I hadn't used before, and got no dialog. I assumed it was because I'd previously installed this bundle name on the various previous devices, even though I'd deleted it, but if it's not asking for perms even on new devices - even though notifications do get set up in settings - would that have something to do with what's going on?

@amantoux
Copy link
Contributor

amantoux commented Aug 28, 2020

Might not be the solution to all the problems here but just in a case:
Make sure you subscribe to
FirebaseMessaging.onTokenRefresh and update your server accordingly
You'll notice that the refresh happens quite often especially when developing (numerous installations, new sessions etc)

For some reason, this refresh seems to happen less often on Android...

Hope it helps

PS : Thanks for the blog post @robrichardson13 it was very helpful (https://firebase.googleblog.com/2017/01/debugging-firebase-cloud-messaging-on.html)

@kshivam1177
Copy link

I fixed my problem by deleting the push notification capability because I saw that I had "(Profile)" next to the push notification capability. After that, I just added it back and the "(Profile)" was gone and the notification started working again!

Before:
Screenshot 2020-08-02 at 17 56 36

After:
Screenshot 2020-08-02 at 19 17 27

fixed my problem too.

@yarmel
Copy link

yarmel commented Oct 2, 2020

https://stackoverflow.com/questions/64172280/flutter-fcm-on-ios-14

@MurtuzaSrashtaSoft
Copy link

MurtuzaSrashtaSoft commented Oct 7, 2020

not receive notification in the ios simulator while the app in the background or kill.

https://stackoverflow.com/questions/64242818/not-receive-fcm-push-notification-in-ios-while-app-in-background-or-terminate-i

@tech-instacare
Copy link

not receive notification in the ios simulator while the app in the background or kill.

facing same problem.

@anztrax
Copy link

anztrax commented Oct 19, 2020

ya still facing the same problem, anyone can help ? 😕

@chornbe
Copy link

chornbe commented Oct 19, 2020

ya still facing the same problem, anyone can help ? 😕

Specifically replying to @anztrax as I totally sense and feel your frustration. terminated the project in Flutter for a variety of reasons, and wrote the iOS version in native code, and for the time being, I'm not offering an Android version of this particular project. For the other project where we already have an installed base, I have suspended updates, and rolled back a lot of commits to the version I knew last worked, and have frozen that version as "the" version for the time being.

In my investigation, starting over from scratch on a brand new project, I can make things work and as the project progresses, there comes a point where lots of stuff stops working. I'm probably 5 or 6 redoes into this investigation, to the point that the only thing I've really learned is that lagging dependencies, weird dependency and/or version conflicts, etc., DO exist and ARE causing problems that make no sense. But I'll be damned if I can build a list with any confidence or consistency.

I literally do not have time for the investigation this would take.

Flutter's overall dependency model and inclusions system is... sloppy, and the community support on libraries is not the speediest. I mean, I get it; many of the libraries out there that don't come from the core group are ones that may solve a certain problem a certain way for a certain developer, but may not necesarily be ready for the Wild West prime time that is the bigger world. I get it.

In my one project, I've basically just started stripping out all dependency libraries, writing my own, and not relying on the community. I've pushed this project out ~6 months now, but I'm ending up with 100% in house code.

And I STILL have problems with push notifications on Firebase, so maybe it's all a wasted effort.

@acoutts
Copy link

acoutts commented Oct 19, 2020

The issues here are largely isolated to the firebase libs. They are in progress of being rewritten but it will take time. @chornbe are you by chance using any other firebase services like auth?

@adar2378
Copy link

adar2378 commented Oct 19, 2020

#3395 (comment)

For anyone who disabled swizzling can have a look here.

@chornbe
Copy link

chornbe commented Oct 19, 2020

The issues here are largely isolated to the firebase libs. They are in progress of being rewritten but it will take time. @chornbe are you by chance using any other firebase services like auth?

In one project, yes (firebase is the entire "back end"). In another, no, just using pushes.

@chornbe
Copy link

chornbe commented Oct 19, 2020

#3395 (comment)

For anyone who disabled swizzling can have a look here.

Thanks, saved for future perusal. Working on something else today, but interested in looking through this. Thanks, man!

@acoutts
Copy link

acoutts commented Oct 19, 2020

Yeah I had no luck getting swizzling to play nice with Auth and Messaging, but after implementing like I outlined in the link @adar2378 shared, I was able to make everything happy again. To be honest, it's not a huge deal to forego swizzling - you just set it up once and leave it. One less "magic" thing that can break.

I've spent a lot of time looking into this. What I found in the end is the sample project included in the messaging app works flawlessly, so there's no problem with it. It breaks when combined with Auth if you have swizzling enabled. But there shouldn't be anything wrong with the messaging lib on its own. I'd double check you've got all of the setup steps correct like the APNS certificate/token uploading to FCM, and make sure the notifications permission is enabled etc. I know you probably read the instructions but it's worth a triple check as there's a lot of steps that can be misconfigured / go wrong.

@adar2378
Copy link

A very good news, FCM rework is coming soon https://twitter.com/mikediarmid/status/1319298281290203139?s=20

@shinsenter
Copy link

Same to me. Some iOS devices are not receiving notifications.

@Gensjava
Copy link

I have the same problem as well.

@CoderJava
Copy link

#2603

@CoderJava
Copy link

CoderJava commented Dec 16, 2020

#2603

I have fixed it this problem.
#2603 (comment)

Hopefully it's working for all of you.

@russellwheatley
Copy link
Member

Given the major reworks to messaging, I'd kindly request you upgrade to the latest version and follow the reworked docs very closely here for what is/isn't possible on iOS. Will reopen if this is still a problem on the latest version.

@firebase firebase locked and limited conversation to collaborators Jun 6, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
impact: crowd Affects many people, though not necessarily a specific customer with an assigned label. (P2) platform: ios Issues / PRs which are specifically for iOS. plugin: messaging type: bug Something isn't working
Projects
None yet
Development

No branches or pull requests