No Sound for Push Notification via Firebase Cloud Messaging - firebase-cloud-messaging

I am trying to send a notification via Firebase Cloud Messaging to many devices. Currently the notification is received on the target devices, but there is never any sound. In my android emulator (Pixel 5 API 30), I have verified in the settings that my app has notifications enabled with sound, too. I also have verified that the sound it should play is not silent and that my computer and emulator's sound is on.
I dispatch the notification in a cloud function, with the relevant code looking like this:
// devicesToNotify is an array of FCM Tokens
devicesToNotify.forEach((deviceId) =>
admin.messaging().send({
token: deviceId,
notification: {
title: "my title",
body: "my body",
},
android: {
notification: {
sound: "default",
click_action: "FLUTTER_NOTIFICATION_CLICK",
},
},
apns: {
payload: {
aps: {
badge: 1,
sound: "default",
},
},
},
}));
I only get the notifications silently though. Am I missing something simple here? Thank you.

Related

Expo Push Notifications Not Pushing to Physical Device

My application in React Native using Expo was sending notifications beautifully using the code below to all of the tokens stored in Firebase. Now, after I published my app on the Expo.io website, it won't work and won't push any notification to any physical device at all. I have tried to rebuild the project in my local machine and run expo on my phone from my computer, and I console logged the information and all of the expo token information is correct and being pulled correctly. Why are the notifications not pushing now to any physical device? Please help. The try block below executes without error, but why aren't notifications pushing then? My component did mount also calls loadInformation & generateToken, and my render and return just call the sendPushNotif function when the user presses the send notification button.
My this.state.finalArray console logs the following: "Array [
Object {
"body": "test",
"title": "this is a test",
"to": Array [
"ExponentPushToken[.......]",
"ExponentPushToken[........]",
], }, ]"
constructor() {
super()
this.state = {
tokenArray: [],
finalArray: [],
}
}
loadInformation = async () => {
var tokens = []
firebase.database().ref('tokens/`).once('value', snapshot => {
const token = Object.values(snapshot.val());
token.map((item) => {
tokens.push(item.data)
return this.setState({ tokenArray: tokens })
})
})
}
generateToken = async () => {
this.state.finalArray = []
this.state.finalArray.push({
to: this.state.tokenArray,
title: this.state.title,
body: this.state.notification
})
}
sendPushNotification = async () => {
//these functions load all the token info from firebase and stores it into an array
this.loadInformation();
this.generateToken();
try {
let response = await fetch("https://exp.host/--/api/v2/push/send", {
method: "POST",
headers: {
Accept: "application/json",
"Accept-encoding": "gzip, deflate",
"Content-Type": "application/json",
},
body: JSON.stringify(this.state.finalArray), //final array has all the tokens and title and body info for the notif. i console logged this and it outputs the correct info
});
alert("Your notification was sent!");
} catch (error) {
console.log(error);
alert("Error! Your notification was not sent.");
}
};
The tokens you have in this.state.finalArray are Expo Push token which every Expo Go app has. So it will not work in Production as every device has its own devicePushToken.
ExponentPushToken[........] tokens work only on Expo Go App and not in Production. See this
Here is the Answer
As expo handle the notification registration for IOS but for android you have to register your app with firebase
So you have to register your app with firebase for this
Click here to get full information
https://docs.expo.dev/push-notifications/using-fcm/
all steps are mentioned
OR for Video information Click here
https://www.youtube.com/watch?v=oRNwNintDW0

Getting double notification popup for single event on ios when sending notification using FCM

