Adobe PhoneGap Build (iOS) and PushWoosh - ios

According to the docs at PushWhoosh:
http://www.pushwoosh.com/programming-push-notification/phonegap-build-push-plugin-integration/
I should be able to use Adobe's Build cloud service to build PhoneGap apps. I've followed the instructions in the docs, but can't get my app to register with the PushWhoosh service (i.e.: it's not sending a device token).
I think the issue has to do with the registration of the plugin in config.xml. According to the Adobe Build docs, the only push plugin supported is their "GenericPush", which I've added to my config.xml file like so:
I've also whitelisted the pushwhoosh.com domain.
In my index.html file, I have the function initPushwhoosh, which gets called when the device is ready:
function initPushwoosh() {
try {
var pushNotification;
pushNotification = window.plugins.pushNotification;
if (device.platform == 'android' || device.platform == 'Android') {
pushNotification.register(successHandler, errorHandler, { "senderID": "replace_with_sender_id", "ecb": "onNotificationGCM" });
}
else {
pushNotification.register(tokenHandler, errorHandler, { "badge": "true", "sound": "true", "alert": "true", "ecb": "onNotificationAPN" });
}
}
catch (err) {
alert(err.message + "\n\n" + err.name);
}
}
And my tokenHandler function (I'm building for iOS) looks like:
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.
PushWoosh.appCode = "E0313-D27FA";
PushWoosh.register(result, function (data) {
alert("PushWoosh register success: " + JSON.stringify(data));
}, function (errorregistration) {
alert("Couldn't register with PushWoosh" + errorregistration);
});
}
Through debugging, it looks like the "pushNotification.register" function never gets called, and the try/catch statement doesn't display any error messages. That function is:
// Call this to register for push notifications. Content of [options] depends on whether we are working with APNS (iOS) or GCM (Android)
PushNotification.prototype.register = function (successCallback, errorCallback, options) {
alert("about to register");
if (errorCallback == null) { errorCallback = function () { } }
if (typeof errorCallback != "function") {
alert("PushNotification.register failure: failure parameter not a function");
return;
}
if (typeof successCallback != "function") {
alert("PushNotification.register failure: success callback parameter must be a function");
return;
}
cordova.exec(successCallback, errorCallback, "GenericPush", "register", [options]);
};
My thinking is that it has to do with the plugin declaration (<gap:plugin name="GenericPush" />) in config.xml; I've tried changing it to (based on some other sample code I found):
<gap:plugin name="PushPlugin"/>
But that didn't work either. Note: when I did this, I tried changing:
cordova.exec(successCallback, errorCallback, "GenericPush", "register", [options]);
to
cordova.exec(successCallback, errorCallback, "PushPlugin", "register", [options]);
The complete code can be found here:
https://github.com/appburnr/PushWhooshTest
I've tripled-checked the my PushWhoosh AppID is correct, but I can never get the app to appear as registered device in my PushWhoosh control panel.
Any ideas?

Are you sure this code is correct?
pushNotification.register(successHandler, errorHandler, { "senderID": "replace_with_sender_id", "ecb": "onNotificationGCM" });
Shouldn't it be the Project ID from GCM? It might explain why the device doesn't register for push notifications.

I'm not familiar with PushWoosh, but they do have a guide to how to achieve this with Build here:
http://www.pushwoosh.com/programming-push-notification/phonegap-build-push-plugin-integration/
Have you followed each step?

If you still haven't had success (I hope you have) try this guide:
http://www.raywenderlich.com/32960/apple-push-notification-services-in-ios-6-tutorial-part-1
I've built a solution using push notifications myself now, and found my biggest issue was that I hadn't set up the certificates. This guide is perfect.
ALSO remember that push notifications won't work in the emulator, only on a real device.

Related

Notifications.getExpoPushTokenAsync not working on Stand Alone iOS

