invertase / react-native-firebase

🔥 A well-tested feature-rich modular Firebase implementation for React Native. Supports both iOS & Android platforms for all Firebase services.
https://rnfirebase.io
Other
11.71k stars 2.22k forks source link

🔥`getInititalNotification` not retrieving notification data iOS app closed #3095

Closed 7patricia closed 4 years ago

7patricia commented 4 years ago

Issue

Hi! I am having a problem with the notifications library. I need to get the notification data in order to open my application in a specific page. Everything is working fine in Android for every app state, but in iOS, when the app is closed and I click the notification, getInitialNotification method is not returning notification data. It is triggered, but the value is undefined. When the app is in foreground or background everything is ok.

I'm sending remote cloud notifications that look like this:

{ "to":"token here",
    "notification": {
        "title": "Test Notification",
        "body": "password reset"
    },
    "data": {
        "url": "myApp://password/reset?token=dfsfsdfsdfsdfdsfsdf"
    }
}

Any ideas on what it might be?

I'm using v5.6.0, but I forked it and done some changes:

Screenshot 2020-01-13 at 16 46 42

P.S: I didn't fill out the Android project files part of the issues since my problem is only in iOS, but please let me know if that would be helpful.


Project Files

Javascript

Click To Expand

#### `package.json`: ```json { "name": "myPackageName", "version": "1.0.0", "private": true, "description": "My app", "author": "My app", "main": "index.js", "dependencies": { (...) "react-native": "0.61.5", "react-native-firebase": "git+ssh://git@github.com/my-org/react-native-firebase#mybranch", (...) }, "devDependencies": { "@babel/core": "7.6.2", "@babel/runtime": "7.6.2", "babel-core": "7.0.0-bridge.0", "babel-jest": "24.9.0", "chai": "4.2.0", "detox": "14.0.3", "eslint-plugin-detox": "1.0.0", "jest": "24.9.0", "mailosaur": "5.0.8", "react-devtools-core": "3.4.3", "react-test-renderer": "16.9.0", "reactotron-react-native": "2.0.0", "relay-compiler": "1.6.2", "stylelint": "10.1.0" }, "resolutions": { "react-devtools-core": "3.4.3" }, "rnpm": { "assets": [ "./src/lib/assets/fonts" ] }, "detox": { "configurations": { "android": { "binaryPath": "android/app/build/outputs/apk/debug/app-debug.apk", "build": "pushd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug && popd", "name": "device", "session": { "sessionId": "manualsession", "server": "ws://localhost:8099" }, "type": "android.emulator" }, "ios": { "binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/MyApp.app", "build": "xcodebuild -workspace ios/Wallet.xcworkspace -UseNewBuildSystem=NO -scheme Wallet -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build ", "name": "iPhone 8", "type": "ios.simulator" } }, "test-runner": "jest" } } ``` ### `index.js` ```json export class Application extends Component { constructor(props) { super(props); } componentDidMount() { this.removeNotificationListener = firebase.notifications().onNotification(received => { if (received && get(received, '_data.displayInForeground') !== 'false') { const notification = new firebase.notifications.Notification() .setBody(get(received, '_body')) .setData(get(received, '_data')) .setNotificationId(get(received, '_notificationId')) .setTitle(get(received, '_title')); if (Platform.OS === 'android') { const channel = new firebase.notifications.Android.Channel( 'my-channel', 'My Channel', firebase.notifications.Android.Importance.Max ).setDescription('My notifications channel'); firebase.notifications().android.createChannel(channel); notification.android.setColor(styles.colors.p06); notification.android.setChannelId('my-channel'); notification.android.setPriority(firebase.notifications.Android.Priority.Max); notification.android.setSmallIcon('ic_notifications'); } firebase.notifications().displayNotification(notification); } }); this.removeNotificationOpenedListener = firebase.notifications().onNotificationOpened(notification => { this.handleNotificationOpened(notification); }); firebase .notifications() .getInitialNotification() .then(notification => { if (notification) { this.handleNotificationOpened(notification); } }); } componentWillUnmount() { this.removeNotificationOpenedListener(); this.removeNotificationListener(); } handleNotificationOpened(notification) { if (notification && get(notification, 'notification._data.url')) { this.setUser({ notification }); if (PlatformUtils.isIOS) { const navigation = get(NavigatorInstance.navigator, '_navigation'); Navigation.navigate(navigation, 'splash'); } } } } ``` #### `firebase.json` for react-native-firebase v6: ```json # N/A ``` ### iOS