Issue Description::
I am working on react native application and using react native firebase messaging service for push notification. I am having a problem on IOS platform. I am getting double notification popups for single event.
Steps I am following to generate the case::
After app installation if I am login and sending notification through FCM I just received a single popup. After this I logged out and login again, now this time I got double popups for single notification. In this case I am not clearing an app from background.
If after every logout I am clearing an app from background I just received a single popup for single event.
When I am logged out from the application, and forcefully sending notification from FCM, I am getting double popup on app initialization screen(login screen).
I am generating a new device token when user login and saving this token inside local storage, we are clearing local storage data on logout.
Code::
async mountDashboard() {
const enabled = await firebase.messaging().hasPermission();
if (enabled) {
const fcmToken = await firebase.messaging().getToken();
await AsyncStorage.setItem(LocalStorageKeys.DEVICE_TOKEN, fcmToken);
if (fcmToken) {
//--- here we are saving our token and sendind data to API
}
}
// in Foreground
this.notificationListener = firebase.notifications().onNotification((notification) => {
new RegisterLocalNotification(notification);
});
// App in Foreground and background
let notificationHandler = new NotificationsHandler();
this.notificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen) => {
notificationHandler.handleNotification(notificationOpen.notification);
});
// app close notification handler
AppCloseNotificationHandler.getInstance().handleNotification();
}
componentDidMount() {
this.mountDashboard();
}
Environment::
Binaries:
Node: 10.15.0 - /usr/local/opt/node#10/bin/node
Yarn: 1.10.1 -/usr/local/bin/yarn
npm: 6.4.1 - /usr/local/opt/node#10/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
List item
npm Packages:
react: ^16.8.4 => 16.8.4
react-native: ^0.58.6 => 0.58.6
npm Global Packages:
react-native-cli: 2.0.1
react-native-firebase: 5.2.3
You have to unsubscribe from your listener when the component will unmount. If you don't do that you are subscribing two listeners.
componentWillUnmount() {
this.notificationListener(); // it's unsubscribing your listener
}
Make sure to send this payload via backend, I am using firebase admin SDK.
This will disable Notification By OS and trigger the local notification. I am using this package for local notification https://github.com/zo0r/react-native-push-notification
async function sendPushNotification(message) {
try {
await admin.messaging().sendToDevice(
['dCk27uEySymSdP_vA1C_QI:APA91bEZNyipZDjTLq0jrGnD0qcpKH2y3oTYg3GMgT0pSENNlJEiymOYXvxvnqTFtQaidDLt5KUgp4oDZsfLsQvfiVkL7m1bpMjekHsm-7x1ZDju4TYUMUZeUgYb0CyPwMhdr9RyzA1v'],
{
data: {
owner: 'a',
user: 'a',
},
},
{
// Required for background/quit data-only messages on iOS
contentAvailable: true,
// Required for background/quit data-only messages on Android
priority: 'high',
},
);
console.log('A');
}catch(e) {
console.log('Gagal mengirim pesan');
}
}
And this my code inside App.js that listen to the notification
RNFirebase.onMessage(RNFirebaseOnMessageHandler);
RNFirebase.setBackgroundMessageHandler(RNFirebaseOnMessageHandler);
And inside the handler, I use this
PushNotification.createChannel(
{
channelId: CHANNEL_ID,
channelName: CHANNEL_NAME,
channelDescription: CHANNEL_DESCRIPTION,
soundName: CHANNEL_SOUND,
importance: CHANNEL_IMPORTANCE,
vibrate: CHANNEL_VIBRATE,
},
(created) => console.log(`createChannel returned '${created}'`), // (optional) callback returns whether the channel was created, false means it already existed.
);
PushNotification.localNotification({
channelId: CHANNEL_ID,
// #todo get ticker value from data payload
ticker: 'CreateOrderLandingScreen',
showWhen: true,
autoCancel: true,
largeIcon: CHANNEL_LARGE_ICON,
smallIcon: CHANNEL_SMALL_ICON,
bigText: 'aaaaa',
subText: CHANNEL_SUB_TEXT,
color: Colors.RED,
vibrate: true,
vibration: 300,
priority: 'high',
visibility: 'private',
invokeApp: true,
alertAction: 'view',
id: 0,
title:'aa',
message: 'aaaa',
userInfo: {},
playSound: false,
soundName: 'default',
});

Correct setup with react-native-fcm

