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));
}, []);
Related
I am trying to set up deep linking for my IOS app using push notifications and can not get notifications to direct a user to a specific screen on a physical device (downloaded via TestFlight).
React Native: 0.66.4
React Navigation: v6
Current Situation
Test push notifications through AWS Pinpoint work (they are successfully sent to a device), but will redirect a user to the wrong route (the initial route / home screen) of the application even when using a deep link. The deep link I am passing through AWS Pinpoint is in the form 'appName://ScreenName' (without the quotes).
The deep link to the page I want the user to go to works, but not as a push notification. For example, if I open Notes on my phone and type 'appName://ScreenName' and press the link I will be redirected to the deep link in my app. This convinces me that deep linking is set up properly, maybe I am wrong here?
If I hardcode the url scheme I want to use into my app.js file (running in development on a physical device) I am directed to the proper screen.
It appears that deep linking is working but Linking.getInitialURL() is not returning the url scheme from a push notifications. The url scheme works, but not as a push notification, whether the app is running in the background or not.
App.js
const config = {
screens: {
'ScreenName': "ScreenName",
},
}
const linking = {
prefixes: ['https://appName.com', 'appName://'],
config,
};
const handleOpenUrl = (event) => {
if (event && event.url) {
const route = event.url.replace(/.*?:\/\//g, "")
if (route?.includes("setmpin")) {
let { hostname, path, queryParams } = Linking.parse(route)
const params = path.split("/")[1]
const listener = Linking.addEventListener(
"url",
handleURL(path.split("/")[0], params)
)
}
}
}
useEffect(() => {
Linking.getInitialURL().then((url) => {
const supported = Linking.canOpenURL(url)
if (supported) {
Linking.openURL(url)
}
})
Linking.addEventListener("url", handleOpenUrl);
return () => {
Linking.removeAllListeners("url");
};
}, [])
Questions...
Am I missing anything glaring here, I have read several stackoverflow and similar posts and am not sure what I have missed.
Am I right to believe that deep linking is setup properly since I can test deep links in my Notes app or by hardcoding the url scheme in my App.js file?
Is there a way to validate what url is being passed by Pinpoint? I believe this is what is driving the issue but do not know how I can check this since push notifications only work on my physical device in production.
Thanks! Happy to share any additional information as well...
I am building a mobile application using Ionic, and decided to use OneSignal for push notifications. I need to have a user be able to click a push notification (text message) and have the app load to a specific page in the app. I was reading information on deep linking, but it's unclear if it applies to what I'm trying to do. I don't want to load anything in a browser.
For example, I may send a text message that says "A new message is available!" If a user clicks the notification, I want to open the application, and go directly to the specific message.
Does someone have an example or can point to the correct documentation?
i have some views about fcm with ionic 3, hope this will help you
this.fcm.onNotification().subscribe(data => {
if(data.wasTapped){
if(data.location == "StoriesPage"){
this.loading = this.loadCtrl.create({
content:'Loading Stories....',
duration:2000
})
this.loading.present();
this.rootPage = HomePage;
} else if(data.location == 'HomePage'){
this.rootPage = HomePage;
} else if(data.location == 'SubscriptionPage'){
this.rootPage = SubscriptionPage;
}
}
console.log("Received in background");
} else {
console.log("Received in foreground");
};
});
here i sent a location attribute as payload of notification data..if based on that i added rootpage
try to approach the same as per your requirement
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")
I am using push plugin in ionic 3 app, everything is working fine but from my server end we are sending one message at a time and im receiving message to iPhone, but old message should overwrite with new message or once we receive new message then old message is clear automatically..
I'm not able to find anything related to this, please anybody help me to solve this.
const options: PushOptions = {
android: {},
ios: {
alert: 'true',
badge: true,
sound: 'false'
},
windows: {},
browser: {
pushServiceURL: 'http://push.api.phonegap.com/v1/push'
}
};
const pushObject: PushObject = this.push.init(options);
pushObject.on('notification').subscribe((notification: any) =>
console.log('Received a notification', notification));
It sounds like you aren't sending your messages configured to be "collapsible". By default each message will be distinct, not overwriting the last message. FCM documents this well:
https://firebase.google.com/docs/cloud-messaging/concept-options
Non-collapsible and collapsible messages
A non-collapsible message
denotes that each individual message is delivered to the device. A
non-collapsible message delivers some useful content, as opposed to a
collapsible message like a content-free "ping" to the mobile app to
contact the server to fetch data.
...
A collapsible message is a message that may be replaced by a new message if it has yet to be delivered to the device.
...
Or if you are not using FCM, here's a reference to Apple's APN docs directly.
To allow the coalescing of similar notifications, you can include a
collapse identifier within a notification request. Normally, when a
device is online, each notification request that you send to APNs
results in a notification delivered to the device. However, when the
apns-collapse-id key is present in your HTTP/2 request header, APNs
coalesces requests whose value for that key is the same. For example,
a news service that sends the same headline twice could use the same
collapse identifier value for both requests. APNs would then coalesce
the two requests into a single notification for delivery to the
device. For details on the apns-collapse-id key
Update with some code details:
public void sendMessage(String title, String body, Map<String, String> data, boolean shouldCollapse) {
PlatformConfiguration platformConfig = new PlatformConfiguration(30);
if (shouldCollapse)
messageBuilder.setAndroidConfig(platformConfig.getCollapsibleAndroidConfig("test")).setApnsConfig(platformConfig.getCollapsibleApnsConfig("test"));
...
public ApnsConfig getCollapsibleApnsConfig(String collapseKey) {
return getCoreApnsConfig().putHeader("apns-collapse-id", collapseKey)
.setAps(getNonCollapsibleApsBuilder().setCategory(collapseKey).setThreadId(collapseKey).build()).build();
}
public AndroidConfig getCollapsibleAndroidConfig(String collapseKey) {
return getCoreAndroidConfig().setCollapseKey(collapseKey)
.setNotification(
getNonCollapsibleAndroidNotificationBuilder().setTag(collapseKey).build()).build();
}
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;
});