React native ios handle push notification without clicking on notification - ios

I am using react-native 0.60, Firebase push notification. I need help with react native firebase ios push notification with data payload.
I am able to send notifications with data payload. I am able to receive the notification when the app is foreground, background, killed. I am sending data with notification.
{
"to" : "FCM Token",
"show_in_foreground" : "true",
"collapse_key" : "type_a",
"notification" : {
"notification_type" : "N",
"ad_type" : "banner",
"sub_type" : "info",
"text_message" : "Lorem ipsum dolor sit amet",
"Title": "Notification 0000",
"image_url": "https://firebasestorage.com/xyz",
"ad_time" : 7,
"x_time" : 4,
"delay_time" : 4
},
"data" : {
"notification_type" : "N",
"ad_type" : "banner",
"sub_type" : "info",
"text_message" : "Lorem ipsum dolor sit amet",
"Title": "Notification 0000",
"image_url": "https://firebasestorage.googleapis.com/xyz",
"ad_time" : 7,
"x_time" : 4,
"delay_time" : 4
},
"content-available" : true,
"priority": "high"
}
I want to show notification and also store data in local app database at the same time even if the user doesn't click on the notification.
I am able to handle the notification when user clicks on the notification. I want to update the data in the app when the notification is received by the user and also show the notification. I dont want to use silent background notification.
My Appdelegate code
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler{
if ([[FIRAuth auth] canHandleNotification:userInfo]) {
completionHandler(UIBackgroundFetchResultNoData);
return;
}
[[FIRMessaging messaging] appDidReceiveMessage:userInfo];
[[RNFirebaseNotifications instance] didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
NSLog(#"Inactive - the user has tapped in the notification when app was closed or in background 3");
}
I want to achieve
1. User should get the notification even if the app is closed, killed, background.
2. User's App local Database should be updated even if user doesnt click on the notification.
I have achieved the first point looking for 2nd. I am new to react native. I know that when the notification is received the completion handler method is called. when the app is killed nothing is showed in the xcode log. how do i write code in completion handler method ? and how do i check if the method is called and task is performed.

messaging().onNotificationOpenedApp(remoteMessage => {
console.log(
'Notification caused app to open from background state:',
remoteMessage.notification,
);
navigation.navigate(remoteMessage.data.type);
});
// Check whether an initial notification is available
// This will handle notification when App is opened from killed state or background
messaging()
.getInitialNotification()
.then(remoteMessage => {
if (remoteMessage) {
console.log(
'Notification caused app to open from quit state:',
remoteMessage.notification,
);
setInitialRoute(remoteMessage.data.type); // e.g. "Settings"
}
setLoading(false);
});
Use this notification listeners
2nd thing React-Native Does not can not manage kill state for Application. Because when Application is killed, js engine shuts down.
3rd: v6 lib does not support badge count updating like v5 did. So When there are notification and When User Directly Open Application all notification should be cleared,
So that can be done from Native Side
For Android -> MainActivity.java
#Override
protected void onResume() {
super.onResume();
// Clear all notification
NotificationManager nMgr = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
nMgr.cancelAll();
}
So This Will Clear All Notification From StatusBar, LockScreen, whenever app is opened whether directly or from Notification Press. But still do this if requirement is this.
On more thing Android manages badge count and update automatically, but for iOS Native Code implementation must. in AppDelegate file.
Most common mistake seen : remoteMessage.notification and remoteMessage.data both are different, console whole remoteMessage object :)))

So, in iOS currently, there are no background services that could be run on the background as we have it on Android. So, from my perspective, you can't check were notification shown or not to the user in realtime if the app was killed. I can't understand why you need that. Notifications act pretty much correctly, so, you don't need to check iOS is it works.
What you can do is collect information about notifications after your app restarts.

messaging().onNotificationOpenedApp(remoteMessage => {
console.log(
'Notification caused app to open from background state:',
remoteMessage.notification,
);
YOUR_NAVIGATION_PATH_HERE;
});
SOURCE : https://rnfirebase.io/messaging/notifications

Related

Add deep link when creating Firebase message