I feel like the docs at react-native-fcm are a bit of a mess and I am having a hard time figuring this out.
I currently have a production app and my android users are telling me they are not receiving notifications for events where they should be. So this is stressing me out a lot right now. On iOS everything seems fine.
In the react-native-fcm example app you can see the following:
//FCM.createNotificationChannel is mandatory for Android targeting >=8. Otherwise you won't see any notification
componentDidMount() {
FCM.createNotificationChannel({
id: 'default',
name: 'Default',
description: 'used for example',
priority: 'high'
})
}
Do I need to call FCM.createNotificationChannel()?? I mainly use remote notifications so is this relevant in any way?
Here is MY setup:
import FCM, {
FCMEvent,
NotificationType,
RemoteNotificationResult,
WillPresentNotificationResult,
} from 'react-native-fcm';
FCM.on(FCMEvent.Notification, async (notif) => {
// there are two parts of notif. notif.notification contains the notification payload, notif.data contains data payload
FCM.presentLocalNotification({
id: "new_message", // (optional for instant notification)
title: notif.fcm.title, // as FCM payload
body: notif.fcm.body, // as FCM payload (required)
sound: "default", // as FCM payload
priority: "high", // as FCM payload
click_action: "com.myapp.MyCategory", // as FCM payload - this is used as category identifier on iOS.
badge: 10, // as FCM payload IOS only, set 0 to clear badges
number: 10, // Android only
ticker: "My Notification Ticker", // Android only
auto_cancel: true, // Android only (default true)
large_icon: "ic_launcher", // Android only
icon: "ic_launcher", // as FCM payload, you can relace this with custom icon you put in mipmap
color: "blue", // Android only
vibrate: 300, // Android only default: 300, no vibration if you pass 0
wake_screen: true, // Android only, wake up screen when notification arrives
group: "group", // Android only
picture: "https://google.png", // Android only bigPicture style
ongoing: false, // Android only
my_custom_data:'my_custom_field_value', // extra data you want to throw
lights: true, // Android only, LED blinking (default false)
});
if(Platform.OS ==='ios'){
//optional
//iOS requires developers to call completionHandler to end notification process. If you do not call it your background remote notifications could be throttled, to read more about it see https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623013-application.
//This library handles it for you automatically with default behavior (for remote notification, finish with NoData; for WillPresent, finish depend on "show_in_foreground"). However if you want to return different result, follow the following code to override
//notif._notificationType is available for iOS platfrom
switch(notif._notificationType){
case NotificationType.Remote:
notif.finish(RemoteNotificationResult.NewData) //other types available: RemoteNotificationResult.NewData, RemoteNotificationResult.ResultFailed
break;
case NotificationType.NotificationResponse:
notif.finish();
break;
case NotificationType.WillPresent:
notif.finish(WillPresentNotificationResult.All) //other types available: WillPresentNotificationResult.None
break;
}
}
});
FCM.on(FCMEvent.RefreshToken, (token) => {
try {
const { currentUser } = firebase.auth();
let updates = {};
updates[`/allUsers/serviceUsers/${currentUser.uid}/userInfo/fcmToken`] = token;
return firebase.database().ref().update(updates).catch(err => console.log('fcm refresh error', err))
} catch (e) {
console.log('couldnt update fcm refresh token', e)
}
});
const store = createStore(reducers, {}, applyMiddleware(ReduxThunk));
class App extends Component {
componentWillMount() {
let config = {configgg}
!firebase.apps.length ? firebase.initializeApp(config) : firebase.app();
FCM.requestPermissions();
}
render() {
return (
<Provider store={store}>
<Router/>
</Provider>
);
}
}
export default App;
I mainly use remote notifications and it is critical for my app for it to work. Is there anything I am missing in my setup?
Any hint or suggestions will help me out a lot! Thanks!
EDIT:
Found this in adb logcat when receiving a notification (that did not show up)
NotificationService: No Channel found for pkg=com.lisdoworker, channelId=null, id=0, tag=GCM-Notification:9015992, opPkg=com.lisdoworker, callingUid=10487, userId=0, incomingUserId=0, notificationUid=10487, notification=Notification(channel=null pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x10 color=0x00000000 vis=PRIVATE)
Does this have to do with FCM.createNotificationChannel()??
Yeah, apparently createNotificationChannel was added in version 16 to support Android 8 and it is barely documented.

react-native-fcm don't receive notification when app is opened

Why can't i receive notication from react-native-fcm when the app is opened?
Here is my payload
const proState={};
proState.notiUID=recKey;
proState.notiPayload={
data: {
senderKey:senderKey,
id: senderKey+':chat',
type: 'chat'
},
notification: {
title: proState.senderSnap.fullname,
body: proState.lastmsg,
sound: 'default',
id: senderKey+':chat',
tag : senderKey+':chat',
priority : "high",
data: senderKey
},
};
const optionss = {
priority: "high",
show_in_foreground: true
};
return admin.messaging()
.sendToTopic(proState.notiUID, proState.notiPayload,optionss)
I only receives notifications when the app is minimized or closed
you are facing same issue in android and ios both platforms? If you are facing this issue only in ios then don't worry ios not receives notifications in foreground. Which is default behaviour of ios.

How to bring app to foreground from background in Ionic 2?

Is there any possible way to bring app from background mode in to foreground when an event happens like notification arrive? like WhatsApp and Skype that bring into foreground when a voice call or video call arrive.
Update:
public subscribeToPushNotificationEvents(): void {
// Handle token refresh
this.firebase.onTokenRefresh().subscribe(
token => {
//console.log(`The new token is ${token}`);
this.saveToken(token);
},
error => {
console.error('Error refreshing token', error);
});
// Handle incoming notifications
this.firebase.onNotificationOpen().subscribe(
(notification: NotificationModel) => {
this.backgroundMode.moveToForeground();
let notificationAlert = this.alertCtrl.create({
title: notification.title,
message: notification.body,
buttons: ['Ok']
});
notificationAlert.present();
}
As far as I know, your only option is this plugin: http://ionicframework.com/docs/native/background-mode/