Click To Expand

#### `ios/Podfile`: - [ ] I'm not using Pods - [x] I'm using Pods and my Podfile looks like: ```json platform :ios, '9.0' require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' source 'https://github.com/CocoaPods/Specs.git' use_frameworks! target "Wallet" do pod 'JumioMobileSDK/Netverify', '3.3.1' # Required by react native. pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec' pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector" pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec" pod 'Firebase/Core', '~> 6.13.0' pod 'Firebase/Messaging', '~> 6.13.0' pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec' pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec' pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired" pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety" pod 'React-Core', :path => '../node_modules/react-native/' pod 'React-Core/DevSupport', :path => '../node_modules/react-native/' pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/' pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules' pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact' pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi' pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor' pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector' pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS' pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation' pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob' pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image' pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS' pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network' pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings' pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text' pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration' pod 'React', :path => '../node_modules/react-native/' pod 'ReactCommon/jscallinvoker', :path => "../node_modules/react-native/ReactCommon" pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon" pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga' end post_install do |installer| rnfirebase = installer.pods_project.targets.find { |target| target.name == 'RNFirebase' } rnfirebase.build_configurations.each do |config| config.build_settings['HEADER_SEARCH_PATHS'] = '$(inherited) ${PODS_ROOT}/Headers/Public/**' end end use_native_modules! ``` ```ruby # N/A ``` #### `AppDelegate.m`: ```objc /** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ #import "AppDelegate.h" #import #import #import #import #import #import "RNSplashScreen.h" #import "RNFirebaseNotifications.h" #import "RNFirebaseMessaging.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { return [RCTLinkingManager application:application openURL:url sourceApplication:sourceApplication annotation:annotation]; } - (void)applicationWillEnterForeground:(UIApplication *)application { [[self.window.rootViewController.view viewWithTag:999] removeFromSuperview]; } // Only if your app is using [Universal Links](https://developer.apple.com/library/prerelease/ios/documentation/General/Conceptual/AppSearch/UniversalLinks.html). - (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler { return [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler]; } - (void)applicationDidEnterBackground:(UIApplication *)application { UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleRegular]; UIVisualEffectView *bluredView = [[UIVisualEffectView alloc] initWithEffect:effect]; bluredView.frame = self.window.rootViewController.view.bounds; bluredView.tag = 999; [self.window.rootViewController.view addSubview:bluredView]; } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { if ([FIRApp defaultApp] == nil) { [FIRApp configure]; } if (launchOptions) { //launchOptions is not nil NSDictionary *userInfo = [launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; NSDictionary *apsInfo = [userInfo objectForKey:@"aps"]; if (apsInfo) { //apsInfo is not nil NSLog(@"apsInfo %@", apsInfo); [[RNFirebaseNotifications instance] didReceiveRemoteNotification:userInfo fetchCompletionHandler:nil]; } } [RNFirebaseNotifications configure]; RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"Wallet" initialProperties:nil]; rootView.backgroundColor = [UIColor blackColor]; self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; if (@available(iOS 13.0, *)) { self.window.overrideUserInterfaceStyle = UIUserInterfaceStyleLight; } UIViewController *rootViewController = [UIViewController new]; rootViewController.view = rootView; self.window.rootViewController = rootViewController; [self.window makeKeyAndVisible]; // [RNSplashScreen show]; [RNSplashScreen showSplash:@"LaunchScreen" inRootView:rootView]; UNUserNotificationCenter.currentNotificationCenter.delegate = self; [UIApplication sharedApplication].applicationIconBadgeNumber = 0; return YES; } - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification { [[RNFirebaseNotifications instance] didReceiveLocalNotification:notification]; } - (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler{ [[RNFirebaseNotifications instance] didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler]; } - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings { [[RNFirebaseMessaging instance] didRegisterUserNotificationSettings:notificationSettings]; } - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { #if DEBUG return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; #else return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; #endif } - (void)userNotificationCenter:(UNUserNotificationCenter* )center willPresentNotification:(UNNotification* )notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler { completionHandler(UNNotificationPresentationOptionAlert); } @end ```

--- ### Android
Click To Expand