I'm trying to my expo/react-native project to send push notifications to my server. It works on standalone Android, but not stand alone iPhone.
The standalone iPhone app never sends the token.
Since the app sends nothing without error, I tried removing:
if (finalStatus !== 'granted') { return; }
This didn't work either.
export async function registerForPushNotificationsAsync(token) {
const { status: existingStatus } = await Permissions.getAsync(
Permissions.NOTIFICATIONS
);
let finalStatus = existingStatus;
// Only ask if permissions have not already been determined, for iOS.
if (existingStatus !== 'granted') {
const { status } = await Permissions.askAsync(Permissions.NOTIFICATIONS);
finalStatus = status;
}
// Stop here if the user did not grant permissions
if (finalStatus !== 'granted') {
return;
}
// Get the push token that uniquely identifies this device
let expoToken = await Notifications.getExpoPushTokenAsync();
// Post new push token to backend for user
return axios({
method: 'POST',
url: `${str.ROOT_URL}/account/push/`,
headers: {
Authorization: `Token ${token}`
},
data: {
"token": expoToken,
"status": finalStatus
}
});
}
I expected the token to get sent to the backend, but nothing is sent on the standalone iOS app.
Please let me know if you know a workaround or had this issue before. Thanks!
I think it's too late to give an answer, but I spent 2 days to resolve it... I hope it helps somebody.
Instead this:
import * as Notifications from "expo-notifications";
Try this:
import { Notifications } from "expo";

Titanium: Check iOS notifications upon opening the app without clicking the notification

I am trying to handle push notifications on iOS.
My simple code looks something similar to this:
var Cloud = require("ti.cloud");
var deviceToken = null;
var deviceToken = Ti.App.Properties.getString('deviceToken');
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
]
});
Ti.App.iOS.addEventListener('usernotificationsettings', function registerForPush() {
Ti.App.iOS.removeEventListener('usernotificationsettings', registerForPush);
Ti.Network.registerForPushNotifications({
success: function(e) {
if (e.deviceToken !== Ti.App.Properties.getString('deviceToken', null)) {
deviceToken = e.deviceToken;
Ti.App.Properties.setString('deviceToken', deviceToken)
subscribeToChannel();
} else {
Ti.API.info('Already registered for push notifications!');
}
},
error: function(e) {
Ti.API.error('Failed to register for push notifications: ' + e.error);
},
callback: receivePush
});
});
function subscribeToChannel () {
Cloud.PushNotifications.subscribeToken({
device_token: deviceToken,
channel: 'general',
type: Ti.Platform.name == 'android' ? 'android' : 'ios'
}, function (e) {
alert(e.success === true ? 'Subscribed' : 'Error!');
});
}
// When receieve interactive remote notification
Ti.App.iOS.addEventListener('remotenotificationaction', function(e) {
alert('remotenotificationaction: ' + JSON.stringify(e));
});
// When receieve interactive notification in the background
Ti.App.iOS.addEventListener('localnotificationaction', function(e) {
alert('localnotificationaction');
});
// When receieve interactive notification in the foreground
Ti.App.iOS.addEventListener('notification', function(e) {
alert('notification');
});
function receivePush(e) {
alert('receivePush');
}
For the most part everything works fine. The following happens when I send a remote push notification:
When the app is in the background, a notification appears. Upon clicking the notification, I get the "receivePush" message, as expected
When the app is in the foreground, a notification does not appear, but I still get the "receivePush" message, as expected.
However, when I receive a notification while the app is in the background, and then click on the app directly (i.e. not clicking the notification), none of the above events is triggered!
How can I make sure an event is triggered for the last case.
I don't think this is possible since your callback function is assigned with a notification behavior, not app starting. This is not a Titanium problem but a workflow misunderstanding if you know what I mean.
I think for you is best to always check something when the app starts, not related to notifications.

Potential causes of Ionic function not working in Ionic View, but working on web

