ios
ios copied to clipboard
iOS Background Notification Not Working
Bug report
Summary
I am trying to acheive Push Notifications for both Android & iOS (Foreground & Background). I followed the official firebase docs and was able to run it correctly on Android in all app states. Foreground, Background & Quit it works
But the same thing is only working in Foreground for IOS.
In background what i want is push notification from RestApi. And on foreground I am showing a LocalNotification which is working fine.
No Matter what I do it doesnot trigger the messaging().setBackgroundMessageHandler(async remoteMessage => {console.log('Message handled in the background!', remoteMessage);});
Environment info
react-native info output:
System:
OS: Windows 10 10.0.18363
CPU: (8) x64 Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz
Memory: 2.67 GB / 11.88 GB
Binaries:
Node: 12.16.1 - C:\Program Files\nodejs\node.EXE
Yarn: 1.21.1 - C:\Program Files (x86)\Yarn\bin\yarn.CMD
npm: 6.13.4 - C:\Program Files\nodejs\npm.CMD
Watchman: Not Found
SDKs:
Android SDK:
API Levels: 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27, 28, 29
Build Tools: 24.0.2, 25.0.3, 26.0.1, 26.0.2, 28.0.2, 28.0.3, 29.0.0, 29.0.2
System Images: android-19 | Google APIs Intel x86 Atom, android-27 | Google APIs Intel x86 Atom, android-27 | Google Play Intel x86 Atom, android-28 | Google APIs Intel x86 Atom, android-28 | Google Play Int
el x86 Atom, android-29 | Google APIs Intel x86 Atom
Android NDK: Not Found
IDEs:
Android Studio: Version 3.5.0.0 AI-191.8026.42.35.6010548
Languages:
Java: 1.8.0_211 - C:\Program Files\Java\jdk1.8.0_211\bin\javac.EXE
Python: 2.7.17 - C:\Python27\python.EXE
npmPackages:
@react-native-community/cli: Not Found
react: 16.11.0 => 16.11.0
react-native: 0.62.2 => 0.62.2
npmGlobalPackages:
*react-native*: Not Found
`Package.json'
{
"name": "ABCAPP",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint ."
},
"dependencies": {
"@react-native-community/masked-view": "0.1.5",
"@react-native-community/push-notification-ios": "^1.2.2",
"@react-native-firebase/app": "^7.2.1",
"@react-native-firebase/iid": "^7.1.4",
"@react-native-firebase/messaging": "^7.1.5",
"@react-navigation/drawer": "^5.1.1",
"@react-navigation/material-bottom-tabs": "^5.1.6",
"@react-navigation/native": "5.2.1",
"@react-navigation/stack": "5.2.16",
"axios": "^0.19.2",
"expo-font": "^8.1.1",
"native-base": "2.13.8",
"react": "16.11.0",
"react-dom": "~16.9.0",
"react-native": "0.62.2",
"react-native-gesture-handler": "~1.5.0",
"react-native-notifications": "^3.2.2",
"react-native-reanimated": "~1.4.0",
"react-native-safe-area-context": "0.6.0",
"react-native-screens": "2.0.0-alpha.12",
"react-native-unimodules": "^0.9.1",
"react-native-vector-icons": "^6.6.0",
"react-native-web": "~0.11.7",
"react-redux": "^7.2.0",
"redux": "^4.0.5",
"redux-logger": "^3.0.6",
"redux-persist": "^6.0.0",
"redux-saga": "^1.1.3"
},
"devDependencies": {
"@babel/core": "^7.6.2",
"@babel/runtime": "^7.6.2",
"@react-native-community/eslint-config": "^0.0.5",
"babel-jest": "^24.9.0",
"eslint": "^6.5.1",
"jest": "^24.9.0",
"metro-react-native-babel-preset": "^0.58.0",
"react-test-renderer": "16.11.0"
},
"jest": {
"preset": "react-native"
}
}
Reproducible sample code
import React, {useEffect, useState} from 'react';
import {Provider} from 'react-redux';
import {createStore, applyMiddleware, compose} from 'redux';
import logger from 'redux-logger';
import createSagaMiddleware from 'redux-saga';
import AllSagas from './js/sagas';
import {persistStore, persistReducer} from 'redux-persist';
import {AsyncStorage, View, Image , Platform } from 'react-native';
import {PersistGate} from 'redux-persist/integration/react';
import reducer from './js/reducers';
import RootNavigator from './js/navigators/RootNavigator';
import messaging, {AuthorizationStatus} from '@react-native-firebase/messaging';
import {firebase} from '@react-native-firebase/iid';
import {Alert} from 'react-native';
import {Notifications} from 'react-native-notifications';
import PushNotificationIOS from "@react-native-community/push-notification-ios";
const persistConfig = {
key: 'root',
storage: AsyncStorage,
};
const persistedReducer = persistReducer(persistConfig, reducer);
let sagaMiddleware = createSagaMiddleware();
const middleware = [sagaMiddleware];
function configureStore(initialState) {
const enhancer = compose(applyMiddleware(...middleware, logger));
return createStore(persistedReducer, initialState, enhancer);
}
const store = configureStore({});
sagaMiddleware.run(AllSagas);
const persistor = persistStore(store);
// Uncomment in case you want to delete state from persistant storage.
// persistor.purge();
export default App = () => {
const [isReady, setisReady] = useState(false);
requestUserPermission();
getMyToken();
// Foreground Notification Listener;
useEffect(() => {
const unsubscribe = messaging().onMessage(async remoteMessage => {
// Alert.alert('A new FCM message arrived!', JSON.stringify(remoteMessage));
const { title , body } = remoteMessage.data;
if(Platform.OS === 'android'){
Notifications.postLocalNotification({
body: body,
title: title,
sound: 'default',
silent: false,
category: 'SOME_CATEGORY',
userInfo: {},
'google.message_id': '',
payload: {
body: body,
title: title,
sound: 'default',
silent: false,
category: 'SOME_CATEGORY',
'google.message_id': '',
},
});
}else if(Platform.OS==='ios'){
PushNotificationIOS.presentLocalNotification({
alertTitle: title,
alertBody: body
});
}
});
return unsubscribe;
},[]);
setTimeout(() => {
setisReady(true);
}, 3500);
if (!isReady) {
return (
<View style={{flex: 1}}>
<Image
source={require('./assets/images/gif_splash.gif')}
resizeMethod="auto"
resizeMode="cover"
style={{width: '100%', height: '100%'}}
/>
</View>
);
}
return (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<RootNavigator/>
</PersistGate>
</Provider>
);
};
async function requestUserPermission() {
const authStatus = await messaging().requestPermission({
alert: true,
announcement: false,
badge: true,
carPlay: true,
provisional: false,
sound: true,
});
const enabled =
authStatus === AuthorizationStatus.AUTHORIZED ||
authStatus === AuthorizationStatus.PROVISIONAL;
if (enabled) {
console.log('Authorization status:', authStatus);
}
}
const getMyToken = async () => {
const alarmFcmToken = await firebase.messaging().getToken(
firebase.app().options.messagingSenderId, // default to this app
'FCM',
); // defaults to 'FCM');
console.log('TOOOOOOOOOOOOOOKEEEEEEEEEEEN');
console.log(alarmFcmToken);
};
/**
* @format
*/
import React from 'react';
import {AppRegistry, Platform} from 'react-native';
import {Alert} from 'react-native';
import messaging from '@react-native-firebase/messaging';
import {Notifications} from 'react-native-notifications';
import App from './App';
import {name as appName} from './app.json';
// Register background handler
messaging().setBackgroundMessageHandler(async remoteMessage => {
console.log('Message handled in the background!', remoteMessage);
});
function HeadlessCheck({ isHeadless }) {
if (isHeadless) {
// App has been launched in the background by iOS, ignore
return null;
}
return <App />;
}
AppRegistry.registerComponent(appName, () => HeadlessCheck);
#import <React/RCTBridgeDelegate.h>
#import <UserNotifications/UNUserNotificationCenter.h>
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate, UNUserNotificationCenterDelegate>
@property (nonatomic, strong) UIWindow *window;
@end
#import "AppDelegate.h"
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#if DEBUG
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>
#import <RNCPushNotificationIOS.h>
#import <UserNotifications/UNUserNotificationCenter.h>
#import <Firebase.h>
static void InitializeFlipper(UIApplication *application) {
FlipperClient *client = [FlipperClient sharedClient];
SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
[client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
[client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
[client addPlugin:[FlipperKitReactPlugin new]];
[client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
[client start];
}
#endif
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#if DEBUG
InitializeFlipper(application);
#endif
// Start I added
[FIRApp configure];
if ([UNUserNotificationCenter class] != nil) {
// iOS 10 or later
// For iOS 10 display notification (sent via APNS)
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert |
UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
[[UNUserNotificationCenter currentNotificationCenter]
requestAuthorizationWithOptions:authOptions
completionHandler:^(BOOL granted, NSError * _Nullable error) {
// ...
}];
} else {
// iOS 10 notifications aren't available; fall back to iOS 8-9 notifications.
UIUserNotificationType allNotificationTypes =
(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
UIUserNotificationSettings *settings =
[UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
[application registerUserNotificationSettings:settings];
}
[application registerForRemoteNotifications];
[FIRMessaging messaging].delegate = self;
[[FIRInstanceID instanceID] instanceIDWithHandler:^(FIRInstanceIDResult * _Nullable result,
NSError * _Nullable error) {
if (error != nil) {
NSLog(@"Error fetching remote instance ID: %@", error);
} else {
NSLog(@"Remote instance ID token: %@", result.token);
}
}];
[FIRMessaging messaging].autoInitEnabled = YES;
// End I added
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:@"HomeMediCare"
initialProperties:nil];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
}
// Start I added
- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken {
NSLog(@"FCM registration token: %@", fcmToken);
// Notify about received token.
NSDictionary *dataDict = [NSDictionary dictionaryWithObject:fcmToken forKey:@"token"];
[[NSNotificationCenter defaultCenter] postNotificationName:
@"FCMToken" object:nil userInfo:dataDict];
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[FIRMessaging messaging].APNSToken = deviceToken;
[RNCPushNotificationIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
[RNCPushNotificationIOS didRegisterUserNotificationSettings:notificationSettings];
}
// Required for the notification event. You must call the completion handler after handling the remote notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
[[FIRMessaging messaging] appDidReceiveMessage:userInfo];
[RNCPushNotificationIOS didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
// Required for the registrationError event.
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
[RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error];
}
// Required for the localNotification event.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
[RNCPushNotificationIOS didReceiveLocalNotification:notification];
}
// Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
NSDictionary *userInfo = notification.request.content.userInfo;
[[FIRMessaging messaging] appDidReceiveMessage:userInfo];
completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge);
}
// End I added
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}
@end
Library version: ^1.2.2 iOS: 13.4.1
Experiencing this also. No background notification being sent when soft-closing the app.
same issue with me and the same version of Firebase V7
Is this module compatible with react native firebase cloud messaging ?
Same for me :/ not working. Any solution?
I can vouch iOS isn't working for me either, I have been stuck with debugging for like 2 days now
still same? i am also having the same issue.
Actually whenever I’m switching current application to any other apps, local notification is not working but when I back to current application, It works. I want local notifications to be work in any scenario, within the application and also while I’m switching to other application. Please Help.... here's the lib and version in my app: "@react-native-community/push-notification-ios": "^1.5.0", "react-native-push-notification": "^5.1.1", "react": "16.11.0", "react-native": "0.62.2",
I have local notification issue in iOS => local notification working fine in android for foreground & background, also local notification click event work but In Case of iOS local notification work in only foreground, not in background, also not working click event of notification. I need perfect solution for local notification working fine both iOS & Android, and also working their click event. Help...
Facing the same issue with the basic setup, when the app is in the foreground everything works fine, both presentLocalNotification and scheduleLocalNotification, however once I schedule a local notification and soft close the app nothing happens.
I'm facing the same issue receiving notifications on Android either in background or foreground, On iOS getting notifications in the foreground but not in background
the same issue
My issue turned out to be I was generating the ID myself a 32 bit unsigned integer, but somehow it was not correct it was overflowing, after I changed to generate a 31 bit integer, everything started working in a stable manner
same issue, i used firebase react native messaging and onmessage also called, but with ios nothing comes out. even app is closed. i used react-native-push-notification @react-native-community/push-notification-ios @react-native-firebase/messaging.
Still no solution?
I was able to just use the react-native-firebase latest without this push notification library.
Please make sure you send the data correctly in order to trigger the notification.
At my side, I have used the following format:
{ "to": "TOKEN", "data":{ "title":"Some title", "message":"Some text", "vibrate":1, "sound":1, "channelId": "TEST" }, "notification": {. <-- Trigger notification "title":"Some title", "body":"Some text", "sound": "default" }, "content_available":true, <-- Trigger notification required for IOS "priority":"high" }
setBackgroundMessageHandler just handle the message once the app opens due to the notification. It does not trigger when notification is received.
Facing the same issue... When the app is killed(removed from the background) on notification gets triggered after receiveing a notification, but when app is in the background nothing happens.
Still not working guys ? I have the same problem...
Just an FYI as this is pretty difficult to debug due to the way messaging works and the fact you will get different message/system behaviour depending on the message structure.
Below works fairly consistently
Note that i don't have a data object.
{
"to": "{{myID}}",
"notification": {
"title": "Working Good",
"body": "backgroudn noti",
"badge": "1"
},
"priority": "high",
"badge": "1",
"content_available": true
}
Definitely doesn't trigger background notifications.
Doesn't contain the priority, badge, and content_available properties. This was my original message structure.
{
"to": "myID",
"notification": {
"title": "payload.title1",
"body": "payload.body"
},
"data": {
"link": "payload.link"
},
"apns": {
"payload": {
"aps": {
"mutable-content": 1
}
}
}
}
Might trigger background notifications and badge count. But not always I'm still debuggin issues myself, and i'm actually using a different notification package, but this was such a nightmare, that i fellt the need to share.
Note, that here i have the priority fields and both a notification and data block, i've read in other posts for react native that if you have a notification "AND" a data block that firebase messagings setbackgroundhandler won't trigger. if your using that. But haven't confirmed that yet.
{
"to": "myID",
"notification": {
"title": "payload.title",
"body": "payload.body"
},
"data": {
"link": "payload.link"
},
"apns": {
"payload": {
"aps": {
"mutable-content": 1
}
}
},
"priority":"high",
"badge":"1",
"content_available":true
}
Anyway, my advice if this is a poblem, is to setup postman or some test endpoints with all the possible combinations of message.
@emileswain you just saved my day