I am trying to build a simple app using latest pushnotification plugin. I am using Phonegap build. But I am not able to get the registration Id on iOS 9.1 but it is working on iOS8. Check below code
var push = PushNotification.init({
"android": {
"senderID": "12345679"
},"ios": {
"alert": "true", "badge": "true", "sound": "true"
}, "windows": { }
});
push.on('registration', function(data) {
alert("got registration id");
console.log(JSON.stringify(data));
localStorage.setItem("deviceToken", data.registrationId);
});
push.on('notification', function(data) {
// data.message,
// data.title,
// data.count,
// data.sound,
// data.image,
// data.additionalData
});
push.on('error', function(e) {
// e.message
alert(e.message);
});
Config.xml
<gap:plugin name="phonegap-plugin-push" source="npm" version="1.4.2" />
<preference name="phonegap-version" value="cli-5.2.0" />
<preference name="android-build-tool" value="gradle"/>
I found the solution of this problem,
Actually it's not certain thing but it's combination of more than one factor
For client side make sure to use the latest version of the push plugin found here which is 1.4.2 (till now)
here is the a sample of client side code
var push = PushNotification.init({ "android": {"senderID": "12345679"},
"ios": {"alert": "true", "badge": "true", "sound": "true"}, "windows": {} } );
push.on('registration', function(data) {
// data.registrationId
});
push.on('notification', function(data) {
// data.message,
// data.title,
// data.count,
// data.sound,
// data.image,
// data.additionalData
});
push.on('error', function(e) {
// e.message
});
For server side and Xcode project :
1- be sure to use Xcode 7.1.1 (latest stable version till now)
2- be sure to create APNS Production NOT DEVELOPMENT certificate then download it
3- drag it or open it with keychain access expand it and export the private key as yourAppNameKey.p12
4- then we need to generate the pem file for the certificate,So via terminal write :
openssl x509 -in aps_production.cer -inform der -out yourAppNameCert.pem
Note : ins the last step we used the certificate which we downloaded in step 2
5- now we will Convert the private key’s .p12 file into a .pem file:
openssl pkcs12 -nocerts -out yourAppNameKey.pem -in yourAppNameKey.p12
Note : you will be asked to enter the password you used to export the private key and insert a pass phrase and confirm it to use in the server side code
6 - Finally we will combine the certificate and key into a single .pem file:
cat PushChatCert.pem PushChatKey.pem > ck.pem
here is a sample of the server side code
Hope it works with everyone .. Thanks
Related
I am integrating OneSignal into my app built with Felgo, when building my app for test purposes I am able to manually send notifications from my OneSignal dashboard, but obviously I want these to be automatic when an event happens in app.
I am truly struggling to understand how to get this working, I have read through both:
Felgo OneSignal Plugin and
Felgo HttpRequest
and I think combining these would be how I would go about it? Something along the lines of:
AppButton {
id: button
onClicked: {
//other onClicked actions,
HttpRequest
.post("https://onesignal.com/api/v1/notifications")
.set('Content-Type', 'application/json')
.send({ title: "post title", body: "post body" })
.then(function(res) {
console.log(res.status);
console.log(JSON.stringify(res.header, null, 4));
console.log(JSON.stringify(res.body, null, 4));
})
.catch(function(err) {
console.log(err.message)
console.log(err.response)
});
}
}
But how on earth would I go about sending to specific tags for targeted notifications?
In the Felgo OneSignal link above, they show that I can test push notifications with curl in the following way:
curl --include \
--request POST \
--header "Content-Type: application/json" \
--header "Authorization: Basic <ONESIGNAL-REST-API-KEY>" \
--data-binary '{
"app_id": "<ONESIGNAL-APP-ID>",
"contents": { "en": "Message" },
"tags": [{"key": "userId", "relation": "=", "value": "1"}]
}' \
https://onesignal.com/api/v1/notifications
But outside of test purposes, how would I go assigning the specific tags and trigger a notification on a button press (or other event) within my app?
I understand all the information I should need to implement the notifications is there - but I cannot begin to make sense of it! :(
Any help would be massively appreciated as even when reading through documentation I am struggling.
I have got this working using the code below, what is shown is the end result of a signal sent when an AppButton is pressed elsewhere in my app.
I do not have my own web service to host this my notifications through, but for security reasons my REST key should not be in my code.
To combat this I have added my One Signal Rest API Key to a branch in my firebase database (which I am using in my app also), which can only be accessed by authorised users, this is then downloaded on the instance the request is made, and changed to a different string after.
property var osKey
firebaseDb.getValue("keys/OSkey", {
}, function(success, key, value) {
if(success){
osKey = value;
HttpRequest
.post("https://onesignal.com/api/v1/notifications")
.set('Content-Type', 'application/json')
.set("Authorization", "Basic " + osKey)
.send({
"app_id": "<MY_APP_ID>",
"contents": { "en": "MESSAGE" },
"tags": [
// the specific tags I want to send too
{"key": "groupAdmin", "relation": "=", "value": "1"},
{"key": "group", "relation": "=", "value": groupName}
]
})
.then(function(res) {
console.log(res.status);
console.log(JSON.stringify(res.header, null, 4));
console.log(JSON.stringify(res.body, null, 4));
})
.catch(function(err) {
console.log(err.message)
console.log(err.response)
});
}
})
osKey = "Nothing to see here"
I understand for securities sake, this still may not be the most secure, and again - if anyone can tell me how to improve this it would be a massive help!
Thanks
I'm struggling with this problem for more than a week... We have implemented push message in Chrome by using Firebase and a Service Worker. Everything works just fine, the messages are being sent and received correctly with the payload. On the service worker, we handle the push message to display a notification and the notificationclick event to send the user to a specific URL when clicking on it, then close the notification.
The problem is with 'old' notifications: if a user receives a message but doesn't clicks on it right away, it keeps there for a while then after some time (not sure how much) he clicks the notification - he gets redirected to https://[domain]/firebase-messaging-sw.js
We have traced the entire process: the notification gets received with all the info properly (the url is also correct, actually if he clicks right when the message is received it works just fine). But if the notification lives there for a while it gets 'emptied'.
The message being sent is pretty simple (just for showing there are no TTLs, nor expiration parameters being used). The curl command looks like that:
curl -X POST
-H "Authorization: key=[SERVER API KEY]"
-H "Content-Type: application/json"
-d '{
"notification":{
"click_action":"[URL to be redirected]",
"icon":"[A custom image]",
"title":"[News title]"},
"to":"/topics/[A topic]"
}'
"https://fcm.googleapis.com/fcm/send"
This is the code for processing the push message on the service worker:
self.addEventListener('push', function(event) {
console.log('Push message received', event);
var data = {};
if (event.data) {
data = event.data.json();
}
event.stopImmediatePropagation();
showNotification(data.notification);
});
function showNotification(notification) {
var click_action = notification.click_action; //<-- This is correct!
var options = {
body: notification.body,
icon: notification.icon,
subtitle: notification.subtitle,
data: {
url: click_action
}
};
if (self.registration.showNotification) {
return self.registration.showNotification(notification.title, options);
}
}
And the code for managing notificationclick event is pretty straightforward:
self.addEventListener('notificationclick', function(event) {
var url = '';
try {
url = event.notification.data.url; // <-- event.notification is null randomly!!
} catch (err) {}
event.waitUntil(self.clients.openWindow(url));
});
Is there any reason for loosing the payload after a certain time on the service worker context? Is this time specified on any documentation somewhere?
Thanks in advance for your help!
//payload of push message
{
"notification": {
"title": data.title,
"body": data.text,
"click_action": url,
"tag": "",
"icon": ""
},
"to": token
}
//in service woker
self.addEventListener("notificationclick", (event) => {
event.waitUntil(async function () {
const allClients = await clients.matchAll({
includeUncontrolled: true
});
let chatClient;
for (const client of allClients) {
if (client['url'].indexOf(event.notification.data.FCM_MSG.notification.click_action) >= 0) {
client.focus();
chatClient = client;
break;
}
}
if (!chatClient) {
chatClient = await clients.openWindow(event.notification.data.FCM_MSG.notification.click_action);
}
}());
});
so in this basically, on click of notification you are redirected to application ,and if the application is not open you are opening the application in new tab , as you are concerned that in event you are not able to get the click_action, could you try event.notification.data.FCM_MSG.notification.click_action by using this and see if you are getting the url, and add the event listener in beginning of service worker https://github.com/firebase/quickstart-js/issues/102
i am building mobile application using cordova and phonegap.
I want to display a popup on device screen when the notification reaches.Is there any plugin in cordova for this.
From https://programmingistheway.wordpress.com/2017/07/19/devextremephonegap-how-to-manage-push-notifications-with-fcm/
The 3 events registration, notification and error are managed only if the app is opened.
Registration: the APP registers itself to the push service, receiving
a unique registrationId. This event is useful if you want to store
this value to send notifications to single devices;
Notification: instead of show the classic notification pop up (depending on the
phone), the event notication shows a little pop up (using DevExtreme
feature) to read the message, if the APP is open (if the app is
closed, you will get the notification in the classic way);
Error: if the APP is open and the notification throws some error, here you can manage it.
So, the event you have to mangage is notification. This event is raised when a notification is delivered with the app in foreground (so, when the app is running).
Insert this code in the deviceReady event:
var push = PushNotification.init({
android: {
},
ios: {
alert: "true",
badge: "true",
sound: "true",
clearBadge: "true"
},
windows: {}
});
push.on('registration', function (data) {
// data.registrationId
DevExpress.ui.notify("Device registered " + data.registrationId, "success", 3000);
});
push.on('notification', function (data) {
// data.message,
// data.title,
// data.count,
// data.sound,
// data.image,
// data.additionalData
// mostra la notifica se l'app è aperta
DevExpress.ui.notify(data.message, "info", 10000);
});
push.on('error', function (e) {
// e.message
// sarà da togliere, utilissimo in fase di debug
DevExpress.ui.notify(e.message, "error", 10000);
});
and insert the code you need in the notification event. In this case, DevExtreme is used, but if you don't use it you can just show an alert or look for what you need (example)enter link description here.
I am using the phonegap-plugin-push plugin to do Push Notifications in an Ionic 2 Chat App.
I've implemented it according to the documentation, and it works, but only on the same device. i.e. it sends a notification to the phone if you supply its device token.
My issue is for a chat app, I need a PubSub model. So that a user can publish to a topic and another user can subscribe to that topic even if they are on different decices.
Looking at the documentation, it seems to be possible. See android.topics and ios.topics.
android.topics array [] Optional. If the array contains one or more
strings each string will be used to subscribe to a GcmPubSub topic.
So I try the following:
Javascript Client:
publish
let push = Push.init({
android: {
senderID: "xxxxxxxx",
topics: ['foo']
},
ios: {
alert: "true",
badge: false,
sound: "true",
topics: ['foo']
},
windows: {}
});
push.on('registration', (data) => {
// call the Java Server
let promise: Promise<string> = this.notificationService.push(data.registrationId, 'This is a test message from Ionic Chat');
promise.then((data) => {
});
});
Java Server:
try {
System.out.println("NotificationService: device_token: "+device_token);
logger.info("NotificationService: device_token: "+device_token);
// Prepare JSON containing the GCM message content. What to send and where to send.
JSONObject jGcmData = new JSONObject();
JSONObject jData = new JSONObject();
jData.put("title", "This is title");
jData.put("message", message);
jGcmData.put("to", device_token); // <===== is this the problem???? it is the data.registrationId from the client
// What to send in GCM message.
jGcmData.put("data", jData);
// Create connection to send GCM Message request.
URL url = new URL("https://gcm-http.googleapis.com/gcm/send");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", "key=" + API_KEY);
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestMethod("POST");
conn.setDoOutput(true);
// Send GCM message content.
OutputStream outputStream = conn.getOutputStream();
outputStream.write(jGcmData.toString().getBytes());
} catch (Exception e) {
e.printStackTrace();
}
Javascript Client:
Subscribe
let push = Push.init({
android: {
senderID: "xxxxxxxx",
topics: ['foo']
},
ios: {
alert: "true",
badge: false,
sound: "true",
topics: ['foo']
},
windows: {}
});
push.on('notification', (data) => {
});
It works on the same device, but it doesn't work if the publisher and subscriber are on different devices.
I think the problem may be that even though another user is subscribed to the topic I publish to, it is still only publishing to the data.registrationId (Device Token).
See the following line on the Java Server:
jGcmData.put("to", device_token);
Question
Does anyone know how to make it send to all subscribers on that topic?
I think the answer is here:
"to": "/topics/foo-bar",
But how should this be formatted for multiple topics? (that's just one topic foo-bar)
Need to Change the Java Server to send to the topic instead of the device:
jGcmData.put("to", "/topics/"+topics);
see: https://developers.google.com/cloud-messaging/
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);
}
);
});
})