#### Have you converted to AndroidX? - [ ] my application is an AndroidX application? - [ ] I am using `android/gradle.settings` `jetifier=true` for Android compatibility? - [X] I am using the NPM package `jetifier` for react-native compatibility? #### `android/build.gradle`: ```groovy // N/A ``` #### `android/app/build.gradle`: ```groovy // N/A ``` #### `android/settings.gradle`: ```groovy // N/A ``` #### `MainApplication.java`: ```java // N/A ``` #### `AndroidManifest.xml`: ```xml ```

--- ## Environment
Click To Expand

**`react-native info` output:** ``` warn Your project is using deprecated "rnpm" config that will stop working from next release. Please use a "react-native.config.js" file to configure the React Native CLI. Migration guide: https://github.com/react-native-community/cli/blob/master/docs/configuration.md warn The following packages use deprecated "rnpm" config that will stop working from next release: - react-native-sentry: https://github.com/getsentry/react-native-sentry Please notify their maintainers about it. You can find more details at https://github.com/react-native-community/cli/blob/master/docs/configuration.md#migration-guide. info Fetching system and libraries information... System: OS: macOS 10.15.2 CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz Memory: 55.24 MB / 32.00 GB Shell: 5.7.1 - /bin/zsh Binaries: Node: 10.17.0 - /usr/local/opt/node@10/bin/node Yarn: 1.21.0 - /usr/local/bin/yarn npm: 6.11.3 - /usr/local/opt/node@10/bin/npm SDKs: iOS SDK: Platforms: iOS 13.2, DriverKit 19.0, macOS 10.15, tvOS 13.2, watchOS 6.1 Android SDK: API Levels: 28, 29 Build Tools: 28.0.3, 29.0.2 IDEs: Android Studio: 3.5 AI-191.8026.42.35.6010548 Xcode: 11.3/11C29 - /usr/bin/xcodebuild npmPackages: react: 16.9.0 => 16.9.0 react-native: 0.61.5 => 0.61.5 ``` - **Platform that you're experiencing the issue on**: - [X] iOS - [ ] Android - [ ] **iOS** but have not tested behavior on Android - [ ] **Android** but have not tested behavior on iOS - [ ] Both - **`react-native-firebase` version you're using that has this issue:** - `v5.6.0` - **`Firebase` module(s) you're using that has the issue:** - `Notifications` - **Are you using `TypeScript`?** - `N`