I'm using the firebase Message class to create push notifications for a react native app. I want the notification to take users to a specific screen of the app. Right now tapping on the push notification just takes users to the last screen they were on before they back-grounded the app. I'm testing this on my iOS device. How can I embed a specific deep link in the message? Would I use setApnsConfig(ApnsConfig apnsConfig) or setFcmOptions(FcmOptions fcmOptions)?
I would use the APNS config since this is for an iOS app:
https://firebase.google.com/docs/reference/admin/java/reference/com/google/firebase/messaging/ApnsConfig.Builder
You could approach it different ways, but you could either include a URL in the header field, and use it for custom deep link logic, or you can have custom data in the putCustomData(String key, Object value) and then have your app process that info to deep link into the correct part of your app.
Your app would process this notification in the application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623013-application
I had integrated this feature in an app I made in react native aswell. Look at my solution below.
As you can see in the app I am waiting for a notification to come on and I check if it has a type available. My notifications are always routed to another page. In my case its the same page but I set a route as datatype in my payload.
After that you can use that route payload with your naviogator library in my case react-navigation to navigate to the correct screen.
You should chose which trigger works best for you ether onNotificationOpenedApp or getInitialNotification.
useEffect(() => {
// Assume a message-notification contains a "type" property in the data payload of the screen to open
messaging().onNotificationOpenedApp((remoteMessage) => {
console.log(
"Notification caused app to open from background state:",
remoteMessage
);
//navigation.navigate(remoteMessage.data.type);
});
// Check whether an initial notification is available
messaging()
.getInitialNotification()
.then((remoteMessage) => {
if (remoteMessage) {
console.log(
"Notification caused app to open from quit state:",
remoteMessage
);
const route = remoteMessage?.data?.route;
navigation.navigate(route, {
data: remoteMessage.data,
});
}
})
.catch((error) => console.log("Caught ", error));
}, []);

Test OneSignal Push Notification on iOS Simulator

I've set up react-native-onesignal on my project to implement Push Notification using OneSignal.
It is possible to test Push Notification on iOS simulators since Xcode 11.4 Beta. I created JSON formatted apns file to test Push Notification on Simulator and it worked very well.
But how can I emulate OneSignal Push Notification?
I followed OneSignal Documentation and want to receive Push Notification which is sent from OneSignal Dashboard.
Here's what I've implemented on my App.tsx file.
const initializeOneSignal = () => {
OneSignal.setLogLevel(6, 0);
OneSignal.init("MY_ONESIGNAL_APP_ID", {
kOSSettingsKeyAutoPrompt: false,
kOSSettingsKeyInAppLaunchURL: false,
kOSSettingsKeyInFocusDisplayOption: 2,
});
OneSignal.inFocusDisplaying(2);
OneSignal.promptForPushNotificationsWithUserResponse(myiOSPromptCallback);
OneSignal.addEventListener('received', onPNReceived);
OneSignal.addEventListener('opened', onPNOpened);
OneSignal.addEventListener('ids', onPNIds);
};
useEffect(() => {
initializeOneSignal();
return () => {
OneSignal.removeEventListener('received', onPNReceived);
OneSignal.removeEventListener('opened', onPNOpened);
OneSignal.removeEventListener('ids', onPNIds);
};
}, []);
const onPNReceived = notification => {
console.log('Notification received: ', notification);
};
const onPNOpened = openResult => {
console.log('Message: ', openResult.notification.payload.body);
console.log('Data: ', openResult.notification.payload.additionalData);
console.log('isActive: ', openResult.notification.isAppInFocus);
console.log('openResult: ', openResult);
};
const onPNIds = device => {
console.log('Device info: ', device);
};
const myiOSPromptCallback = permissions => {
console.log('Permissions: ', permissions);
};
I cannot see any logged message when I sent Push Notification from my OneSignal Dashboard.
Do I need to do any trick in apns file?
Any help would be appreciated.
tl;dr you can't send a real notification to a simulator. You can only send mocked notifications to a simulator
Your server is oblivious of a simulator, because simulators don't have device tokens. Apple decided not to give it one. I suppose this was so users can't fake their device token and get notifications on their simulator...
The 11.4 simply allows the drag and drop of a APNs payload into the simulator without any mention of device token.
You can check out this article on Medium enter link description here.
This article helped me test oneSignal push notifications on my iOS simulator and figure out the deep linking issue.
Here are my steps:
Create a payload.apns file on your desktop
Put the following code inside it:
{
"Simulator Target Bundle": "com.example.app",
"aps": {
"alert": {
"title": "Push Notification",
"subtitle": "Test Push Notifications",
"body": "Testing Push Notifications on iOS Simulator",
}
},
"custom": {
"i": "notificationId as UUID",
"a": {"deeplinkKey": "{\"deeplinkDetailKey\":\"deeplinkDetailValue\"}", "launchURL": "example://collection/myCollectionId/type/1"}
}
}
Remember to replace com.example.app with your app bundle ID.
Run your app on the simulator, then close the app and keep metro open
Drag and drop payload.apns file on the simulator, you will see the notification to click on it. If you have done the 3rd step right, you should be redirected to your app
(Optional) If you need to test a deep link with the push notification, I haven't yet found the key oneSignal uses, but as you see in the .apns file above, I added a launchURL to the a which represents additionalData and handled catching and opening it manually in the app to test what's wrong with the deep link.
(Optional) To open a deep link in your app, you can use Linking API from react-native:
import {Linking} from 'react-native'
Linking.openURL("Path/to/launchURL")

