In my ionic app, I need to open a specific page after receiving a push notification.
I'm testing it in the Android Studio emulator and have displayed a bunch of console logs that prove that the push.on('notification').subscribe event is definitely triggering the page using navCtrl.push (I've tried navCtrl.setRoot too) and the ngOnInit is doing everything as normal and making it to the end of its code.
The problem is that after that, the page just isn't showing.
I can see the following message in the Android console log, but I don't really know what it means:
D/SystemWebChromeClient: ng:///AppModule/ShiftDetailsPage.ngfactory.js: Line 563 : ERROR
I/chromium: [INFO:CONSOLE(563)] "ERROR", source: ng:///AppModule/ShiftDetailsPage.ngfactory.js (563)
but they appear before all the console log messages output by ngOnInit in ShiftDetailsPage, so I guess they don't mean there was a problem loading the page.
Another thing that is appearing is:
Cannot read property 'controls' of undefined.
in the app.
I've searched everywhere for someone having a similar problem, but all I can find are descriptions of how to receive notifications, but nothing helpful about how to trigger pages from the event.
Should I use something other than navCtrl.push or is that the correct way?
Any suggestions are very welcome.
Here's the code in the push.on subscribe:
push.on('notification').subscribe(async (data: EventResponse) => {
console.log("in notification, data = " + JSON.stringify(data));
if (data.additionalData.shiftId != null
&& data.additionalData.shiftId != ""
&& await this.login.isLoggedIn()
) {
console.log("in notification, shiftId = " + data.additionalData.shiftId);
console.log("in notification, isLoggedIn = " + JSON.stringify(await this.login.isLoggedIn()));
const confirmAlert = this.alertCtrl.create({
title: 'Shift Notification',
message: data.additionalData.shiftId,
buttons: [
{
text: 'Ignore',
role: 'cancel'
},
{
text: 'View',
handler: () => {
console.log("in notification, handler");
this.shiftDetailsProvider.getShiftDetails(data.additionalData.shiftId).then( async shift => {
const userLocation = await this.getUserLocation().then(userLocation => {
console.log("in pushSetup on notification, userLocation = ", userLocation);
return userLocation;
});
this.navCtrl.push(ShiftDetailsPage, {shift: shift, userLocation: userLocation, sourcePage: "notification"});
});
}
},
]
});
confirmAlert.present();
} else {
console.log("in notification, else");
if (data.additionalData.foreground) {
console.log("in notification, foreground");
const confirmAlert = this.alertCtrl.create({
title: 'New Notification',
message: data.message,
buttons: [
{
text: 'Cancel',
role: 'cancel'
},
{
text: 'OK',
handler: () => {
console.log('New notification callback')
}
},
]
});
confirmAlert.present();
if (this.platform.is('ios')) {
console.log("in notification, platform is ios");
push.finish(data.additionalData.notId);
}
} else {
console.log('Push notification clicked from the background');
}
}
});
Related
I have installed FCM notification plugin and added following code in
FCM.onNotification().subscribe(data => {
if (data.wasTapped) {
this.route.navigateByUrl(`${data.routeUrl}`);
console.log("Received in background");
} else {
this.localNotifications.schedule({
title: data.title,
text: data.body,
foreground: true
})
this.localNotifications.on("click").subscribe((notification: any) => {
this.navCtrl.navigateForward([data.routeUrl]).then((entry) => {
}).catch((err) => {
console.log('Error while navCtrl:- ' + JSON.stringify(err));
});
})
console.log("Received in foreground");
};
});
With this I am able to navigate to a screen from the path provided in the body of notification when app is open but when app is in closed state or in background I'm unable to navigate to that screen
Please help me out regarding this issue
Regards
Unfortunately, no answer yet. I am checking out postman, I hope I can use that to test quicker.
I manage to send a notification through my app, however, the notification always ends up in the silent notification of my phone, no sound, no vibration and no notification icon in the top left of the phone, only a notification in the drawer when I swipe down :(
In an attempt to fix / improve the situation I tried the following:
Create an android notification channel with id: high_importance_channel by using flutter_local_notifications package. The channel was created successful, because requesting an overview of the existing channels, showed the newly created channel (among the other channels). The new channel has importance: 5, enableVibration: true and playSound: true, so that should do the job.
Send a FCM through cloud functions with the following code:
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
exports.chatNotification = functions.firestore
.document('chats/{groupId}/chat/{chatId}')
.onCreate( async (snapshot, context) => {
const message = {
"notification": {
"title": "Message Received",
"body": "Text Message from " + fromUserName,
},
"tokens": registrationTokens,
"android": {
"notification": {
"channel_id": "high_importance_channel",
},
},
};
admin.messaging().sendMulticast(message)
.then((response) => {
console.log(response.successCount + ' messages were sent successfully');
});
}
But so far not luck, the notification still ends up in the silent notifications. What am I doing wrong?
There are 2 ways of doing it. Might work in your case.
Way 1:
var payload = {
notification: {
android_channel_id: 'AppChannel',
/*
https://stackoverflow.com/questions/62663537/how-do-i-add-a-channelid-to-my-notification
https://firebase.google.com/docs/cloud-messaging/http-server-ref#notification-payload-support
*/
title: 'Push Notification Arrived!',
body: 'Using Cloud Functions',
sound: 'default',
},
data: {
route: '/someRoute',
},
};
try {
const response = await admin.messaging().
sendToDevice(deviceTokens, payload);
console.log('Notification sent succesfully.');
} catch (err) {
console.log('Error sending Notifications...');
console.log(err);
}
Way 2:
const message = {
/*
https://firebase.google.com/docs/reference/admin/node/firebase-admin.messaging.basemessage.md#basemessagenotification
*/
notification: {
title: 'Push Notification Arrived!',
body: 'Using Cloud Functions',
},
data: {
route: '/someRoute',
},
android: {
/*
https://firebase.google.com/docs/reference/admin/node/firebase-admin.messaging.androidnotification.md#androidnotificationbodylockey
*/
notification: {
channelId: "AppChannel",
priority: 'max',
defaultSound: 'true',
},
},
token: deviceTokens,
};
// https://firebase.google.com/docs/reference/admin/node/firebase-admin.messaging.messaging.md#messagingsend
admin.messaging().send(message)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message, for LOVEs sake:', error);
});
I have a cloud function which executes this code to send the notification to the user, I am getting notification correctly but I want to navigate to a particular screen for that I have to add click action something like this.
clickAction: FLUTTER_NOTIFICATION_CLICK
I have tried to put this property in different lines of code but nothing seem to work, can someone please tell where should I put it exactly?
This is my index.js file!
const message = {
token: data['guestFcmToken'],
notification: {
title: `New message from ${data['hostName']}.`,
body: data['type'] === 'image' ? 'Photo' : data['lastMessage'],
},
data: {
showForegroundNotification: 'false',
screen: 'chat'
},
}
console.log('Sending message');
const response = await admin.messaging().send(message);
console.log(response);
You can add clickAction: 'FLUTTER_NOTIFICATION_CLICK' in the following way
message = {
token: data['guestFcmToken'],
notification: {
title: `New message from ${data['hostName']}.`,
body: data['type'] === 'image' ? 'Photo' : data['lastMessage'],
},
data: {
showForegroundNotification: 'false',
screen: 'chat'
},
android: {
notification: {
clickAction: 'FLUTTER_NOTIFICATION_CLICK',
},
}
};
I've built a small alert service (wrapper for Angular AlertController) in my Ionic 4 project, it works perfectly when I view the project in "ionic serve" (browser), "ionic cordova emulate" (on my connected phone), "ionic cordova build android" (installing the app-debug APK manually on my phone) however when I build the release version of the app using "ionic cordova build android --prod --release" the "message" part of the Alert does not show. The header (title) and the buttons show and work fine still, but the message does not appear.
Here is my method which creates and presents the alert:
/**
* "Confirm" with callback or "Cancel" alert
*/
async confirmOrCancelAlert(title, message, callback) {
const alert = await this.alertController.create({
header: title,
message: message,
buttons: [
{
text: 'Cancel',
role: 'cancel',
cssClass: 'secondary',
}, {
text: 'Confirm',
handler: () => {
callback();
}
}
]
});
await alert.present();
}
This is the code which called the method shown above, which is called from a button click:
/**
* Answer questions button event click
*/
answerQuestions() {
if (this.shift.getEarly() && (this.shift.getTimeToStart().asHours() > environment.alertTimes.answerQuestions)) {
var timeTo = this.durationFormatPipe.transform(this.shift.getStart());
var message = 'Your shift starts ' + timeTo + ', are you sure you want to answer questions now?';
this.alertService.confirmOrCancelAlert('You are early!', message, () => {
this.doAnswerQuestions();
});
} else {
this.doAnswerQuestions();
}
}
Here are two images showing the message messing from the release build but showing in the serve / emulate / debug builds:
Many thanks in advance for any and all advice.
I think it's a timing problem. when you call confirmOrCancelAlert() the timeTo is not prepared yet. so the type of message will be undefined.
try this:
answerQuestions() {
if (this.shift.getEarly() && (this.shift.getTimeToStart().asHours() > environment.alertTimes.answerQuestions)) {
var timeTo = this.durationFormatPipe.transform(this.shift.getStart());
var message = 'Your shift starts ' + timeTo + ', are you sure you want to answer questions now?';
setTimeout(() => {
this.alertService.confirmOrCancelAlert('You are early!', message, () => {
this.doAnswerQuestions();
});
}, 50);
} else {
this.doAnswerQuestions();
}
}
try this:
async confirmOrCancelAlert(title, myMessage, callback) {
const alert = await this.alertController.create({
header: title,
message: myMessage,
buttons: [
{
text: 'Cancel',
role: 'cancel',
cssClass: 'secondary',
}, {
text: 'Confirm',
handler: () => {
callback();
}
}
]
});
await alert.present();
}
change the name to myMessage to make it different than property name. message: message will cause a problem I think I had the same problem last year. check it out and inform me of the results.
I'm implementing Push Notifications on my Android Ionic 2 App with the Ionic Native FCM
When I'm receiving a notification in the foreground it works, but when I'm receiving a notification in the background and if I clicked on it, nothing happens.
app.component.ts
firebaseInit(){
//Firebase
this.fcm.subscribeToTopic('all');
this.fcm.getToken()
.then(token => {
console.log(token);
this.nativeStorage.setItem('fcm-token', token);
});
this.fcm.onNotification().subscribe(
data => {
console.log("NOTIF DATA: " + JSON.stringify(data));
if(data.wasTapped){
this.nav.push(MemoViewPage, {memo: {_id: data.memo_id}})
console.info('Received in bg')
}else{
let alert = this.alertCtrl.create({
title: data.subject,
message: "New memorandum",
buttons: [
{
text: 'Ignore',
role: 'cancel'
},
{
text: 'View',
handler: () => {
this.nav.push(MemoViewPage, {memo: {_id: data.memo_id}})
}
}
]
});
alert.present();
console.info('Received in fg')
}
});
this.fcm.onTokenRefresh()
.subscribe(token => {
console.log(token);
})
}
The if(data.wasTapped) condition doesn't go off once I clicked the notification from the system tray.
EDIT
The app opens but only in the Home Page not to the designated page that I set which is this.nav.push(MemoViewPage, {memo: {_id: data.memo_id}})
I also cannot receive notifications when the app is killed or not running.
you could use push plugin instead of FCM.
this.push.createChannel({
id: "testchannel1",
description: "My first test channel",
importance: 3
}).then(() => console.log('Channel created'));
and then you could use pushObjects to specify the needs for your notification like sound, ion etc.
const options: PushOptions = {
android: {},
ios: {
alert: 'true',
badge: true,
sound: 'false'
},
windows: {},
browser: {
pushServiceURL: 'http://push.api.phonegap.com/v1/push'
}
};
After that it is easy for you to receive notifications whether you are using the app or not
const pushObject: PushObject = this.push.init(options);
pushObject.on('registration').subscribe((registration: any) => this.nativeStorage.setItem('fcm-token', token));
pushObject.on('notification').subscribe((notification: any) => console.log('Received a notification', notification));
you could use the option of forceShow:true in the pushObject init for the app to show the notification whether you are using the app or not.
And once you clicked the notification the notification payload is received by the app with the app home page set as default.