--- Think `react-native-firebase` is great? Please consider supporting all of the project maintainers and contributors by donating via our [Open Collective](https://opencollective.com/react-native-firebase/donate) where all contributors can submit expenses. [[Learn More]](https://invertase.io/oss/react-native-firebase/contributing/donations-expenses) - 👉 Check out [`React Native Firebase`](https://twitter.com/rnfirebase) and [`Invertase`](https://twitter.com/invertaseio) on Twitter for updates on the library.
mikehardy commented 4 years ago

Hi there! I think this has all the information I'd expect - and even had the syntax highlighting, thank you. I can't see anything obvious unfortunately. One tiny thing (0-1% chance it will actually change anything) is that firebase ios sdk is at 6.14.0 now.

The notification handler in case getInitialNotification has a notification was omitted so I'm not sure what it's doing but I'll trust it's successfully differentiating between success and failure

Seems like you could just include the messaging pod vs chaining it as a dependency for the notification pod, but I'm not the best at iOS dev so I'm not certain there

One question - is this a remote cloud message with a notification payload that generates the notification, or is it a notification you generate in your app? It might be useful to show the actual JSON you post to the server via a script? At the very least it will make testing it for you even easier

I have a script that posts JSON totally different from what you want but looks like this, for reference, and I can then see what JSON is being sent to the mobile app:

(base) mike@kunashir:~/work/Kullki/ksocialscore/packages (onboarding) % cat public-app/publish/test-silent-push.sh 
#!/bin/bash

PROD_SERVER_KEY="<SERVER KEY FROM THE FIREBASE CONSOLE HERE, OMITTED>"

#SERVER_KEY=$DEV_SERVER_KEY
SERVER_KEY=$PROD_SERVER_KEY

curl -X POST \
--header "Authorization: key=$SERVER_KEY"  \
--Header "Content-Type: application/json" https://fcm.googleapis.com/fcm/send -d "{\"to\":\"/topics/AppInfo\",\"collapse_key\": \"AppInfo\",\"content_available\": true, \"priority\": \"high\", \"data\":{\"IconCheck\":\"Testing Icon\"}}"

My only solid troubleshooting tip is that the docs don't indicate your code:

  if ([FIRApp defaultApp] == nil) {
    [FIRApp configure];
  }

  if (launchOptions) { //launchOptions is not nil
      NSDictionary *userInfo = [launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
      NSDictionary *apsInfo = [userInfo objectForKey:@"aps"];
      if (apsInfo) { //apsInfo is not nil
        NSLog(@"apsInfo %@", apsInfo);
        [[RNFirebaseNotifications instance] didReceiveRemoteNotification:userInfo fetchCompletionHandler:nil];
      }
  }

  [RNFirebaseNotifications configure];

they prescribe:

  [FIRApp configure];
  [RNFirebaseNotifications configure];

...and nothing else. All the other stuff looks well thought out, so I don't submit this as a possible fix, but what happens if you remove everything except the two lines for configure?

7patricia commented 4 years ago

@mikehardy Thanks for the quick response!

I edited the issue adding the information about the type of messages I am sending, and also the missing notification handler.

but what happens if you remove everything except the two lines for configure?

I just tested this and the problem still persists. I also updated Firebase sdk to 6.14.0

mikehardy commented 4 years ago

:thinking: sorry none of that seemed to positively affect it. I'm afraid I don't have any great ideas, but to me this seems like the consequence of mixing data messages (which would otherwise be "messaging" module and known as silent-push) and notification messages

I use a different design where I send data-only messages 100% of the time from firebase, then in my handler I do the necessary local notification API calls to display and handle notifications.

This still may not be on target, but with a data-only style you could put the data you want into async-storage then pop the local notification, and if the user clicks it when the app launches you could check async-storage to see if there is anything important in there.

This is also potentially important because in the case where the user sees the app notification but for some reason clicks the app icon instead of the notification, there is no extra data passed either - https://stackoverflow.com/a/12202161/9910298 - an edge case but something to think about maybe

Thinking even a bit further (I looked into this more because it will affect my work project as well) - if you rely on data-only messages from FCM then then in the case the user has force-closed the app, the message won't be delivered until the app is reopened, which is undesirable: https://facebook.github.io/react-native/docs/pushnotificationios#getdata

The solution to that according to the internet ifor iOS is to not use FCM but to use APNS directly - per https://facebook.github.io/react-native/docs/pushnotificationios#getdata - with the apn module https://www.npmjs.com/package/apn - so you the device will definitely get silent-push notifications

This all may be totally off target but then I'd do:

Then it should handle all app states, including if the user opens via app icon or not, with data always available via either server-fetch on startup or async-storage

But that does all seem terribly complicated. Unfortunately that's my typical experience with mobile messaging :man_shrugging:

7patricia commented 4 years ago

Sooo... after hours and hours of trying to fixing it, trying to send different payloads on the notification, debugging... Turns out it just doesn't work when you have your app in debug mode (which I always had) for some reason. 🤷‍♀ Thank you @mikehardy for your help, hope this helps others that might face the same issue.

mikehardy commented 4 years ago

oh my that isn't what I was thinking at all. Can anyone else verify this (I'll try myself as well). If this is the case a PR to the docs (there's an edit button on the top right of each page) might save lots of others the pain

mstankov commented 4 years ago

@7patricia @mikehardy can confirm that this happens during 'debug' mode

mikehardy commented 4 years ago

Thanks for confirming @mstankov I will PR docs now. @7patricia great work isolating this, sorry it burnt a lot of your time

mikehardy commented 4 years ago

Any comments / suggestions / other places it should be welcome on https://github.com/invertase/react-native-firebase-docs/pull/246

Going to close this as with v5.x.x in maintenance mode a documentation fix is worth more to me (for stability) than code change as long as it's clear (and I think it is?)

seb-montana commented 4 years ago

Hello, With my first experience on React Native app development (iOS/Android), integrate PushNotification seems to be difficult because some concepts have to be understood but simple in reality. After some troubles using Firebase to send PushNotifications (alerts in my case, not silents), everything works fine with Android, but nothing received on iOS, and after reading lots of @mikehardy answers (special thanks Mike !), I've decided to not use Firebase for iOS and directly send request to APNs to deliver my PushNotifications on iOS. Using react-native-push-notification and @react-native-community/push-notification-ios plugins, everything works fine. PN events are catched by onNotification function. One point of attention, on iOS, when user is using app when a PN is received (foreground mode), nothing is shown on iPhone (tested on iOS 13.3.1). So you just have to catch this event in onNotification method and display yourself this notification in your app. Note : react-native-push-notification and @react-native-community/push-notification-ios generate DEVICE_TOKEN (not FCM_TOKEN (which is generated by react-native-firebase plugin)), it's ok between Android <-> Firebase and ok between iOS <-> APNs, nothing else. Note 2 : sorry for my poor english I hope it helps,

mikehardy commented 4 years ago

Hey there @seb-montana - thanks for posting up what worked for you. Just to be clear, since my most recent messages involving messaging and silent push to iOS involved a theory - but no proof - that in the "iOS app was force-closed, then you send a silent message to it" case, the app successfully woke up after receiving a direct-to-APNS silent message and called your onNotification, allowing you to show a local notification (or similar)? That is the one case where - if I understand correctly - FCM simply does not handle things. Hearing a positive confirmation of someone that tested it and it works would help me and others. Thanks!

mstankov commented 4 years ago

@mikehardy indeed it would! @seb-montana your english is perfectly fine. Please confirm whether a direct APNS notification (silent, ak.a. data-only) wakes up the device while the app is killed (dead), it would be of great help :)

seb-montana commented 4 years ago

I've just tried to send silent notification directly using APNs (apns doc). Nothing received on my app when is in background or killed. I only receive notification on foreground mode. My app use react-native-push-notification and @react-native-community/push-notification-ios

seb-montana commented 4 years ago

Maybe try this plugin : react-native-notifications I realise my configuration is out of this topic based on Firebase.

mikehardy commented 4 years ago

Hm - based on this tutorial I would expect your iOS remote notification handler to receive the push assuming background notifications are enabled and you set content_available to 1 https://www.raywenderlich.com/8164-push-notifications-tutorial-getting-started.

Your configuration is only sort-of off-topic, as the current understanding (which we're looking to confirm) is that FCM has a specific gap on iOS and we're looking for how to recommend people handle it. So I'm interested at least :-)

mikehardy commented 4 years ago

Further research (I do a bit more every time this discussion perks up) indicates it app force-close on Apple may simply be impossible:

However, the system does not automatically launch your app if the user has force-quit it. In that situation, the user must relaunch your app or restart the device before the system attempts to launch your app automatically again.

https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623013-application

If that's the case then I would expect FCM silent push messages to be as robust as any solution if the capabilities, permissions, app listener registration, token handling and message JSON are all lined up correctly, and the app is in any state except force-closed.

seb-montana commented 4 years ago

I'had missed one header in my configuration of my APNs post request, so after add "apns-priority: 5" (in addition to "apns-push-type: background" and "apns-expiration: 0") based on this reply => my app receives notification when it is in background mode. => my app receives notification when it is killed too and app is launched in background by the system without user interaction. So is it ok ?

mstankov commented 4 years ago

I'had missed one header in my configuration of my APNs post request, so after add "apns-priority: 5" (in addition to "apns-push-type: background" and "apns-expiration: 0") based on this reply => my app receives notification when it is in background mode. => my app receives notification when it is killed too and app is launched in background by the system without user interaction. So is it ok ?

Yup, this is great! Thank you!

mikehardy commented 4 years ago

very interesting! perhaps that's why FCM->APNS->Device has a problem vs APNS->Device, I know FCM->APNS translates 'content_available' to 'content-available' but I'm not sure it lets the 'apns-push-type' and 'apns-expiration' stuff through. This seems like the key to the puzzle, thanks again for reporting back @seb-montana - @mstankov have you now tested this and you are saying it works for you as well? Can anyone post the complete JSON they send to APNS plus some simple test script (like using curl or similar) that shows how to post it to the APNS server? I'd love to test it myself but have never posted to anything but FCM

seb-montana commented 4 years ago

that's my shell script (using .pem file - if you prefer use .p8 key, combine this script with this resource) :

shell-apns-send-silent-notification-pem.sh.txt

About headers

mikehardy commented 4 years ago

@seb-montana a pile of internet points for you 😄 🏅 - thank you for those!