How can I set notification sound when app is not running in React-Native firebase

I'm trying to make notification ringing when app is not running in IOS.
Here is my code.
this.notificationListener = firebase.notifications().onNotification((notification: Notification) => {
// SET SYSTEM DEFAULT SOUND!
notification.setSound("default");
firebase.notifications().displayNotification(notification);
});
When app is in background or foreground ( Maybe I can say 'app is running'), notification rings well.
Should I need to use other listener?
Or should I need to add my own sound file for ringing?
Finally, I know how to do this.
This issue was not related to react-native-firebase, it was related to my server.
When server post message to app, server can set several options like sound, badge.
https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingwithAPNs.html#//apple_ref/doc/uid/TP40008194-CH11-SW1
If you set sound section to 'default', you can get default notification sound when notification is coming even if your app is on background.
I hope my answer can help react-native-firebase beginners like me.
Anyone Has issue with RNFIREBASE & REACT NATIVE, Try to send your notification via Firebase ADMIN SDK. That will work for Sure
//Notification Payload
const payload = {
notification: {
title: update.title,
body: update.body,
icon: "default",
badge: '1',
sound: 'default' // notification sound
},
};
//sending notification via Firebase Admin SDK
admin.messaging().sendToDevice('TOKEN_OR_TOKENS', payload)
.then( () => { return true; }).catch(function() {
console.log('error sendToDevice() ')
return null;
});

IOS Push Notification count

I need to display push notification count. when user launches the application by tapping application or from notification bar.
Example: application is in background and device received 10 notifications related to my app. we have to display notification count 10 within app.
I can achieve this by adding content-update key in notification payload. But I don't want to make change in notification payload.
Your backend need to send bagdes for this :- Eaxmple
{
"aps" : {
"alert" : "You got your emails.",
"badge" : 9,
"sound" : "bingbong.aiff"
},
"acme1" : "bar",
"acme2" : 42
}
and you can use this badges in your apps.
You can check how many notifications were received (assuming you are incrementing badges in your push notifications) by checking [UIApplication sharedApplication].applicationIconBadgeNumber.
This also assumed you reset the badge count each time they leave the app (standard practice), if for some reason you don't though, simply save [via NSUserDefaults] the current badge count in the willResignActive callback and check the delta when they return.

How to set sound for push notifications in ios objective c?

I am working on an app in which I have implemented Apple push notifications. When my app is in background state then I am able to receive push notifications without sound but when my app is in active state then I am able to get sound for notifications but not showing any banner for it.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
UIApplicationState state = [application applicationState];
if (state == UIApplicationStateInactive)
{
AudioServicesPlaySystemSound(1007);
}
else {
AudioServicesPlaySystemSound(1007);
carPlateNo = [userInfo valueForKeyPath:#"aps.alert.loc-args"];
if(![carPlateNo isEqualToString:#"Return Message"])
{
[self receiveServices];
}
// Push Notification received in the background
}
}
Can anyone help on this?
You have to set sound in APNS Payload only, and add sound clip in XCode bundle.
Sample Payload
{
"aps" : {
"alert" : "You got your emails.",
"badge" : 9,
"sound" : "bingbong.aiff"
},
"acme1" : "bar",
"acme2" : 42
}
More Info
Try This :
when you send push notification, just add the name of sound in JSON payload. Example:
{
"aps" : {
"alert" : "your alert message here.",
"badge" : 1,
"sound" : "samplemusic.aiff"
}
}
Thats it! You don't have to do anything special in code of app.
iOS takes care of delivering notification to app when app is killed. iOS also takes care of showing the banner/alert depending on user settings and also plays the audio for the notification.
What you can do though is specify what audio to play in your notification payload
{
"aps" : {
"alert" : "You got your emails.",
"badge" : 9,
"sound" : "bingbong.aiff"
},
"acme1" : "bar",
"acme2" : 42
}
If you don't want default notification sound you can bundle your own audio file of format .aiff and ship it with app and specify the file name in your notification payload as shown above
refer : https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html
As far as
when my app is in active state then I am able to get sound for
notifications but not showing any banner for it
concerned, when your app is in foreground its your app's responsibility to show any custom banner/alert. System default banner/alert will not be displayed. You can use https://github.com/sandeeplearner/SBNotificationBar for the same :)
- When my app is in background state then I am able to receive push
notifications without sound
There must be one the following two issues
1.Sound key is not there or sending empty value for it in payload (Reference)
2.Your phone in silent mode
- my app is in active state then I am able to get sound for notifications but not showing any banner for it.
When Application is active app is responsible to handle what to do on push notification receive for more please refer this answer

Resources