I am building a food delivery app using Ionic. And I am having problems getting the app to work on mobile for the address creation step. After creating an account the user must create a delivery address, at which point the app figures out what delivery location to use.
Address creation works in Chrome (ionic serve) and in iOS simulator (ionic run ios -l -c -s).
However, once I've uploaded the app to my Ionic View iOS app for testing, it gets stuck at the Address creation step.
But at the address creation step, the Ionic loading wheel starts but it doesn't go away and there is no state transition to the menu.
Here is the implementation in the controller.
Address.create($scope.newAddress, $scope.user)
.then(function(response) { // never gets a response back in Ionic View
console.log("address created");
user.save(null,
{ success: function(user) {
// success callback
}, error: function(error) {
// throw error
}
});
}, function(error) {
// throw error
});
The Address.create() method I have implemented is fairly lengthy:
...
.factory('Address', ['$http', '$q', 'PARSE_HEADERS'
function ($http, $q, PARSE_HEADERS) {
return {
create: function(data, userID) {
var deferred = $q.defer();
var zipArray = ['1111','22222','33333'];
var inZone = false;
var restaurantCoords = {
latitude: 11.11111, longitude: 22.22222
};
for (var i=0, bLen=zipBrooklyn.length; i<bLen; i++) {
if(data.zipCode==zipArray[i]) {
inZone = true;
}
}
if (inZone == true ) { // valid zip
function onSuccess(coords) {
var limit = 3041.66;
var meters = getDistance(coords, restaurantCoords);
if (meters < limit) {
$http.post('https://api.parse.com/1/classes/Address', data, {
headers: PARSE_HEADERS
})
.success(function(addressData) {
deferred.resolve(addressData);
})
.error(function(error, addressData) {
deferred.reject(error);
});
}
function onError() {
deferred.reject("Unable to Geocode the coordinates");
}
// GET COORDS
navigator.geocoder.geocodeString(onSuccess, onError, data.address1 + ',' + data.zipCode);
}
}
return deferred.promise;
}]);
I've stripped out all of the code that I believe was working.
So a valid answer for this question could take multiple forms:
I'd accept an answer giving a decent way to debug apps IN Ionic View.
Or, if someone could provide an answer as to why it might be working in the browser and in iOS Simulator, but not iOS itself, that would be appreciated even more.
Ionic view doesn't support all the plugins yet. please take a look at this link for the list of supported plugins.
Device is always better (First Option). If you have a ios device and apple developer account. You can create and configure the required certificate with the device id and run the app using 'ionic run ios'. Second option is iOS simulator. You can use the simulator for your whole app, though few tasks would need a device.
Even if you use the simulator for the whole development, it is always advisable to test in the device before launcing the app.

Cordova/Phonegap iOS Parse-Push Plugin

I have spent lot of time to find correct cordova plugin for parse push notifications for both Android & iOS platforms.
My requirements are:
To receive parse push notification (in both android & iOS)
Able to store all the incoming push notifications in mobile local storage Sqlite.
I have tried all the below parse push cordova plugins for both Android & iOS platforms.
https://github.com/avivais/phonegap-parse-plugin
https://github.com/taivo/parse-push-plugin
https://github.com/campers/parse-push-plugin
https://github.com/manishiitg/parse-push-plugin
For Android: All the above plugins are working perfectly to fulfill my above mentioned requirements.
For iOS: Only 1st plugin i.e https://github.com/avivais/phonegap-parse-plugin is working. And that too i was not able to save the notifications in local storage sqlite. That means only my 1st requirement is fulfilled but not my 2nd requirement.
All the github pages of remaining plugins (i.e 2nd, 3rd, 4th) states that:
"Please note that I've only worked on the Android aspect of this fork. The iOS side is not yet up to date."
Is there any plugin which will work for both Android & iOS platforms to fulfill my 2 requirements?
(or)
If there is no common plugin for both the platforms, then how can I store the incoming plugins in iOS sqlite?
Please help me. Thanks in advance.
I happen to maintain https://github.com/taivo/parse-push-plugin
It looks like you caught my fork at its infancy. I picked it up when the upstream fork seemed stagnant for a while and at that time I was only addressing the Android aspect. Since then I've provided full iOS support. And it works for parse-server as well as the out-going parse.com. I also did one better and made installation just a matter of
cordova add https://github.com/taivo/parse-push-plugin
and writing a few config.xml tags to indicate server url, and app id.
That should take out the big pain of manually messing with Android Manifest, Java, and Objective C when setting up the plugin.
It should now meet or exceed your requirement. To receive push notification and store in sqlite, all you have to do is set an event handler in javascript. Be sure to wrap it with some sort of device ready or platform ready event handler to ensure the plugin has properly loaded.
$ionicPlatform.ready(function(){
if(window.ParsePushPlugin){
ParsePushPlugin.on('receivePN', function(pn){
console.log('yo i got this notif:' + JSON.stringify(pn) );
//
// do your sqlite storage here
//
});
}
});
You just might be interested in the Azure Push Notifications. It combines both Push notification services so you can send messages to both devices from one central point.
I quote:
Notification Hubs A scalable, cross-platform solution for sending push
notifications to mobile devices, Notification Hubs works well with
Cordova apps. Notification Hubs manages the registrations with each
PNS. More important, Notification Hubs lets you create template
registrations so you can send messages to all registered devices,
regardless of platform, with only a single line of code. You can also
use tags to send targeted notifications only to devices with specific
registrations. For more information about Notification Hubs, see the
Azure Web site at aka.ms/nkn4n4.
Here i have a helper class for registering your device with the pushnotification service. For sending push notifications, you can use an azure portal and send styled push notifications in json format.
var Pushman = {
Initialize: function (hubConnString, hubName, gcmSenderId, callbackRegistered, callbackUnRegistered, callbackInlineNotification, callbackBackgroundNotification, callbackError) {
//store connection and callback information on app startup for Push Registration later
Pushman.HubConnectionString = hubConnString;
Pushman.HubName = hubName;
Pushman.GcmSenderId = gcmSenderId;
//callbacks
Pushman.RegisteredCallback = callbackRegistered;
Pushman.UnRegisteredCallback = callbackUnRegistered;
Pushman.NotificationForegroundCallback = callbackInlineNotification;
Pushman.NotificationBackgroundCallback = callbackBackgroundNotification;
Pushman.ErrorCallback = callbackError;
},
RegisterForPushNotifications: function (tags) {
//setup Azure Notification Hub registration
Pushman.Hub = new WindowsAzure.Messaging.NotificationHub(Pushman.HubName, Pushman.HubConnectionString, Pushman.GcmSenderId);
Pushman.Hub.registerApplicationAsync(tags).then(Pushman.onRegistered, Pushman.onError);
//setup PushPlugin registration
Pushman.Push = window.PushNotification;
var push;
//register depending on device being run
if (device.platform == 'android' || device.platform == 'Android' || device.platform == "amazon-fireos") {
//android
push = Pushman.Push.init(
{ "android": { "senderID": Pushman.GcmSenderId } }
);
push.on('registration', Pushman.onRegistered);
push.on('notification', Pushman.onAndroidNotification);
push.on('error', Pushman.onError);
} else {
//iOS
push = Pushman.Push.init(
{ "ios": { "alert": "true", "badge": "true", "sound": "true" } }
);
push.on('registration', Pushman.onRegistered);
push.on('notification', Pushman.onIOSNotification);
push.on('error', Pushman.onError);
}
},
UnRegisterForPushNotifications: function () {
if (Pushman.Hub != null) {
//dont pass through error handler
//unreg azure
Pushman.Hub.unregisterApplicationAsync()
.then(Pushman.onUnRegistered, null);
//unreg native
Pushman.Push.unregister(Pushman.onUnRegistered, null);
}
},
onRegistered: function (msg) {
Pushman.log("Registered: " + msg.registrationId);
//only call callback if registrationId actually set
if (msg.registrationId.length > 0 && Pushman.RegisteredCallback != null) {
Pushman.RegisteredCallback(msg);
}
},
onUnRegistered: function () {
Pushman.log("UnRegistered");
if (Pushman.UnRegisteredCallback != null) {
Pushman.UnRegisteredCallback();
}
},
onInlineNotification: function (msg) {
Pushman.log("OnInlineNotification: " + msg);
if (Pushman.NotificationForegroundCallback != null) {
Pushman.NotificationForegroundCallback(msg);
}
},
onBackgroundNotification: function (msg) {
Pushman.log("OnBackgroundNotification: " + msg);
if (Pushman.NotificationBackgroundCallback != null) {
Pushman.NotificationBackgroundCallback(msg);
}
},
onColdStartNotification: function (msg) {
Pushman.log("OnColdStartNotification: " + msg);
if (Pushman.NotificationBackgroundCallback != null) {
Pushman.NotificationBackgroundCallback(msg);
}
},
onError: function (error) {
Pushman.log("Error: " + error);
if (Pushman.ErrorCallback != null) {
Pushman.ErrorCallback(error);
}
},
onAndroidNotification: function (e) {
switch (e.event) {
case 'registered':
if (e.regid.length > 0) {
Pushman.onRegistered("Registered");
}
break;
case 'message':
if (e.foreground) {
//if this flag is set, this notification happened while app in foreground
Pushman.onInlineNotification(e.payload.message);
} else {
//otherwise app launched because the user touched a notification in the notification tray.
if (e.coldstart) {
//app was closed
Pushman.onColdStartNotification(e.payload.message);
}
else {
//app was minimized
Pushman.onBackgroundNotification(e.payload.message);
}
}
break;
case 'error':
Pushman.onError(e.msg);
break;
default:
Pushman.onError("Unknown message");
break;
}
},
onIOSNotification: function (event) {
//TODO: not sure how ios works re cold start vs inline msg types?
if (event.alert) {
navigator.notification.alert(event.alert);
}
if (event.badge) {
Push.setApplicationIconBadgeNumber(app.successHandler, app.errorHandler, event.badge);
}
},
tokenHandler: function (result) {
// iOS - not sure its use though appears somewhat important
// 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('device token = ' + result);
},
log: function (msg) {
console.log(msg);
},
}
///"class" variables - not sure how to put them into the js "class"
Pushman.Push = null;
Pushman.Hub = null;
Pushman.HubConnectionString = null;
Pushman.HubName = null;
Pushman.GcmSenderId = null;
Pushman.NotificationForegroundCallback = null;
Pushman.NotificationBackgroundCallback = null;
Pushman.RegisteredCallback = null;
Pushman.UnRegisteredCallback = null;
Pushman.ErrorCallback = null;
I did not write this myself, all credit goes to this guy.
Then you just need to initialize the plugin when the application starts:
//azure notificationshub connection information
notificationHubPath = "notificationhub name";
connectionString = "notificatin hub connectionstring";
//sender id for google cloud services
var senderIdGCM = "sender id from google gcm";
//tag registration (csv string), can be empty but not undefined
var registrationTagsCsv = ""; //test1, test2
var app = {
Initialize: function () {
//reg for onload event
this.AppStart();
},
AppStart: function () {
"use strict";
document.addEventListener('deviceready', app.onLoad, false);
document.addEventListener('deviceready', onDeviceReady.bind(this), false);
function onDeviceReady() {
// Handle the Cordova pause and resume events
document.addEventListener('pause', onPause.bind(this), false);
document.addEventListener('resume', onResume.bind(this), false);
// TODO: Cordova has been loaded. Perform any initialization that requires Cordova here.
};
function onPause() {
// TODO: This application has been suspended. Save application state here.
};
function onResume() {
// TODO: This application has been reactivated. Restore application state here.
};
},
onLoad: function () {
app.log("Initializing...");
//setup push notifications
Pushman.Initialize(connectionString, notificationHubPath, senderIdGCM,
app.onNotificationRegistered, app.onNotificationUnRegistered,
app.onNotificationInline, app.onNotificationBackground, app.onNotificationError);
//hookup cmd buttons
app.registerForPush();
//$("#register").click(app.registerForPush);
//$("#unregister").click(app.unRegisterForPush);
app.onAppReady();
},
registerForPush: function (a, c) {
app.log("Registering...");
//register for tags
Pushman.RegisterForPushNotifications(registrationTagsCsv);
},
unRegisterForPush: function (a, c) {
app.log("UnRegistering...");
//register for tags
Pushman.UnRegisterForPushNotifications();
},
onAppReady: function () {
app.log("Ready");
},
onNotificationRegistered: function (msg) {
app.log("Registered: " + msg.registrationId);
},
onNotificationUnRegistered: function () {
app.log("UnRegistered");
},
onNotificationInline: function (data) {
app.log("Inline Notification: " + data);
},
onNotificationBackground: function (data) {
app.log("Background Notification: " + data);
},
onNotificationError: function (error) {
app.log("Error: " + error);
},
log: function (msg) {
console.log(msg);
},
};
If you want to store the messages then you just need to add your code for storing to sql where the messages get received. You'll need an azure account to make this work, here you can get a free trail. It will allow you to send up to 1 million push notifications a month free of charge.
I think this article may be of use, it has more of a direct native workaround for your hybrid app to work
http://www.hiddentao.com/archives/2015/04/10/parse-push-notifications-for-your-android-and-ios-cordova-app/.
I'm working on a Cordova android app, and this seems to be a working solution

Cordova/Ionic Facebook getLoginStatus not working

I am developing an App in Ionic/Cordova with Login over Facebook. Before showing the "Login-Page" I would like to check if the user is already connected.
The following getLoginStatus check works as expected in the iOS Simulator. When testing on the actual device, the getLoginStatus callback does not get fired.
facebookConnectPlugin.getLoginStatus(
function (response) {
if (response.status == "connected") {
set_tokens(response);
$location.path('/tab/person/me/events');
}
},
function (response) { alert(JSON.stringify(response)) }
);
Already set the Facebook-App to public and verified the App-Id.
Can anybody give a reason for the described behaviour?
I have the following implementation for Facebook login using facebookConnect Plugin.
facebookConnectPlugin.getLoginStatus(
function(response){
if(response.status == "connected"){
//do something, for example share or redirect
}else{
facebookConnectPlugin.login(["basic_info"],
function(success) { /*do something...*/},
function(error) {
//handle error
});
}
}, function(error) {
// handle error
})
}
If you still have errors, try to log the error and success events to see what is happening. This implementations works in a controller.

Resources