I'm working with react native and firebase 6 to send push notifications.
I use the official documentations of the new version :
https://invertase.io/oss/react-native-firebase/v6
I add native code for both android and ios to handle sending and receiving notifications
In my AndroidManifest.xml :
<!-- [START firebase_service] -->
<service
android:name=".java.MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<!-- [END firebase_service] -->
I did not create the MyFirebaseMessagingService .
I AppDelegate.m i add some functions :
// Required for the register event.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
[FIRMessaging messaging].APNSToken = deviceToken;
[RNCPushNotificationIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
NSLog(#"APNs device token retrieved: %#", deviceToken);
}
// Required for the registrationError event.
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
[RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error];
NSLog(#"Unable to register for remote notifications: %#", error);
}
// Required for the localNotification event.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
[RNCPushNotificationIOS didReceiveLocalNotification:notification];
}
In my Component.js i get the token like this :
// Firebase
import firebase from '#react-native-firebase/app'
import messaging from '#react-native-firebase/messaging'
// ----- COMPONENT DID MOUNT ---- //
async componentDidMount () {
// ====================================================== //
// ====================================================== //
// ====================================================== //
const granted = messaging().requestPermission()
if (granted) {
console.log('User granted messaging permissions!')
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
firebase
.messaging()
.getToken()
.then(fcmToken => {
if (fcmToken) {
// user has a device token
console.log('-------- FCM TOKEN -------')
console.log(fcmToken)
console.log(JSON.stringify(fcmToken))
this._setItem(fcmToken)
} else {
// user doesn't have a device token yet
console.log('error')
}
})
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
} else {
console.log('User declined messaging permissions :(')
}
// ====================================================== //
// ====================================================== //
// ====================================================== //
}
// ----- FIN COMPONENT DID MOUNT ---- //
I send POST request to https://fcm.googleapis.com/fcm/send :
{
"to" : "token",
"notification" : {
"body" : "un nouveau partage",
"title" : "un partage de contact reçu",
"priority" : "high",
"vibration":true,
"sound": "Enabled",
"badge":1,
"requireInteraction": true,
"click_action": "fcm.ACTION.HELLO"
},
"data" : {
"body" : "nouvelle opportunité",
"title" : "un nouveau partage",
"content_available" : true,
"priority" : "high"
}
}
I receive the notification for both android and ios but i can't handle the click action :
I want to redirect to specific route when the user click on the notification .
I haven't used Firebase for notifications, but as you're saying the notifications are working, then the actual issue it seems to me is you want to handle it when your app opens.
So here are the steps you have to follow to get your work done.
Get the data coming in the notification, on the event onNotificationOpened. Check out this link to check if you're getting the notification data.
Next, you want to a specific route on the basis of notification. What I do is, send the type of the screen and id related to that screen to navigate there, ex:
{
"entity": "Place",
"id": "123"
}
So, when I receive the notification, I send the data to a switch case factory that navigate to the screen on the basis of info in that data. Something like that.
function navigateToScreen(entity:string, id:string){
let screenName = "";
let params = {}
switch(entity){
case "Place":
screenName = "placeScreen";
params = {id};
break;
default: return;
}
// Navigation Service = https://reactnavigation.org/docs/navigating-without-navigation-prop/
NavigationService.navigate(screenName, params);
}
Now in case you want to run a specific function on the basis of notification, you can do it on the basis of info received. Like in this example I have to make an API req to get the data of that place by id.
const id = props.match.params['id'];
useEffect(() => {
getThePlaceDetails(id);
}, [id]);
Related
In my Angular 13 Ionic 6 app I'm using the capacitor/push-notifications with FireBase,
In my service:
import { EventEmitter, Injectable, Output } from '#angular/core';
import {ActionPerformed, PushNotifications, PushNotificationSchema, Token} from '#capacitor/push-notifications';
import { Capacitor } from '#capacitor/core';
import { Dialogs, DialogType } from '../Utilities/dialogs';
import { get, set, remove } from './storage.service';
import { BehaviorSubject } from 'rxjs';
import { App } from '#capacitor/app';
//https://devdactic.com/push-notifications-ionic-capacitor/
#Injectable({
providedIn: 'root'
})
export class FbNotificationsService {
onFCMTokenChanged: BehaviorSubject<string> = new BehaviorSubject('');
tokenProcessed: boolean = false;
constructor(private dialogs: Dialogs) {
}
initPush() {
if (Capacitor.getPlatform() !== 'web') {
this.registerPush()
} else {
console.log('Web platform detected');
this.onFCMTokenChanged.next('web-platform');
}
}
private registerPush() {
PushNotifications.requestPermissions().then((permission) => {
if (permission.receive === 'granted') {
// Register with Apple / Google to receive push via APNS/FCM
console.log('FB Permission granted');
PushNotifications.register(); //Registers app to receive notifications
} else {
// No permission for push granted by user on iOS
console.log('FB NO permissions granted');
}
});
PushNotifications.addListener(
'registration',
(token: Token) => {
if ((token)&&(!this.tokenProcessed)) {
this.tokenProcessed = true;
console.log('My token: ' + JSON.stringify(token));
this.onFCMTokenChanged.next(token.value);
set('device-token', token.value);
}
});
PushNotifications.addListener('registrationError', (error: any) => {
console.log('Registration Error: ' + JSON.stringify(error));
this.dialogs.dialogClose('Network Error','The network signal is not sufficient at this time. Please improve connection and try again');
App.exitApp();
});
PushNotifications.addListener(
'pushNotificationReceived',
async (notification: PushNotificationSchema) => {
console.log('Push received: ' + JSON.stringify(notification));
alert('Push received: ' + JSON.stringify(notification));
//What to do next. Notification received on the device.
}
);
PushNotifications.addListener(
'pushNotificationActionPerformed',
async (notification: ActionPerformed) => {
const data = notification.notification.data;
console.log('Action performed: ' + JSON.stringify(notification.notification));
alert('Push action performed: ' + JSON.stringify(notification));
//What to do next. data holds all payload fields of the notification object
}
);
}
}
The basic guide I followed is here.
When I send a test message from the Firebase console, the alert statement I placed is poping up, meaning, the message is received by the app:
alert('Push received: ' + JSON.stringify(notification)); //WORKING
HOWEVER, there is no notification message popping up by the OS for the user to see. I do get notifications all the time from Whatapp, Emails, etc, and the "Do not disturb" setting is turned off.
This is experienced with TWO Android devices: Xiaomi Rednote 8 and Samsung Galaxy A32.
Am I missing something?
I had a similar problem before, maybe the following information could help you:
When your Android app is in the foreground, PushNotifications won't appear on the screen.
If you absolutely want a visual display of the notification, you can create a local notification when the push notification is received.
How to skip/open a specific screen based notification. Example: When a user clicks on the notification, the application should open and go directly to the notifications page instead of the home page.
when i was using react-native-push-notification i mannage to get the text of my notification this way :
componentWillMount() {
var _this = this;
PushNotification.configure({
onRegister: function(token) {
_this.props.InitToken(token.token);
},
onNotification: function(notification) {
setTimeout(() => {
if(!notification['foreground']){
_this.props.InitNotif(notification['message']);
}
}, 1);
PushNotification.localNotificationSchedule({
title: 'Notification with my name',
message: notification['name'], // (required)
date: new Date(Date.now()) // in 60 secs
});
},
// ANDROID ONLY: GCM Sender ID (optional - not required for local notifications, but is need to receive remote push notifications)
senderID: "YourID",
});
}
where
_this.props.InitToken(token.token);
and
_this.props.InitNotif(notification['message']);
are redux based function that update your state with the notification token and message. When you'r state is updated whith the notification message your can change route ou display the message on screen.
PS:
i dont know if it was the good way but i was working
componentWillMount() is depreciated.
I'm sending push notifications from server to clients via google FCM.
In the react-native app I've registered these listeners:
this.notificationOpenedListener = firebase.notifications().onNotificationOpened(async (notificationOpen) => {
})
this.notificationListener = firebase.notifications().onNotification(async (notification) => {
});
the notification data contains information if there should be a sound / vibration or not when the notification is received.
However, I can't find any documentation about completely disabling sound/vibration on demand.
How can I achieve this?
UPDATE
I've tried setting sound to an empty string on server side, but there's still sound/vibration on notification.
var message = {
data: {
userId: fromUserId,
},
notification: {
title: `My notifcation`,
body: `Body`,
sound: "",
},
}
return sendToTopic(topicId, message)
When setting your notification target, remove sound parameter.
const notify = {
...message.notification,
show_in_foreground: true,
notify_type: message.NotificationType,
obj_id: message.ObjectId,
sound: '' // remove this
};
firebase.messaging().createLocalNotification(notify);
I'm not sure how you are setting up your Push notifications but you can tag extra data into the JSON like this:
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"data":{
"Nick" : "Mario",
"body" : "great match!",
"Room" : "PortugalVSDenmark"
}
}
}
This means you could add a boolean to it to manually play a tone on arrival or not play a tone when the subscription fires, like this:
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"data":{
"Nick" : "Mario",
"body" : "great match!",
"Room" : "PortugalVSDenmark",
"playTone" : "true"
}
}
}
Then it's the case of having a check in your callback to check the response:
this.notificationListener = firebase.notifications().onNotification(async (notification) => {
if(notification.data.playtone) {
// Play Tone
} else {
// Don't
}
});
In general though push notifications are handled by the OS and not the application, you can hook into it like you have and perform actions on the arrival of a push notification but normally they all arrive in the same "Drop everything and deal with me" style.
Both Android and Apple do support priority but it might not be what you're after:
https://firebase.google.com/docs/cloud-messaging/concept-options#setting-the-priority-of-a-message
I am using Ionic 2, and am trying to get Push Notifications working.
I have registered my app with Firebase, and can push notifications to it successfully.
I now need to set up, so that I can push notifications from my app. So I decided to use the following Cordova Plugin (cordova-plugin-fcm).
Question 1
When I follow it's instructions, by doing the following in my Ionic app:
app.ts
declare var FCMPlugin;
...
initializeApp() {
this.platform.ready().then(() => {
...
FCMPlugin.getToken(
function (token) {
....
I get the following Error at runtime:
EXCEPTION: Error: Uncaught (in promise): ReferenceError: FCMPlugin is
not defined
How do I solve this please?
Question 2
In order to send notifications from your app, the Cordova Plugin (cordova-plugin-fcm) instructs the following:
//POST: https://fcm.googleapis.com/fcm/send
//HEADER: Content-Type: application/json
//HEADER: Authorization: key=AIzaSy*******************
{
"notification":{
"title":"Notification title", //Any value
"body":"Notification body", //Any value
"sound":"default", //If you want notification sound
"click_action":"FCM_PLUGIN_ACTIVITY", //Must be present for Android
"icon":"fcm_push_icon" //White icon Android resource
},
"data":{
"param1":"value1", //Any data to be retrieved in the notification callback
"param2":"value2"
},
"to":"/topics/topicExample", //Topic or single device
"priority":"high", //If not set, notification won't be delivered on completely closed iOS app
"restricted_package_name":"" //Optional. Set for application filtering
}
This is not even Typescript or Javascript. So where does it go? I just don't understand. Any advise appreciated.
You should have FCMPlugin.js included in your HTML index file
find the path for js file into plugins directory of the app
Example : MyFCM\plugins\cordova-plugin-fcm\www\FCMPlugin.js
app.controller('AppCtrl', function(FCMPlugin,$scope,$cordovaToast,$cordovaDialogs,ionPlatform) {
// call to register automatically upon device ready
ionPlatform.ready.then(function (device) {
console.log('I am working');
FCMPlugin.onNotification(
function(data){
if(data.wasTapped){
//Notification was received on device tray and tapped by the user.
$cordovaDialogs.alert(data.notification.body);
}else{
//Notification was received in foreground. Maybe the user needs to be notified.
$cordovaDialogs.alert(data.notification.body);
//$cordovaToast.showShortCenter( JSON.stringify(data) );
}
},
function(msg){
$cordovaToast.showShortCenter('onNotification callback successfully registered: ' + msg);
},
function(err){
$cordovaToast.showShortCenter('Error registering onNotification callback: ' + err);
}
);
});
})
I already know how to send push notifications in Titanium with Alloy, the way I do is:
// Require the module
var CloudPush = require('ti.cloudpush');
var deviceToken = null;
// Initialize the module
CloudPush.retrieveDeviceToken({
success: deviceTokenSuccess,
error: deviceTokenError
});
// Enable push notifications for this device
// Save the device token for subsequent API calls
function deviceTokenSuccess(e) {
deviceToken = e.deviceToken;
// alert("--->" + deviceToken);
subscribeToChannel();
}
function deviceTokenError(e) {
alert('Failed to register for push notifications! ' + e.error);
}
// Process incoming push notifications
CloudPush.addEventListener('callback', function (evt) {
alert("Notification received: " + evt.payload);
});
// For this example to work, you need to get the device token. See the previous section.
// You also need an ACS user account.
// Require in the Cloud module
var Cloud = require("ti.cloud");
function loginUser(){
// Log in to ACS
Cloud.Users.login({
login: 'example',
password: 'example'
}, function (e) {
if (e.success) {
alert('Login successful');
} else {
alert('Error:\n' +
((e.error && e.message) || JSON.stringify(e)));
}
});
}
function subscribeToChannel(){
// Subscribe the user and device to the 'test' channel
// Specify the push type as either 'android' for Android or 'ios' for iOS
// Check if logged in:
Cloud.PushNotifications.subscribe({
channel: 'test',
//device_token: 'APA91bHRjGoZLCYKwn-XcCtNLETuf-KRKfT4sMgVE4KgXQgInYfZuYTNrZC7FUMugLs0idzzqtLytrvVJjVzYBzQoc7Q81hEerq0O2vww_tV8mACuUfAi0JRvs7LoufnQZpYLZrb_1rlUsIOEMsPxDs9b_pIRJF5rw',
device_token:deviceToken,
type: Ti.Platform.name == 'android' ? 'android' : 'ios'
}, function (e) {
if (e.success) {
alert('Subscribed');
} else {
alert('Error:\n' +
((e.error && e.message) || JSON.stringify(e)));
}
});
}
function unsubscribeToChannel (){
// Unsubscribes the user and device from the 'test' channel
Cloud.PushNotifications.unsubscribe({
channel: 'test',
device_token: deviceToken
}, function (e) {
if (e.success) {
alert('Unsubscribed');
} else {
alert('Error:\n' +
((e.error && e.message) || JSON.stringify(e)));
}
});
}
loginUser();
However this way is only for sending push notification through https://cloud.appcelerator.com/ such a manually because it is needed you write the alert and push the button in that backend site.
So my question: Is there any way for sending push notification in Titanium from an own server in an "automatically" way?
Thanks in advance for any help.
Yes, it is possible.
How to obtain a device token for push notifications is described in the Titanium docs, here.
To send notifications you have to send the token to your server. The server then sends your notification to Apple Push Notification Services (APNS). See Apple docs. That's not "automatic" but it's a simple task for PHP or any other language - you can find a lot of scripts.
You can also schedule local notifications which might come in handy depending on your case.