PushPlugin register function does not give regid - javascript

I have added in <gap:plugin name="com.phonegap.plugins.pushplugin" /> config.xml. When I run the app it shows alert "Callback Success! Result = OK" even when phone is not connected to internet then I press OK and nothing else happens.
onNotificationGCM event does not fire and so it never returns regid.
function showAlert(message, title) {
if (navigator.notification) {
navigator.notification.alert(message, null, title, 'OK');
} else {
alert(title ? (title + ": " + message) : message);
}
}
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
$(document).ready(function () {navigator.splashscreen.hide();});
try {
var pushNotification = window.plugins.pushNotification;
pushNotification.register(successHandler, errorHandler, {"senderID":"659859389520","ecb":"onNotificationGCM"});
} catch (ex) {
showAlert(ex, 'push error');
}
setTimeout(function() {
navigator.splashscreen.hide();
}, 3000);
}
function successHandler(result) {
showAlert('Callback Success! Result = '+result, "Success");
}
function errorHandler(error) {
showAlert(error, "Error");
}
function onNotificationGCM(e) {
switch( e.event )
{
case 'registered':
if ( e.regid.length > 0 )
{
console.log("Regid " + e.regid);
showAlert('registration id = '+e.regid);
}
break;
case 'message':
showAlert('message = '+e.message+' msgcnt = '+e.msgcnt, "Message");
break;
case 'error':
showAlert('GCM error = '+e.msg, "Error");
break;
default:
showAlert('An unknown GCM event has occurred', "Unknown Event");
break;
}
}
In the ADB log GCM is working absolutely fine. It is returning a regid perfectly but sendJavascript is not calling my onNotificationGCM function. And therefore it is not working. Why? What I am doing wrong here?
05-22 01:28:27.407: V/PushPlugin(21372): sendJavascript: javascript:onNotificationGCM({"regid":"APb91bG...Sqg4YP","event":"registered"})

Solved the issue. I was redirecting from index.html to another page before onNotificationGCM could be called. Therefore it was not being called at all.
To test I placed the redirection code inside onNotificationGCM and it works perfect.

Related

service-worker.js catch updatefound before running other custom functions

