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
});
Related
I update a timestamp in a Firebase server every time I click a button on my react-native app (android).
The problem is that, after updating it, I want to read it and set my state with this timestamp.
Here is some code I found on the Internet, it updates the date on Firebase, reach the first 'then' block but then never go on, so never reach the second 'then' block and never show the alert(onlyDate);
I have no error about rules on Firebase, read and write are both available.
getDateServerFirebase = () => {
let fb_currentTime = firebase.database().ref('currentTime/');
fb_currentTime.update({ time: firebase.database.ServerValue.TIMESTAMP })
.then(() => {
fb_currentTime.once('value').then(function (data) {
//console.log(data);
let timestamp = data._value.time;
let fullDate = new Date(timestamp);
let onlyDate = fullDate.getDate() + '/' + (fullDate.getMonth()+1) + '/' + fullDate.getFullYear();
alert(onlyDate);
}, function serverTimeErr(err) {
console.log('Could not reach to the server time !');
});
}, function (err) {
console.log ('set time error:', err)
});
}
I tried this and still the same problem: writing works, reading not.
setData = () =>{
firebase.database().ref('prova/').set({
name:'luis',
surname:'rew'
}, function(error) {
if (error) {
// The write failed...
} else {
// Data saved successfully!
}
});
}
readData = () =>{
firebase.database().ref('prova/')
.once('value')
.then((data)=>{
alert(data);
})
}
Can someone help me??
The way you access response from firebase function is through running the val(); function on the result.
change this line
let timestamp = data._value.time;
into this:
let timestamp = data.val().time;
I intend to get users geolocation even when the app sits dormant in the background and store the same in the database.
I'm using katzer's Cordova Background Plug-in,
When I try to access navigator.geolocation.getCurrentPosition inside backgroundMode.onactivate function, nothing happens, Whereas when I try passing hard coded values api is called, data is stored in database.
following is my code
document.addEventListener('deviceready', function() {
// Android customization
cordova.plugins.backgroundMode.setDefaults({
text: 'Doing heavy tasks.'
});
// Enable background mode
cordova.plugins.backgroundMode.enable();
// Called when background mode has been activated
cordova.plugins.backgroundMode.onactivate = function() {
console.log('inside background')
a();
}
var a = function() {
console.log('a called')
navigator.geolocation.getCurrentPosition(function(pos) {
console.log('inside navigate');
var data = {
Lati: '123456',
Longi: '132456',
//LoginID: JSON.parse(window.localStorage.getItem('LoginId'))
EmpCode: localStorage.getItem('LoginId')
};
$http.post("https://app.sbismart.com/bo/ContactManagerApi/UpdateEmployeeLoc", data).success(function(rsdata, status) {
console.log('inside rsdata');
console.log(data.Lati + "," + data.Longi);
})
}, function(error) {
alert('Unable to get location: ' + error.message);
});
}
}, false);
cordova.plugins.backgroundMode.onfailure = function(errorCode) {
console.log(errorCode)
};`
and check as to why is it failing....then again u need to run the locationService function in a timeout function in the background to get updated about the location and check the location from previously got location.
Something like this...
cordova.plugins.backgroundMode.onactivate = function () {
setTimeout(function () {
a();
}, 5000);
}
Hope this helps.
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 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
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