I'm working on a cordova application which has a local notification plugin. which I found at this git: https://github.com/katzer/cordova-plugin-local-notifications
I have a problem when I run the click event of a notification. What is happening is the event is being triggered but the parameters notification and status are returning empty.
The notification is triggered and the parameters are correct. the date I used was in the past could it be that?
Does anyone have the same issue and found a solution for it?
cordova.plugins.notification.local.on("click", function (notification, state) {
if (notification.data == null || notification.data == undefined) { }
else if (notification.data.localeCompare('') == 0) {
} else {
}
}, this);
NotificationTemplate = function (sheduleTime, id, title, text, process,rowId) {
var sound = device.platform == 'Android' ? 'file://sound.mp3' : 'file://beep.caf';
cordova.plugins.notification.local.schedule({
id: id,
title: title,
text: text,
at: sheduleTime,
sound: sound,
data: { RowId: rowId, proc: process }
});
};
Check the syntax in your mentioned link. You need to schedule a notification with the required data. The sample demonstrates how to schedule a local notification which repeats every week. The listener will be called when the user has clicked on the local notification.
cordova.plugins.notification.local.schedule({
id: 1,
title: "Production Jour fixe",
text: "Duration 1h",
firstAt: monday_9_am,
every: "week",
sound: "file://sounds/reminder.mp3",
icon: "http://icons.com/?cal_id=1",
data: {meetingId:"123#fg8"}
});
cordova.plugins.notification.local.on("click", function (notification) {
joinMeeting(notification.data.meetingId);
});
Related
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 have push notifications working using FCM from a cloud function. This works for both iOS and Android and displays the appropriate icon and plays a custom sound on iOS.
All is working except the custom sound for Android, it simply plays the default sound.
I have created a folder and added my sound file to it as follows: android\app\src\main\res\raw\mp3_example.mp3
This mp3 is 27s long. I have also tried a .wav and .aiff.
I read that I may have to create a push notification channel for later versions of Android so it could be related to this. I tried creating a channel and using the channelID from the cloud function and it works but there is no sound just a vibration.
The test device is a Moto G6 running Android 8.
I am using:
FCM
Firebase Cloud Functions
Ionic 4
Capacitor
https://github.com/stewwan/capacitor-fcm
Cloud Function:
const notification: admin.messaging.Notification = {
title: title,
body: body
}
const message: admin.messaging.Message = {
notification,
topic: 'QMTBC',
android:{
notification:{
sound: 'mp3_example.mp3',
icon: 'push_logo',
color: '#000000'
}
},
apns:{
payload:{
aps: {
sound: 'gears-short.wav'
}
}
}
}
return admin.messaging().send(message)
app.component.ts
import { FCM } from 'capacitor-fcm';
const fcm = new FCM();
const { PushNotifications } = Plugins;
initializeApp() {
this.platform.ready().then(() => {
PushNotifications.register();
PushNotifications.addListener('registration', (token: PushNotificationToken) => {
console.log('token ' + token.value);
fcm
.subscribeTo({ topic: 'QMTBC' })
.then(r => console.log(`subscribed to topic`))
.catch(err => console.log(err));
});
PushNotifications.addListener('registrationError', (error: any) => {
console.log('error on register ' + JSON.stringify(error));
});
PushNotifications.addListener('pushNotificationReceived', (notification: PushNotification) => {
console.log('notification ' + JSON.stringify(notification));
this.pushNotificationService.notifications.push(notification);
});
PushNotifications.addListener('pushNotificationActionPerformed', (notification: PushNotificationActionPerformed) => {
console.log('notification ' + JSON.stringify(notification));
this.pushNotificationService.notifications.push(notification);
});
fcm.getToken()
.then(r => console.log(`Token ${r.token}`))
.catch(err => console.log(err));
});
}
UPDATE:
I tried creating a channel as follows.
If I use the channel I just get the default sound. If I specific no channel or one that does not exist I also get the default sound (default channel).
cloud function:
const message: admin.messaging.Message = {
notification,
topic: 'QMTBC',
android:{
notification:{
sound: 'punch.mp3',
icon: 'push_logo',
color: '#000000',
channelId: 'QMTBC'
}
}
app.component.ts
const channel: PushNotificationChannel = {
description: 'QMTBC',
id : 'QMTBC',
importance: 5,
name : 'QMTBC'
};
PushNotifications.createChannel(channel).then(channelResult => {
console.log(channelResult);
console.log('Channel created');
// PushNotifications.listChannels().then(channels => {
// console.log('Channels');
// console.log(channels);
// });
}, err => {
console.log('Error Creating channel');
console.log(err);
});
});
UPDATE 2:
I can see the channel I have created for the app on my device and it says the sound is default. I can manually change it to another inbuilt android sound and this works. But I still can't use my custom sound.
UPDATE 3:
The custom sound works on if the Android version is < 8. Only tested this on an emulator.
#MadMac I was facing the same problem these days, after read FCM documentations and the Capacitor Java code, I got it.
It's necessary to set the visibility to 1, place your file in res/raw folder.
PushNotifications.createChannel({
description: 'General Notifications',
id: 'fcm_default_channel',
importance: 5,
lights: true,
name: 'My notification channel',
sound: 'notifications.wav',
vibration: true,
visibility: 1
}).then(()=>{
console.log('push channel created: ');
}).catch(error =>{
console.error('push channel error: ', error);
});
I'm using this payload in my firestore function to send notifications
{
android: {
notification: {
defaultSound: true,
notificationCount: 1,
sound: 'notifications.wav',
channelId: 'fcm_default_channel'
},
ttl: 20000,
collapseKey
},
apns: {
payload: {
aps: {
badge: 1,
sound: 'default'
}
}
},
notification: {
title,
body: message,
},
token: token
};
This was such a good question that helped me find the answer. So I post my answer here. Try setting the sound of the notifications to notification channels themselves at the time when you create the channels. I suppose, based on your info, the old Android versions will play sound according to the sound field in the notification payload, but in the new versions you would have to set it directly to the notification channels themselves since that is where the control is now currently intended to be by Google. I had to uninstall and reinstall the app for this code change to work, because my channels were previously initialized and the channels won't update after the first initialization.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !notificationChannelsInitialized) {
val newMessagesChannel = NotificationChannel(NEW_MESSAGES_NOTIFICATION_CHANNEL_ID, "New Messages", NotificationManager.IMPORTANCE_HIGH)
val notificationSoundUri =
Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE.toString() + "://" + context.packageName + "/" + R.raw.ns) // ns.wav is my notification sound file in the res/raw folder in Android Studio
val notificationSoundUriAttributes = AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build()
newMessagesChannel.setSound(notificationSoundUri, notificationSoundUriAttributes)
val notificationManager: NotificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannels(listOf( newMessagesChannel)) // and other channels
}
I was able to get it working for React Native using the react-native-push-notification library (here). The key to resolving is that you must create a channel within your app. (I had thought channels were created on the backend, but that's not right). After placing the mp3 file in the res/raw directory in the android folder of my app, I added the following code in React Native (copied from documentation in the above library), and it worked:
import PushNotification, {Importance} from 'react-native-push-notification';
...
PushNotification.createChannel(
{
channelId: "channel-id", // (required)
channelName: "My channel", // (required)
channelDescription: "A channel to categorise your notifications", // (optional) default: undefined.
playSound: true, // (optional) default: true
soundName: "mp3_example", // (optional) See `soundName` parameter of `localNotification` function
importance: Importance.HIGH, // (optional) default: Importance.HIGH. Int value of the Android notification importance
vibrate: true, // (optional) default: true. Creates the default vibration pattern if true.
},
(created) => console.log(`createChannel returned '${created}'`) // (optional) callback returns whether the channel was created, false means it already existed.
);
This is asked previously but not in cordova.
Hi all, I want to get alert when user enters the geofence region and also want alert when user exit from the geofence so that I can make entry.
it should work on all cases foreground, background, and even when the app is killed
I'm getting alert when user enters but not when user exits from region.
Any help would be really appreciated .
CODE:
window.geofence.addOrUpdate({
id: "69ca1b88-6fbe-4e80-a4d4-ff4d3748acdb",
latitude: xx.12345,
longitude: xx.12345,
radius: 100,
transitionType:1,
notification: {
id: 1,
title: "Welcome!",
text: "In.",
openAppOnClick: true
}
}, {
id: "69ca1b88-6fbe-4e80-a4d4-ff4d3748acdc",
latitude: xx.12345,
longitude: xx.12345,
radius: 100,
transitionType:2,
notification: {
id: 1,
title: "Bye!",
text: "Out.",
openAppOnClick: true
}
}).then(function () {
navigator.notification.alert('successfully added', function () { });
}, function (reason) {
navigator.notification.alert('failed', function () { });
})
Transition callback function:
which is getting called only only when i am in within region, it is not called when i'm out of the region
window.geofence.onTransitionReceived = function (geofences) {
alert(JSON.stringify(geofences));
}
Where using this plugin : https://github.com/cowbell/cordova-plugin-geofence and depending on you'r needs, be carefull about the following :
Javascript background execution
This is known limitation. When in background your app may/will be suspended to not use system resources. Therefore, any javascript code won't run, only background services can run in the background. Local notification when user crosses a geofence region will still work, but any custom javascript code won't. If you want to perform a custom action on geofence crossing, try to write it in native code.
We can see this exemple into the plugin documention :
window.geofence.onTransitionReceived = function (geofences) {
geofences.forEach(function (geo) {
console.log('Geofence transition detected', geo);
});
};
And if we search into the plugin code we found this (www/TransitionType.js) :
var TransitionType = {
ENTER: 1,
EXIT: 2,
BOTH: 3,
};
So you have to check if this work :
window.geofence.onTransitionReceived = function (geofences) {
geofences.forEach(function (geo) {
if (geo.TransitionType === 2 ) {
// Do what you want
}
});
};
EDIT 1
After adding your code to your primary code, I noticed two things :
First, the documentation specifies that when you want to add several geofences at once you must do so from an array and therefore with several parameters.
It may be nothing but it's better to trust the documentation.
Then, the documentation also specifies
Geofence overrides the previously one with the same id.
And that exactly what you do That may be why the event can't work properly.
If I follow the documentation correctly, you should have something that looks like this :
window.geofence.addOrUpdate({
id: "69ca1b88-6fbe-4e80-a4d4-ff4d3748acdb",
latitude: xx.12345,
longitude: xx.12345,
radius: 100,
transitionType: 3, // Both (Enter and Exit)
notification: {
id: 1,
title: "Welcome!",
text: "In.",
openAppOnClick: true
}
}
).then(function () {
navigator.notification.alert('successfully added', function () { });
}, function (error) {
navigator.notification.alert('failed', function () { });
});
window.geofence.onTransitionReceived = function (geofences) {
geofences.forEach(function (geo) {
console.log('Geofence transition detected', geo);
// Do what you want
});
};
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');
}
}
});
I want to display a group notification instead of multiple notifications like whatsapp does.
For eg:
One notification with message - "2 discussions 1 comment" instead of
total three notifications.
I used react-native-fcm library (https://github.com/evollu/react-native-fcm)
I used group & tag keys but couldn't achieve the result as below code
FCM.presentLocalNotification({
title: 'Title',
body: 'Body',
priority: "high",
click_action: true,
show_in_foreground: true,
local: true,
group: 'group1',
tag: 'tag1'
});
Is it possible to achieve this functionality in react native FCM? Please let me know.
The project react-native-fcm is moved under react-native-firebase and there is a solution under this issue on the project.
The main idea:
The trick is to create an additional notification that will contain the notifications for that group.
// ID for grouping notifications, always the same
const SUMMARY_ID = `${ALERTS_GROUP}.summary`
const sendIt = (notification: Firebase.notifications.Notification) => {
return firebase.messaging().hasPermission().then((yes) => {
if (yes) {
try {
return firebase.notifications().displayNotification(notification)
.catch((err) => {
Log.e(`[sendNotification] ERROR: ${err}`)
return Promise.resolve()
})
} catch (err) {
Log.e('[sendNotification] Error displaying notification: ' + err)
}
}
return Promise.resolve()
})
}
const sendSummary = (data: MessageData) => {
const summary = new firebase.notifications.Notification()
.setNotificationId(SUMMARY_ID)
.setTitle(_T('notification.channels.alert.description'))
.setData(data)
.android.setAutoCancel(true)
.android.setCategory(firebase.notifications.Android.Category.Message)
.android.setChannelId(getChannelId(MsgType.Alert))
.android.setColor(variables.scheme.primaryColor)
.android.setSmallIcon(STATUS_ICON)
.android.setGroup(ALERTS_GROUP)
.android.setGroupSummary(true)
.android.setGroupAlertBehaviour(firebase.notifications.Android.GroupAlert.Children)
sendIt(summary)
}
/**
* Called by `bgMessaging` or the `onMessage` handler.
*/
export function sendNotification (message: Firebase.messaging.RemoteMessage) {
const payload: MessagePayload = message.data as any || {}
const notification = new firebase.notifications.Notification()
// ... more code
if (Platform.OS === 'android' && Platform.Version >= 24) {
notification.android.setGroup(ALERTS_GROUP)
sendSummary(notification.data)
}
Log.v('[sendSummary] sending notification.')
return sendIt(notification)
}