I don't have any more hair to tear out and need help..
I want to send messages to a topic (or channel) from a server (via GCM) so it reaches all devices subscribing to that topic.
Sending push messages to individual devices works fine and the format for sending to topics is the same, except for specifying a deviceToken, specify the topic in the for /topics/mytopic
This is described here:
https://developers.google.com/cloud-messaging/downstream
https://developers.google.com/cloud-messaging/topic-messaging
On the Titanium side (Android for now but the plan is IOS too later on) I register the device to a channel "myChannel". I can verify this by a success message returned and also in Appcelerators console.
Now, I simulate a server with curl, and send a message to "myChannel" to GCM. The message response with success and I receive back a message_id from GCM.
curl -H "Content-Type:application/json" -H "Authorization:key=APIKEY" --data '{"to": "/topics/myChannel","data": {"payload":{ "message": "Hi!" } }}' https://gcm-http.googleapis.com/gcm/send
My problem is that this message is not routed to the device.
I am guessing there is some syntax conversion needed between the channel subscribed to in Titanium and the one I use to GCM but I don't know.
The funny thing is, as soon I put in the deviceToken in curl it works perfectly.
Am I missing something fundamental here? Is the channel not there to route the same message to multiple devices subscribing to it?
Any help, clues are much appreciated.
My code looks like this:
// Require the module
var CloudPush = require('ti.cloudpush');
// Initialize the module
CloudPush.retrieveDeviceToken({
success: deviceTokenSuccess,
error: deviceTokenError
});
CloudPush.addEventListener('callback', receivePush);
function receivePush(evt) {
alert("Notification received: " + JSON.stringify(evt.payload));
}
function deviceTokenSuccess(e) {
Alloy.Globals.DeviceToken = e.deviceToken;
Titanium.API.info(Alloy.Globals.DeviceToken);
// Subscribe to topic
var Cloud = require("ti.cloud");
var subscribe_data = {
device_token: Alloy.Globals.DeviceToken,
channel: Alloy.Globals.topicChannelID,
type: Ti.Platform.name == 'android' ? 'android' : 'ios'
};
Cloud.PushNotifications.subscribeToken(
subscribe_data, function (e) {
if (e.success) {
Titanium.API.info('Subscribed successfully');
} else {
Titanium.API.error('Error subscribing');
}
});
}
// Something went wrong getting the device token
function deviceTokenError(e) {
Titanium.API.error('Failed ' + e.error);
}
GCM doesn't know about channels. That's something Arrow tracks and translates to the subscribed tokens. So you need to send push via the Arrow API or Appcelerator Dashboard.
http://docs.appcelerator.com/platform/latest/#!/guide/Sending_and_Scheduling_Push_Notifications
http://docs.appcelerator.com/arrowdb/latest/#!/api/PushNotifications
Related
I am trying to determine the best way to detect if my app was opened by tapping on a push notification. I have found some different articles online that suggest different way to do this, but none seem to work in a consistent manner across app platforms and states.
Is there an official Appcelerator way to do this?
Yes, there is an official way.
if (Ti.Platform.getOsname() !== 'android') {
// Wait for user settings to be registered before registering for push notifications
Ti.App.iOS.addEventListener('usernotificationsettings', function registerForPush() {
// Remove event listener once registered for push notifications
Ti.App.iOS.removeEventListener('usernotificationsettings', registerForPush);
Ti.Network.registerForPushNotifications({
success: deviceTokenSuccess,
error: deviceTokenError,
callback: receivePush
});
});
// Register notification types to use
Ti.App.iOS.registerUserNotificationSettings({
types: [
Ti.App.iOS.USER_NOTIFICATION_TYPE_ALERT,
Ti.App.iOS.USER_NOTIFICATION_TYPE_SOUND,
Ti.App.iOS.USER_NOTIFICATION_TYPE_BADGE
]
});
}
// For Android
else {
var CloudPush = require('ti.cloudpush');
var deviceToken = null;
// Initialize the module
CloudPush.retrieveDeviceToken({
success: deviceTokenSuccess,
error: deviceTokenError
});
// Process incoming push notifications
CloudPush.addEventListener('callback', function (evt) {
receivePush(evt);
});
}
// Process incoming push notifications
function receivePush(e) {
// alert(e.data);
}
Hi I follow the steps below
1) I created the cordova project structure.
2) I added the platform( android).
3) I added the cordova plugin
cordova plugin add https://github.com/phonegap-build/PushPlugin.git#2.4.0
4) Bulid the cordova project.
5) Next I import the created app in android eclipse(4.4.2)
6) I wrote the code below in index.js file
init: function(){
alert("init");
var pushNotification = window.plugins.pushNotification;
pushNotification.register(successHandler, errorHandler,
{
'senderID':'XXXXXXXXXX',
'ecb':'onNotificationGCM' // callback function
}
);
function successHandler(result) {
console.log('Success: '+ result);
alert(result);
}
function errorHandler(error) {
console.log('Error: '+ error);
}
function onNotificationGCM(e) {
alert("comming");
if('registered' === e.event) {
// Successfully registered device.
}
else if('error' === e.event) {
// Failed to register device.
}
};
I am getting the respose as "OK".and i am not able call 'ecb': onNotificationGCM' // callback function
In Android console I am getting the bellow Message
V/PushPlugin(2512): execute: action=register
V/PushPlugin(2512): execute: data= [{"senderID":"889953963751","ecb":"onNotificationGCM"}] V/PushPlugin(2512): execute: jo={"senderID":"889953963751","ecb":"onNotificationGCM"} V/PushPlugin(2512): execute: ECB=onNotificationGCM senderID=889953963751
09-12 03:13:33.453: D/GCMRegistrar(2512): resetting backoff for com.ensis.hello
09-12 03:13:33.613: V/GCMRegistrar(2512): Registering app com.ensis.hello of senders 889953963751
09-12 W/PluginManager(2512): THREAD WARNING: exec() call to PushPlugin.register blocked the main thread for 181ms. Plugin should use CordovaInterface.getThreadPool().
This is the push notification flow:
your app request a registration to the remote Apple or Google server
if the registration is ok, the remove server returns a token, that identify this specific app on your device
you send this token to your server, saving it (e.g. on a db)
you send a push notification (from your server) calling Apple or Google services with the message and the tokens of the users you want to notify
these services push to your device/app a notification with the message
You must follow all these steps in order to have push notification working.
For android you need to catch the registration id (token) inside the registered event of the notification handler:
function onNotificationGCM(e) {
alert("comming");
if('registered' === e.event) {
// Successfully registered device.
console.log("regID = " + e.regid);
// save/send this registration id on your server
} else if('error' === e.event) {
// Failed to register device.
}
};
For iOS you need to catch it in the succesHandler of the register function.
For more information look at this example in the plugin repository.
For a while now, I have been trying to figure out how to send push notifications. The app I have made is for Android right now, but I want to extend it to other devices once I figure this out. I've looked into various services, such as Amazon SNS, but they all neglect to include how to get the device token. They all assume you know how to do that.
So what I am asking is: how do I get a device token/registration ID for a device?
I tried using this code:
var tokenID = "";
document.addEventListener("deviceready", function(){
//Unregister the previous token because it might have become invalid. Unregister everytime app is started.
window.plugins.pushNotification.unregister(successHandler, errorHandler);
if(intel.xdk.device.platform == "Android")
{
//register the user and get token
window.plugins.pushNotification.register(
successHandler,
errorHandler,
{
//senderID is the project ID
"senderID":"",
//callback function that is executed when phone recieves a notification for this app
"ecb":"onNotification"
});
}
else if(intel.xdk.device.platform == "iOS")
{
//register the user and get token
window.plugins.pushNotification.register(
tokenHandler,
errorHandler,
{
//allow application to change badge number
"badge":"true",
//allow application to play notification sound
"sound":"true",
//register callback
"alert":"true",
//callback function name
"ecb":"onNotificationAPN"
});
}
}, false);
//app given permission to receive and display push messages in Android.
function successHandler (result) {
alert('result = ' + result);
}
//app denied permission to receive and display push messages in Android.
function errorHandler (error) {
alert('error = ' + error);
}
//App given permission to receive and display push messages in iOS
function tokenHandler (result) {
// Your iOS push server needs to know the token before it can push to this device
// here is where you might want to send the token to your server along with user credentials.
alert('device token = ' + result);
tokenID = result;
}
//fired when token is generated, message is received or an error occured.
function onNotification(e)
{
switch( e.event )
{
//app is registered to receive notification
case 'registered':
if(e.regid.length > 0)
{
// Your Android push server needs to know the token before it can push to this device
// here is where you might want to send the token to your server along with user credentials.
alert('registration id = '+e.regid);
tokenID = e.regid;
}
break;
case 'message':
//Do something with the push message. This function is fired when push message is received or if user clicks on the tile.
alert('message = '+e.message+' msgcnt = '+e.msgcnt);
break;
case 'error':
alert('GCM error = '+e.msg);
break;
default:
alert('An unknown GCM event has occurred');
break;
}
}
//callback fired when notification received in iOS
function onNotificationAPN (event)
{
if ( event.alert )
{
//do something with the push message. This function is fired when push message is received or if user clicks on the tile.
alert(event.alert);
}
if ( event.sound )
{
//play notification sound. Ignore when app is in foreground.
var snd = new Media(event.sound);
snd.play();
}
if ( event.badge )
{
//change app icon badge number. If app is in foreground ignore it.
window.plugins.pushNotification.setApplicationIconBadgeNumber(successHandler, errorHandler, event.badge);
}
}
All I get is an alert that says "result = ok". The alerts later on in the code don't happen. I've tried making sense of the code but I'm not getting anywhere. Any suggestions? Is there a tutorial for this I'm not finding?
Those legacy intel.xdk functions are being retired (the will continue to live in an 01.org, see the notice on this page: https://software.intel.com/en-us/node/492826).
I recommend you investigate one of the many push notification Cordova plugins that are available. Use your favorite web search tool to search for something like "cordova phonegap push notification plugin" to find some. The good ones will have examples of how to use.
Note:-
Unregister - Its not strictly necessary to call it.....
Ensure that you have a sender ID for Android (no idea about iOS).
Result OK means that the plugin is installed correctly and has run properly.
Problems could be due to:
Incorrect sender ID
Testing in emulator without adequate setup
Important - Push notifications are intended for real devices. They are not tested for WP8 Emulator. The registration process will fail on the iOS simulator. Notifications can be made to work on the Android Emulator, however doing so requires installation of some helper libraries, as outlined here, under the section titled "Installing helper libraries and setting up the Emulator".
onNotification must be available as a global object. So try attaching it to the window. Refer to this question
Examples of properly initializing PushPlugin in:
Ionic (my answer)
I got this Unauthorized null message when I try trigger node script for my push notification.
I'm using this sample code for my push notification.
https://github.com/hollyschinsky/PushNotificationSample30/
Please refer this site for your reference.
http://devgirl.org/2013/07/17/tutorial-implement-push-notifications-in-your-phonegap-application/
I already check this solution but it still didn't work. Why?
node.js returns null push messages
After I insert the correct API key, we got authorised but null.
Actually "null" in the case means it is a success. The problem is when you run your application in local environment and the device is connected to wifi. There is a certain case that firewall block the traffic from the outgoing connection ports which are used by GCM (5228,5229,5230).
You can refer to the site as a reference
http://developer.android.com/google/gcm/http.html
Looks like you have not registered for an api key. This is from the url you posted.
var gcm = require('node-gcm');
var message = new gcm.Message();
//API Server Key
var sender = new gcm.Sender('AIzaSyCDx8v9R0fMsAsjoAffF-P3FCFWXlvwLhg');
var registrationIds = [];
// Value the payload data to send...
message.addData('message',"\u270C Peace, Love \u2764 and PhoneGap \u2706!");
message.addData('title','Push Notification Sample' );
message.addData('msgcnt','3'); // Shows up in the notification in the status bar
message.addData('soundname','beep.wav'); //Sound to play upon notification receipt - put in the www folder in app
//message.collapseKey = 'demo';
//message.delayWhileIdle = true; //Default is false
message.timeToLive = 3000;// Duration in seconds to hold in GCM and retry before timing out. Default 4 weeks (2,419,200 seconds) if not specified.
// At least one reg id required
registrationIds.push('APA91bwu-47V0L7xB55zoVd47zOJahUgBFFuxDiUBjLAUdpuWwEcLd3FvbcNTPKTSnDZwjN384qTyfWW2KAJJW7ArZ-QVPExnxWK91Pc-uTzFdFaJ3URK470WmTl5R1zL0Vloru1B-AfHO6QFFg47O4Cnv6yBOWEFcvZlHDBY8YaDc4UeKUe7ao');
/**
* Parameters: message-literal, registrationIds-array, No. of retries, callback-function
*/
sender.send(message, registrationIds, 4, function (result) {
console.log(result);
});
I am trying to develop app with pushnotification, I am getting device token but unable to subscribe.
I am getting error i.e Required field: Channel is missing.
I did this to subscribe
var deviceToken;
var CloudPush = require('ti.cloudpush');
var Cloud = require('ti.cloud');
Cloud.PushNotifications.subscribe({
channel: 'friend_request',
type: Ti.Platform.name == 'android' ? 'gcm' : 'ios',
device_token: deviceToken
}, function (e) {
if (e.success) {
alert('Success :'+((e.message) || JSON.stringify(e)));
pushNotify();
} else {
alert('Error:' + ((e.error && e.message) || JSON.stringify(e)));
}
});
I ran into the same problem. It appears that you can't really subscribe without having a user account logged into the ACS cloud services platform.
So either create an account or use the default one. Here's a thread on Appcelerator.com solving the same problem, and with a code sample that works.
https://developer.appcelerator.com/question/135641/push-notifications-with-ticloud
Either what #Phil McCarty mentioned and make sure you are using GCM and not MQTT which has been deprecated last month. Once those settings have been done, make sure the device is sending the token of the device, as you will get this same ACS message: Channel is missing if the token is wrong.