Is there a way to check if the service worker found an update before loading custom functions?
i have this function which is working, but it runs the custom functions twice, and seems very untidy..
I'm looking for a way to only run the custom functions once, and not when an update was found and installed. When an update is found, the user || the page will reload automatically and then the custom functions can run normally..
I added the reg.events in this function to determine where to place my custom functions. I hope this question is understandable..
function installApp(path, scope) {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register(path, {
scope: scope
}).then((reg) => {
// event listener to catch the prompt if any and store in
// an instance for later use with add to homescreen() function.
getPrompt();
// this is a custom alert type notification
makeProgress('System','is ok');
/* THIS IS THE UPDATE FOUND FUNCTION */
reg.onupdatefound = function() {
var installingWorker = reg.installing;
installingWorker.onstatechange = function() {
switch (installingWorker.state) {
case 'installed':
if (navigator.serviceWorker.controller) {
// the _clear() function removes items from the locaforage db to
// force the app to not auto login, but let the user
// login again to refresh any data when the page reloads
_clear('uuid');
_clear('user');
_clear('token');
makeProgress('new version','reload app');
} else {
// removes any custom notifications
clearProgress();
//just go into the app because everything is loaded.
//We dont need to reinstall the
//homescreen or listen for the homescreen because this
//is an update and the homescreen should already be installed?
enterApp();
}
break;
case 'redundant':
// removes any custom notifications cause
//the install is complete
clearProgress();
enterApp();
console.log('The installing service worker became redundant.');
break;
}
};
return;
};
/** Here is the events that fire during the install
// process and where i am currently stuck **/
if (reg.installing) {
makeProgress('updating','files');
/* THE SERVICE WORKER IS DOWNLOADING THE CACHE FROM THE SERVER */
} else if (reg.waiting) {
/* what message here ?*/
/* as far as i can tell, THE SERVICE WORKER IS WAITING FOR
*//*PREVIOUS SERVICE WORKER TO BEREFRESHED SO A RELOAD */
/*UI SHOULD COME HERE??*/
} else if (reg.active) {
/* what message here ?*/
/* IS THIS THE BEST PLACE TO RUN THE BELOW CUSTOM
*//*FUNCTIONS?? WILL //THEY ALWAYS FIRE */
}
/** AT WHICH OF THE EVENTS ABOVE WILL I ADD THE FUNCTIONS FROM HERE **/
requestWakeLock();
const browserFeatures = detectFeatures(reg);
setCompatibilityArray(browserFeatures);
localforage.ready().then(function() {
localforage.getItem('homescreen').then(function (value) {
if(value != 1){
if (platform == 'iPhone' || platform == 'iPad') {
installHome();
} else {
makeProgress('waiting', 'prompt');
waitPrompt();
}
return;
} else {
enterApp();
return;
}
}).catch(function (err) {
alertIt('something went wrong. Please refresh the page to try again. If the problem persists, try another browser.</br>', 'warning', 0);
return;
});
}).catch(function (err) {
alertIt('Something went wrong.<br>Please refresh the page to restart the installation process.<br>'+err, 'danger', 0);
return;
});
/** TO HERE, WITHOUT RUNNING THESE FUNCTION DURING*/
/*THE ONUPDATEFOUND EVENT AS THEN THEY WILL RUN TWICE**/
}, (err) => {
alertIt('Something went wrong.<br>Please refresh the page to restart the installation process.<br>', 'danger', 0);
})
} else {
alertIt('This browser is not compatible with this app.<br>Please try to use a different browser to install this application.<br>', 'danger', 0);
return;
}
}
I initialize this script like so:
window.addEventListener("load", () => {
makeProgress('Checking','system');
installApp(appsPath, appScope);
})
basically they must not be invoked if a new update is found..
I discovered that the onupdate function runs when old service worker is active..
If the onupdate function fires it changes a variable to a true value
I then used a time out function in the active event to see if a variable had changed... if it did change then i return false, and let the onupdate functions continue their course.. otherwise i continue to load my custom functions...Its working, but it doesn't seem like the best way.
Do you have a better method?
so like this:
function installApp(path, scope) {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register(path, {
scope: scope
}).then((reg) => {
getPrompt();
makeProgress('refreshing','files');
var entApp = true;
reg.onupdatefound = function() {
entApp = false;
var installingWorker = reg.installing;
installingWorker.onstatechange = function() {
switch (installingWorker.state) {
case 'installed':
if (navigator.serviceWorker.controller) {
_clear('uuid');
_clear('user');
_clear('token');
makeProgress('new version','reloading app');
setTimeout(function(){
location.reload();
}, 2500);
return;
} else {
/*NOT SURE WHAT IS SUPPOSED TO GO HERE, SO I JUST RELOADED THE PAGE*/
makeProgress('new version','reloading app');
setTimeout(function(){
location.reload();
}, 2500);
return;
}
break;
case 'redundant':
/*NOT SURE WHAT IS SUPPOSED TO GO HERE, SO I JUST RELOADED THE PAGE*/
makeProgress('new version','reloading app');
setTimeout(function(){
location.reload();
}, 2500);
return;
break;
}
};
return;
};
if (reg.active) {
/** RIGHT HERE IS WHERE THE ONUPDATE FIRES. I GAVE IT A
2.5 SECONDS TO DO ITS THING, THEN CHECKED TO SEE IF THERE WAS
AN UPDATE, IF NO UPDATE THEN I RUN MY CUSTOM FUNCTIONS, OTHERWISE
THE ONUPDATE FUNCTION RELOADS THE PAGE AND THE UPDATED SW.JS FILE
WILL THEN RUN THESE FUNCTIONS WHEN ITS ACTIVE.. IS THERE A BETTER
IN-BUILT METHOD TO DO THIS?**/
setTimeout(function(){
if(entApp === true){
requestWakeLock();
const browserFeatures = detectFeatures(reg);
setCompatibilityArray(browserFeatures);
localforage.ready().then(function() {
localforage.getItem('homescreen').then(function (value) {
if(value != 1){
if (platform == 'iPhone' || platform == 'iPad') {
installHome();
} else {
makeProgress('waiting', 'prompt');
waitPrompt();
}
return;
} else {
enterApp();
return;
}
}).catch(function (err) {
alertIt('something went wrong. Please refresh the page to try again. If the problem persists, try another browser.</br>', 'warning', 0);
return;
});
}).catch(function (err) {
alertIt('Something went wrong.<br>Please refresh the page to restart the installation process.<br>'+err, 'danger', 0);
return;
});
}
}, 2500);
}

jQuery on Button Click in mobile devices

I have a Button
d3.select("#updatebutton").on("click", function(e) {
try{
$.get('any url', function(data) {
alert('Any Alert Message');
window.location.href = window.location.href;
});
}
catch (e) {
alert('Error: ' + e);
}
}
where i want to do certain actions on the button click event:
app.get('any url', function(req, res, next) {
try{
anyfunction();
}
catch(e) {
alert('Error');
}
});
It is working fine on normal web browser, however if I open my webpage on a mobile device, it seems that the click event is never called and nothing happens. Is this a jQuery Problem or am I missing something?
The Code is running on a node.js Server.
Hope anyone can help.
UPDATE:
I'm using jade as rendering-engine for HTML. My Button looks like the following:
div#updatebutton
i.fa.fa-repeat.fa-lg
| 'some description'
Try with touchstart event.
UPDATE
Please check.
var myButton = d3.select("#updatebutton");
myButton.on("touchstart", onDown);
function onDown() {
alert("Work");
try{
$.get('any url', function(data) {
alert('Any Alert Message');
window.location.href = window.location.href;
});
}
catch (e) {
alert('Error: ' + e);
}
}
You can detect user device using navigator object. Refer this
If device is touch enabled then use touchstart/touchend events or use click events for desktops(click events should work in mobile browsers too, can not guess the reason by going through the provided code)
Try this:
function is_touch_device() {
return (('ontouchstart' in window) || (navigator.MaxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0));
}
var myButton = d3.select("#updatebutton");
var myEvent = is_touch_device() ? 'touchend' : 'click';
myButton.on(myEvent, onDown);
function onDown() {
$.get('any url', function(data) {
alert('Any Alert Message');
window.location.reload(); //better way to reload the page
}).fail(function(error) {
console.log(error);
});
}

How to open specific page in the app on clicking Push Notification?

I am working on an Android app using cordova and implemented a push notification system using the cordova $PushPlugin.
My PushPlugin code (source):
module.run(function($rootScope,$cordovaPush) {
var androidConfig = {
"senderID": "replace_with_sender_id",
};
document.addEventListener("deviceready", function(){
$cordovaPush.register(androidConfig).then(function(result) {
// Success
}, function(err) {
// Error
})
$rootScope.$on('$cordovaPush:notificationReceived', function(event, 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;
}
});
// WARNING: dangerous to unregister (results in loss of tokenID)
$cordovaPush.unregister(options).then(function(result) {
// Success!
}, function(err) {
// Error
})
}, false);
});
On clicking the push notification received, I want to redirect the user to a specified page in my app. I referred this(based on phonegap pushplugin) but could not figure out a solution. Any help will be appreciated.
This is a simple solution without using any angular routes.
case 'message':
if (notification.foreground === false){
window.location = '#/abc';
window.location.reload();
}
If you check structure of object notification, you will see that there is an attribute foreground, which will be false when you come to app from clicking notification. You can use that to put your logic
case 'message':
if(notification.foreground === false){
//add logic for navigation to your specific page i.e $state.go('myPage')
}

Cordova PushNotification onNotificationGCM is not called

I am doing pushnotification for both Android/IOS.
I have used a cordova push-plugin https://github.com/phonegap-build/PushPlugin, it seems to work great.
Info : I'm on a AngularJS project.
In my NotificationHelper factory i have this init method:
helper.init = function() {
// Instanciate push plugin notification
var pushNotification = window.plugins.pushNotification;
var errorHandler = function(error) {
logger.debug('errorHandler = ' + error);
};
if ($rootScope.isAndroid()) {
var senderId = CONFIG.NOTIFICATION_ANDROID_SENDER_ID;
pushNotification.register(function(result) {
logger.debug('successHandler = ' + result);
}, errorHandler, {
'senderID' : senderId,
'ecb' : 'onNotificationGCM'
});
}
};
I also defined those methods on mains.js :
var onNotificationGCM = function(event) {
// call back to web service in Angular.
var elem = angular.element(document.querySelector('[ng-app]'));
var injector = elem.injector();
var service = injector.get('NotificationHelper');
service.onNotificationGCM(event);
};
It's a trick to call angularJS factory from main javascript.
'onNotificationGCM' call the 'NotificationHelper.onNotificationGCM' method :
helper.onNotificationGCM = function(e) {
switch (e.event) {
case 'message':
// Notification happened while app was in the foreground
if (e.foreground) {
logger.debug('[notification] [message] Foreground : ' + JSON.stringify(e));
} else { // Notification touched in the notification tray
logger.debug('[notification] [message] Background : ' + JSON.stringify(e));
if (e.coldstart) {
// App was not running and user clicked on notification
} else {
// App was running and user clicked on notification
}
}
decriptPayloadNotification(e.payload);
break;
case 'registered':
logger.debug('[notification] [registered] : ' + JSON.stringify(e));
if (e.regid.length > 0) {
registerUser(e.regid, 'gcm');
}
break;
case 'error':
logger.debug('[notification] [error] : ' + JSON.stringify(e));
break;
default:
logger.debug('[notification] [default] : Unknown, an event was received and we do not know what it is : ' + JSON.stringify(e));
break;
}
};
During the first use, everything work good :
'Registered' event is received
Notifications are received
When i'm on foreground I receive 'message' event :
NotificationHelper: [notification] [message] Foreground : {"event":"message","from":"847593779913","message":"Agenêts 23/03 10h\r\n","collapse_key":"do_not_collapse","foreground":true,"payload":{"lt":"school","lv":"E1154","notId":"35429","title":"Agenêts le 23/03/2015","message":"Agenêts 23/03 10h\r\n"}}
When i'm on background, if i receive notif and touche it on notification tray, I receive 'message' event :
NotificationHelper: [notification] [message] Background : {"event":"message","from":"847593779913","message":"la piscine sera fermée 1 journée pour raison technique","coldstart":false,"collapse_key":"do_not_collapse","foreground":false,"payload":{"lt":"swimming pool","lv":"E114","notId":"29869","title":"23/04/2015 fermeture de la piscine","message":"la piscine sera fermée 1 journée pour raison technique"}}
BUT, if i kill my app, everything stop to work.
If i restart app, i will not receive anymore 'message'event and 'onNotificationGCM' will not be called.
I founded some articles speaking about this problem, but without success :
Stackoverflow : Phonegap PushNotification to open a specific app page
Does anyone has an idea about this problem ?
If you are using node-gcm as push notification server side I hope this might help for your question:
things to check:
use adb logcat from console and check your device logs to see if your device receives any notification (you should see some logs from gcmservices if you receive). I believe you should see some logs because otherwise you probably wouldn't get any notification when the app is on foreground either.
check if you add "title" and "message" keys on your message data (this draw me crazy before)
check if delayWhileIdle parameter is false
sample message variable and method i am using is below:
var pushAndroidSender = new gcm.Sender('Your GoogleApi Server Key Here');
var message = new gcm.Message({
collapseKey: 'demo',
delayWhileIdle: false,
timeToLive: 3,
data: {
"message":"What's up honey?",
"title":"Come on"
}
});
pushAndroidSender.send(message, registrationIds, function(err, result) {
if (err) {
console.error("this is an error: " + err);
} else {
console.log("this is a successful result:" + result);
}
});
I was asking myself why it worked correctly the first time and not the following times...and i had this idea :
maybe callback function is subscribed to plugin first time but not the next times.
And this is exactly the source of my problem. I call "pushNotification.register" only one time to init plugin and get ids...
But the next time I launch app, i don't instanciate again the plugin, so pushplugin don't know which method to call in callback request.
So answer is : Call "pushNotification.register" in each application launch !
In my code, i have to call method below on each "deviceready" event :
helper.init = function() {
// Instanciate push plugin notification
var pushNotification = window.plugins.pushNotification;
var errorHandler = function(error) {
logger.debug('errorHandler = ' + error);
};
if ($rootScope.isAndroid()) {
var senderId = CONFIG.NOTIFICATION_ANDROID_SENDER_ID;
pushNotification.register(function(result) {
logger.debug('successHandler = ' + result);
}, errorHandler, {
'senderID' : senderId,
'ecb' : 'onNotificationGCM'
});
}
};

Disable button if geolocation is unavaliable

So i've got a main page where there's 3 buttons - login, register and recover account. I want to disable all those buttons and display a message when geolocation is unavaliable or the user has not allowed the browser to share it's location.
$scope.btnDisabled = false;
$scope.errorMsg = null;
$scope.checkBrowser = function () {
if (navigator.geolocation.getCurrentPosition) {
// let's find out where you are!
console.log("Got your location");
$scope.btnDisabled = false;
} else {
$scope.errorMsg = "Warning. Could not locate your position. Please enable your GPS device.";
//disable the buttons
$scope.btnDisabled = true;
//Show errorMessage
return true
}
//errorMessage visibility is set false
return false;
}
So far i haven't managed to disable the buttons or show errorMessage(except for an alert message).
This is how i got the alert message:
function getPosition() {
console.group("geoloc getPosition");
if (window.navigator) {
console.log("api supported");
navigator.geolocation.getCurrentPosition(success, error);
} else {
console.log("api fallback");
}
console.groupEnd();
}
function success(pos) {
console.log("geoloc pos ", pos);
}
function error(err) {
alert("Geolocation identification failed.");
$scope.btnDisabled = true;
}
Why doesn't the $scope.btnDisable work in error() function?
You should use
navigator.geolocation.getCurrentPosition(
function() {
$scope.btnDisabled=false;
$scope.$apply();
}, function() {
$scope.btnDisabled=true;
$scope.$apply();
}
});
It is verry important to know, that getCurrentPosition will call a callback instead of returning something! See https://developer.mozilla.org/en-US/docs/Web/API/Geolocation.getCurrentPosition
You've also to call $scope.$apply() as you'll disable any angular updates while processing non angular callbacks!
Do so in your 2nd example and the button state should get updated

Categories