I've been following this sample to get android pushNotifications (with GCM) working on an android emulator.
After $cordovaPush.register(config) I get Ok as response. But it never runs my callback [$scope.$on('$cordovaPush:notificationReceived'].
And in consequence I never get my registration ID.
I've created a google API project. And I'm using that project Id in the config.senderID when calling $cordovaPush.register(config).
I've also registered a gmail account into my emulator.
I guess I have 2 questions.
1.Is it possible to get (and register) push notifications on an android emulator?
why don't I get a $cordovaPush:notificationReceived event that calls my callback?
app.controller('AppCtrl', function($scope, $cordovaPush, $cordovaDialogs, $cordovaMedia, $cordovaToast, ionPlatform, $http) {
$scope.notifications = [];
// call to register automatically upon device ready
ionPlatform.ready.then(function (device) {
$scope.register();
});
// Register
$scope.register = function () {
var config = null;
if (ionic.Platform.isAndroid()) {
config = {
"senderID": "12834957xxxx"
};
}
$cordovaPush.register(config).then(function (result) {
console.log("Register success " + result);
$cordovaToast.showShortCenter('Registered for push notifications');
$scope.registerDisabled=true;
}, function (err) {
console.log("Register error " + err)
});
}
$scope.$on('$cordovaPush:notificationReceived', function (event, notification) {
console.log(JSON.stringify([notification]));
if (ionic.Platform.isAndroid()) {
handleAndroid(notification);
}
});
// Android Notification Received Handler
function handleAndroid(notification) {
// ** NOTE: ** You could add code for when app is in foreground or not, or coming from coldstart here too
// via the console fields as shown.
console.log("In foreground " + notification.foreground + " Coldstart " + notification.coldstart);
if (notification.event == "registered") {
$scope.regId = notification.regid;
storeDeviceToken("android");
}
else if (notification.event == "message") {
$cordovaDialogs.alert(notification.message, "Push Notification Received");
$scope.$apply(function () {
$scope.notifications.push(JSON.stringify(notification.message));
})
}
else if (notification.event == "error")
$cordovaDialogs.alert(notification.msg, "Push notification error event");
else $cordovaDialogs.alert(notification.event, "Push notification handler - Unprocessed Event");
}
The fix is a lot simpler than it seems.
I changed from:
$scope.$on('$cordovaPush:notificationReceived', function (event, notification) {
to:
$scope.$on('pushNotificationReceived', function (event, notification) {
while debugging I noticed this on ng-cordova.js:
angular.module('ngCordova.plugins.push', [])
.factory('$cordovaPush', ['$q', '$window', '$rootScope', function ($q, $window, $rootScope) {
return {
onNotification: function (notification) {
$rootScope.$apply(function () {
$rootScope.$broadcast('pushNotificationReceived', notification);
});
},
That means that it's doing a broadcast for 'pushNotificationReceived'. Not 'notificationReceived' as documented.
I have the same problem. It has been reported in ngCordova github, but no replies yet.
I managed to fix it. I know it's not a good solution if you are using angular but it's the only way I'm able to catch the register Id.
Inside the config object you must specify the 'ecb':
var androidConfig = {
"senderID": "388573974286",
"ecb": "function_to_be_called"
};
Put outside the controller the function:
window.function_to_be_called = function (notification) {
switch(notification.event) {
case 'registered':
if (notification.regid.length > 0 ) {
alert('registration ID = ' + notification.regid);
}
break;
case 'message':
// this is the actual push notification. its format depends on the data model from the push server
alert('message = ' + notification.message + ' msgCount = ' + notification.msgcnt);
break;
case 'error':
alert('GCM error = ' + notification.msg);
break;
default:
alert('An unknown GCM event has occurred');
break;
}
};
Even if you update the event name as you said, I also have another problem, which says: processmessage failed: message: jjavascript:angular.element(document.queryselector('[ng-app]')).injector().get('$cordovapush').onnotification({"event":"registered"...
It happens when angular doesn't find 'ng-app' and it returns 'undefined' angular.element(document.querySelector('[ng-app]'))
So to solve this, you can set manually your 'ecb' like this:
angular.element(document.body).injector().get('$cordovaPush').onNotification
Thanks to this ionic forum entry
please update your ng-cordova.js in lib/ng-cordova.js from http://ngcordova.com/docs/install/ in ng-cordova-master\dist\ng-cordova.js
Related
i have a problem when i want to process notification that is received when the app is in the background. I do receive the notification, when i click on the notification, the app opens however the FCM.on method is not executed at all, it seems it does not handle the callback.
When the app is in the foreground everything is working fine, and it process the notification without any problems.
This is the code in react-native
FCM.on(FCMEvent.Notification, notif => {
switch(notif.fcm.action){
case 'fcm.ACTION.HANDLEMESSAGE':
var data = {
thread: notif.pk,
message: JSON.parse(notif.message)
}
this.props.dispatch(fcmMSG(data));
this.props.dispatch(addNotification(notif.pk, notif.job_id));
break;
case "fcm.ACTION.HANDLEAPPLICATION":
axios.get(newServerURL + "/jobs/companyJobDetails/" + notif.recruitJobId + "/")
.then((response) => {
var jobMainRecruits = response.data;
const {navigator} = this.refs;
navigator.push({
jobMainRecruits,
});
})
.catch((error) => {
console.log("ERROR")
});
break;
default:
}
});
FCM.getInitialNotification().then(notif => {
switch(notif.fcm.action){
case 'fcm.ACTION.HANDLEMESSAGE':
const { navigator } = this.refs;
var thread = {
candidate: notif.candidate,
company: notif.company,
candidate_avatar: notif.candidate_avatar,
candidate_first_name: notif.candidate_first_name,
candidate_last_name: notif.candidate_last_name,
job_id: notif.job_id,
pk: notif.pk,
subject: notif.subject,
message: JSON.parse(notif.message)
}
navigator.push({
thread,
});
break;
case "fcm.ACTION.HANDLEAPPLICATION":
axios.get(newServerURL + "/jobs/companyJobDetails/" + notif.recruitJobId + "/")
.then((response) => {
var jobMainMessages = response.data;
const {navigator} = this.refs;
navigator.push({
jobMainMessages,
});
})
.catch((error) => {
console.log("ERROR")
});
break;
default:
}
})
EDIT:
this is my code in the backend
push_service = FCMNotification(api_key=FCM_API_KEY)
registration_id = token.token
message_title = jobInfo.title
message_body = "New application"
message_icon = 'ic_launcher'
sound = 'Default'
color = '#362F64'
click_action='fcm.ACTION.NEWJOBAPPLICATION'
data_message = {'recruitJobId': self.request.data['job'], 'message_title': message_title, 'message_body': message_body}
result = push_service.notify_single_device(click_action=click_action, registration_id=registration_id, message_title=message_title, message_body=message_body, message_icon=message_icon, sound=sound, data_message=data_message, color=color)
Thanks for help in advance.
The initial notification contains the notification that launches the
app. If the user launches the app by clicking the banner, the banner
notification info will be here rather than through FCM.on event.
sometimes Android kills activity when the app goes to background, and
then resume it broadcasts notification before JS is run. You can use
FCM.getInitialNotification() to capture those missed events. source
FCM.getInitialNotification().then(notif => {
// do some logic here
// I usually add this function inside my root page
});
The event on application is being triggered when the server send the notification, but I get only the alert with the message on app, not the native notification.
I am using ionic framework with the $cordovaPush plugin. On the server side I am using PushSharp library to call GCM.
This is the code added to app.js on $ionicPlatform.ready
var androidConfig = {
badge: true,
sound: true,
alert: true,
"senderID": "10xxxxxxxxxx"
};
$cordovaPush.register(androidConfig).then(function (result) {
// Success
}, function (err) {
// Error
})
$rootScope.$on('$cordovaPush:notificationReceived', function (event, notification) {
alert('$cordovaPush:notificationReceived');
switch (notification.event) {
case 'registered':
if (notification.regid.length > 0) {
alert('registration ID = ' + notification.regid);
}
break;
case 'message':
// this is the actual push notification. its format depends on the data model from the push server
alert(JSON.stringify(notification));
break;
case 'error':
alert('GCM error = ' + notification.msg);
break;
default:
alert('An unknown GCM event has occurred');
break;
}
}, false);
This is the code from the server (C# + PushSharp lib)
var push = new PushBroker();
//Wire up the events for all the services that the broker registers
push.OnNotificationSent += NotificationSent;
push.OnChannelException += ChannelException;
push.OnServiceException += ServiceException;
push.OnNotificationFailed += NotificationFailed;
push.OnDeviceSubscriptionExpired += DeviceSubscriptionExpired;
push.OnDeviceSubscriptionChanged += DeviceSubscriptionChanged;
push.OnChannelCreated += ChannelCreated;
push.OnChannelDestroyed += ChannelDestroyed;
push.RegisterGcmService(new
GcmPushChannelSettings("AIxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"));
push.QueueNotification(new GcmNotification().ForDeviceRegistrationId(
"APAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
.WithJson("{\"alert\":\"Hello World!\",\"badge\":7,\"sound\":\"sound.caf\"}"));
I have not used that plugin, but I recommend you this one:
https://github.com/phonegap/phonegap-plugin-push
this is the one most used, and it works like a charm
Trying to reroute when an app is resumed; really not sure why this isn't working. The resuming alert appears, and a topic id appears as well. Thoughts?
More details: on receiving the notification, lastMessage is stored. When the app is resumed, relevant data is retrieved, but $location.path() isn't working. The same call to $location.path does work elsewhere.
On resume function inside of the notification factory:
function onResumeListener() {
document.addEventListener('resume', function() {
alert("resuming");
var lastMessage;
try {
lastMessage = JSON.parse($window.localStorage.getItem('lastMessage'));
alert(lastMessage.topic_id);
//$location.path("/chat/" + lastMessage.topic_id);
//tried putting route change here as well
} catch (exception) {
alert("failure");
lastMessage = '';
}
$location.path("/chat/" + lastMessage.topic_id);
});
}
on receiving apple notifications
function onNotificationAPN(e) {
$window.localStorage.setItem('lastMessage', JSON.stringify(e));
$rootScope.$broadcast('push.message', e);
if (e.alert) {}
if (e.sound) {}
if (e.badge) {}
}
on receiving android notifications
function onNotificationGCM(e) {
$window.localStorage.setItem('lastMessage', JSON.stringify(e));
switch (e.event) {
case 'registered':
localStorage.setItem('deviceId', e.regid);
$rootScope.$broadcast('push.register', e.regid);
break;
case 'message':
//alert('broadcast');
$rootScope.$broadcast('push.message', e);
break;
case 'error':
$log.error('Error event received: ' + e);
break;
default:
$log.error('Unknown event received: ' + e);
break;
}
}
I had the same problem and solved it (a little hacky) by wrapping the location change in a timeout:
$timeout(function(){$location.path('/yourPath')},0);
I don't know why it solves the problem (at least for me), but I suppose it might be that the full angular functionality isn't available when you click the notification and postpoing the location change on the next free moment (timeout of 0) helps. It might also be that the (additional) apply, that $timeout sends does the trick...
i want to integrate a small chat / instant messaging function in my app and need a little start-up aid.
I've registered a Google Cloud Messaging Account and received a configuration file ("google-services.json", containing the project id) and a server API key.
The first question is: Do i have to make further settings in my google account so that the app gets all information needed for the messenging function?
The next question is, how to integrate the messenging function in my project.
What i've done (and what seems NOT to work):
In my index.html file, i have integrated the following code (XXXXXXXXX has been replaced with my sender ID):
<script type="text/javascript" src="PushNotification.js"></script>
<script>
var pushNotification;
function onDeviceReady() {
alert('Device is ready');
try {
pushNotification = window.plugins.pushNotification;
alert('Registering ' + device.platform);
if(device.platform == 'android' || device.platform == 'Android' ||device.platform == 'amazon-fireos' ) {
pushNotification.register(
successHandler,
errorHandler,
{
"senderID":"XXXXXXXXXXX",
"ecb":"onNotification"
});
alert('Registered the Android device');
alert('regID = ' + e.regid);
} else {
pushNotification.register(tokenHandler, errorHandler, {"badge":"true","sound":"true","alert":"true","ecb":"onNotificationAPN"});
alert('Registered the iOS device');
}
}
catch(err)
{
txt="There was an error on this page.\n\n";
txt+="Error description: " + err.message + "\n\n";
//alert(txt);
alert('Error: ' + err.message);
}
}
// handle APNS notifications for iOS
function onNotificationAPN(e) {
if(e.alert) {
// showing an alert also requires the org.apache.cordova.dialogs plugin
navigator.notification.alert(e.alert);
}
if(e.sound) {
// playing a sound also requires the org.apache.cordova.media plugin
var snd = new Media(e.sound);
snd.play();
}
if(e.badge) {
pushNotification.setApplicationIconBadgeNumber(successHandler, e.badge);
}
}
// handle GCM notifications for Android
function onNotification(e) {
alert('EVENT -> RECEIVED:' + e.event);
switch( e.event )
{
case 'registered':
if( e.regid.length > 0 )
{
// Your GCM push server needs to know the regID before it can push to this device
// here is where you might want to send it the regID for later use.
console.log("regID = " + e.regid);
alert(' REGID = ' + e.regid);
}
break;
case 'message':
// if this flag is set, this notification happened while we were in the foreground.
// you might want to play a sound to get the user's attention, throw up a dialog, etc.
if(e.foreground) {
alert('--INLINE NOTIFICATION--');
// on Android soundname is outside the payload.
// On Amazon FireOS all custom attributes are contained within payload
var soundfile = e.soundname || e.payload.sound;
// if the notification contains a soundname, play it.
// playing a sound also requires the org.apache.cordova.media plugin
var my_media = new Media("/android_asset/www/"+ soundfile);
my_media.play();
} else {
// otherwise we were launched because the user touched a notification in the notification tray.
if(e.coldstart)
//$("#app-status-ul").append('<li>--COLDSTART NOTIFICATION--' + '</li>');
alert('--COLDSTART NOTIFICATION--')
else
alert('--BACKGROUND NOTIFICATION--')
}
alert('MESSAGE -> MSG: ' + e.payload.message);
//android only
alert('MESSAGE -> MSGCNT: ' + e.payload.msgcnt);
//amazon-fireos only
alert('MESSAGE -> TIMESTAMP: ' + e.payload.timeStamp);
break;
case 'error':
//$("#app-status-ul").append('<li>ERROR -> MSG:' + e.msg + '</li>');
alert('ERROR -> MSG' + e.msg);
break;
default:
//$("#app-status-ul").append('<li>EVENT -> Unknown, an event was received and we do not know what it is</li>');
alert('EVENT -> Unknown, an event was received and we do not know what it is');
break;
}
}
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 it the token for later use.
alert('iOS Result = ' + result);
}
function successHandler (result) {
alert('Android Result = ' + result);
alert('RegID = ' + e.regid);
}
function errorHandler (error) {
alert('Error = ' + error);
}
document.addEventListener('deviceready', onDeviceReady, true);
alert('regID = ' + e.regid);
alert('Reg code completed');
</script>
As i use Phonegab Build, i have added the following line to my config.xml file
<gap:plugin name="com.phonegap.plugins.pushplugin" version="2.4.0" />
The following plugins (which are also used) have been already part of the config file:
<gap:plugin name="org.apache.cordova.dialogs" />
<gap:plugin name="org.apache.cordova.media" />
My main questions are:
Where do i have to place the Server API Key?
Where do i have to place the google-services.json file (in which directory) and how is this file linked to he index.html
Further questions:
- Is the GCM Service really free? Because in the member area there is a display "Excpected fees this month: 0,00 €" --> will the fees increase?
- If a user downloads and installs my app from the playstore: How does HE get a sender ID and if i want to send him a message --> How do I know his sender ID to start messenging with him?
I haven't understood the GCM-thing in principle.
Can anyone give me a little help?
Best regards
Daniel
The GCM service itself is free, as mentioned here.
I'm not familiar with setting up Phonegap projects, but the google-services.json file was intended for use with the Google Services plugin for Gradle. Gradle itself is a build tool used by Android Studio. I'm not sure if Phonegap has a similar plugin, but in case it doesn't, what you'll be needing is the project number/sender ID. You register your app/client with that. More on this below.
You use your server API key in your server code, which is the app server that will be sending messages to your app.
More on registration. You'll need to check with some Phonegap tutorials, because GCM's new (and recommended) way for registering is through Instance IDs. It still uses the same sender ID, but you'll need to interface with Google Play Services to do this.
I am trying to implement push notification in ionic app for Android.
I have followed step by step guide from http://docs.ionic.io/v1.0/docs/push-from-scratch.
When I am running my app on android phone, then the registered users are listed in apps.ionic.io. So user registration is working fine.
But device registration is not working.
It is giving error Cannot read property 'pushNotification' of undefined
This is my code at the top of app.js
angular.module('starter', ['ionic','ngCordova',
'ionic.service.core',
'ionic.service.push',
'starter.controllers',
'starter.services'])
.config(['$ionicAppProvider', function($ionicAppProvider) {
// Identify app
$ionicAppProvider.identify({
// The App ID (from apps.ionic.io) for the server
app_id: '',
// The public API key all services will use for this app
api_key: '',
// Set the app to use development pushes
// dev_push: true
gcm_id: ''
});
}])
Here is the code in of my controller
.controller('DashboardCtrl', function($scope,$localstorage, WildfireService, CommonUtilityService,PushNotificationService,$ionicPopup, $ionicLoading) {
PushNotificationService.identifyUser();
PushNotificationService.pushRegister();
})
Here is my services.js
.service('PushNotificationService', function($q, $ionicUser, $ionicPush) {
var PushNotificationService = this;
PushNotificationService.identifyUser = function(){
var user = $ionicUser.get();
if(!user.user_id) {
// Set your user_id here, or generate a random one.
user.user_id = $ionicUser.generateGUID();
};
// Add some metadata to your user object.
angular.extend(user, {
name: 'Technews',
bio: 'Hardcoded for now'
});
// Identify your user with the Ionic User Service
$ionicUser.identify(user).then(function(){
//alert('Identified user ' + user.name + '\n ID ' + user.user_id);
return true;
});
},
PushNotificationService.pushRegister = function(){
// Register with the Ionic Push service. All parameters are optional.
$ionicPush.register({
canShowAlert: true, //Can pushes show an alert on your screen?
canSetBadge: true, //Can pushes update app icon badges?
canPlaySound: true, //Can notifications play a sound?
canRunActionsOnWake: true, //Can run actions outside the app,
onNotification: function(notification) {
// Handle new push notifications here
// console.log(notification);
alert(notification);
return true;
}
});
}
})
Can any one tell me where is the error or what I am missing?
I have added these in index.html
<script src="lib/ionic/js/ionic.bundle.js"></script>
<script src="lib/ngCordova/dist/ng-cordova.js"></script>
<script src="lib/ionic-service-core/ionic-core.js"></script>
<script src="lib/ionic-service-push/ionic-push.js"></script>
Finally push notification is working for me. I moved the function call of pushRegister from controller to identifyUser function. So here is the new working code for me.
Controller code
.controller('DashboardCtrl', function($scope,$localstorage, WildfireService, CommonUtilityService,PushNotificationService,$ionicPopup, $ionicLoading) {
PushNotificationService.identifyUser();
})
Here is new services.js
.service('PushNotificationService', function($q, $ionicUser, $ionicPush) {
var PushNotificationService = this;
PushNotificationService.identifyUser = function(){
var user = $ionicUser.get();
if(!user.user_id) {
// Set your user_id here, or generate a random one.
user.user_id = $ionicUser.generateGUID();
};
// Add some metadata to your user object.
angular.extend(user, {
name: 'Technews',
bio: 'Hardcoded for now'
});
// Identify your user with the Ionic User Service
$ionicUser.identify(user).then(function(){
//alert('Identified user ' + user.name + '\n ID ' + user.user_id);
PushNotificationService.pushRegister();
return true;
});
},
PushNotificationService.pushRegister = function(){
// Register with the Ionic Push service. All parameters are optional.
$ionicPush.register({
canShowAlert: true, //Can pushes show an alert on your screen?
canSetBadge: true, //Can pushes update app icon badges?
canPlaySound: true, //Can notifications play a sound?
canRunActionsOnWake: true, //Can run actions outside the app,
onNotification: function(notification) {
// Handle new push notifications here
// console.log(notification);
alert(notification);
return true;
}
});
}
})
I don't know about this new Ionic push notifications. I succesfully implemented push notifications in my Ionic App with ngCordova's push plugin for both Android an iOS (http://ngcordova.com/docs/plugins/pushNotifications/) just by following the examples there. The key is to put the code in the .run module in app.js.
Here is the code:
angular.module('notPush', ['ionic','notPush.controllers','notPush.factorys','ngCordova','ionic.service.core'])
.run(function($ionicPlatform, $rootScope, $http, $cordovaPush) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if(window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if(window.StatusBar) {
StatusBar.styleDefault();
}
// Manejador de notificaciones push para Android
if (ionic.Platform.isAndroid()){
var androidConfig = {
"senderID": "94XXXXXXXXXX", // ID HERE
"ecb": "window.casosPush"
};
try{
var pushNotification = window.plugins.pushNotification;
} catch (ex){
}
// Llamada en caso de exito
var successfn = function(result){
alert("Success: " + result);
};
// Llamada en caso de error
var errorfn = function(result){
window.alert("Error: " + result);
};
// Llamada de casos de notificacion push
window.casosPush = function(notification){
switch (notification.event){
case 'registered':
if (notification.regid.length > 0){
alert('registration ID = ' + notification.regid);
}
break;
case 'message':
alert(JSON.stringify([notification]));
break;
case 'error':
alert('GCM error = ' + notification.msg);
break;
default:
alert('An unknown GCM event has occurred');
break;
}
};
try{
// Llamada de registro con la plataforma GCM
pushNotification.register(successfn,errorfn,androidConfig);
} catch(notification){
}
}
})
Just remember to install the plugin with
cordova plugin add https://github.com/phonegap-build/PushPlugin.git