Push Notification Not Arriving from Parse Cloud Code - ios

I wrote a simple job to try sending a push notification to myself. Here's the code:
Parse.Cloud.job("testPush", function(request, status) {
Parse.Cloud.useMasterKey();
var installationQuery = new Parse.Query(Parse.Installation);
installationQuery.equalTo("user", "6t1JIuNqe1"); // I triple checked - this is the value of my user in the installation table.
Parse.Push.send({
where: installationQuery,
data: {
alert: "Test"
},
}, {
success: function() {
console.log("The Push Test Worked!");
status.success("All done with the push test!");
}, error: function(error) {
console.error("Something bad happened " + error);
status.error("Something bad happened during the Parse test...");
}
});
});
Although it logs in Parse that the job was run successfully, I never see a notification appear on my iPhone. I checked in Settings - it's all set up properly there (notifications are allowed to appear and should appear as banners, they should show up in notification center, they should show up on my lock screen). And yet the notification never appears.
What more do I need to check? What am I missing?

Pointer field should work with an instance.
Try replacing installationQuery.equalTo("user", "6t1JIuNqe1"); with the following:
var user = new Parse.User();
user.id = '6t1JIuNqe1';
installationQuery.equalTo('user', user);

Related

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.

Query Session class with cloud code Parse

I am trying to send a push notification using a user's id. I have already tested sending with installationId, querying the _Installation class, but i would like to query the session class of the user pointer, to then turn around and query the installation class.
My problem is lying in the restrictions of querying the session class. I have successfully used createWithoutData() found here, and I know it is working because i can output that user. However, even after using the master key found here, the results are always empty.
The general practise for sending Push Notification to specific user is that you will store pointer to User in Installation class... for example when user register do this
Swift
if let installation = PFInstallation.current() {
installation["user_id"] = PFUser.current()!
installation.saveInBackground()
}
Cloudcode
var pushQuery = new Parse.Query(Parse.Installation);
pushQuery.equalTo('user_id', tarUser);
pushQuery.exists("deviceToken");
pushQuery.limit(1); // in case there are more Installation with the user ID, use only the latest
pushQuery.descending("createdAt");
Parse.Push.send({
where: pushQuery, // Set our Installation query
data: {
alert: "Some push text"
}
}, {
success: function() {
// Push was successful
response.success();
},
error: function(error) {
console.error("Got an error " + error.code + " : " + error);
response.error(error);
},
useMasterKey: true
});
if I remember correctly you have to query the pointer in Cloud code with pointer structure, like this
var tarUser = {
__type: 'Pointer',
className: '_User',
objectId: 'insertObjectIDHere'
};

Sending Parse Push with Cloud Code

I cannot find any documentation on Parse.Push used in Parse Cloud Code. The usage case that I see is like this...
// Send the push notification to results of the query
Parse.Push.send({
where: pushQuery,
data: {
alert: message
}
}).then(function() {
response.success("Push was sent successfully.")
}, function(error) {
response.error("Push failed to send with error: " + error.message);
});
What I am trying to do is send a push notification if a recipient user is setup for notifications (i.e. has a valid Installation instance, associated to their user).
At the moment I create the query and pass that into the above with pushQuery. What I notice is that a Push is created in the Parse dashboard but the Pushes sent is 0.
Really I just want to create the Push if a user exists. I have created the query and can run this and return if I get results or not like this...
Parse.Cloud.define("sendTurnNotificationToUser", function(request, response) {
var senderUser = request.user;
var recipientUserId = request.params.recipientId;
var message = request.params.message;
// Validate the message text.
// For example make sure it is under 140 characters
if (message.length > 140) {
// Truncate and add a ...
message = message.substring(0, 137) + "...";
}
// Send the push.
// Find devices associated with the recipient user
var recipientUser = new Parse.User();
recipientUser.id = recipientUserId;
var pushQuery = new Parse.Query(Parse.Installation);
pushQuery.equalTo("user", recipientUser);
pushQuery.find({
success: function(results) {
response.success("push user lookup was ok");
response.success(results);
},
error: function() {
response.error("push user lookup failed");
}
});
I could add the Parse.Push.send call to the success of the query. However the Parse.Push.send has a where clause and I do not know what is required there? I do not want to run the query twice.
You're on the right track. Push "advanced targeting" allows the app to push to installations resulting from a query. That's what the where clause is for...
// don't run find on the pushQuery. set it up as you have it
// then, assuming it returns some installation(s)...
Parse.Push.send({ where: pushQuery, data: "hello" }).then(function(result) {
response.success(result);
}, function(error) {
response.error(error);
});
Incidentally, you can use createWithoutData on Parse.User as a shortcut ...
var recipient = Parse.User.createWithoutData(request.params.recipientId);
but the longer form you have should work, too.
It seems like you may be overthinking this. There's no harm in sending a push notification to 0 installations as the push query will not match any recipients. I wouldn't worry too much about this and I wouldn't add such a pre-check to your code. It would add an unnecessary delay to your code and of course would result in the query being run twice.
If you want to do this anyway -- maybe you wish to keep your push logs free of clutter - you can indeed query over the Installation class to check if the query would have matched a set of installations, and if it does, you can then pass that same query to Parse.Push.send().
Yes, that will result in the query run twice, but that's to be expected, as you can't know how many objects will be matched without running the query.

How to pass the user object that triggered the push notification

I have saved all the user's location in the installation object. And i have another object named locationObject which gets updated when the current user sends his current location.When it does, the cloud code compares his current location with all the other saved locations and send push notifications to the users who are nearby.This is my code to generate push notifications.
Parse.Cloud.afterSave("locationObject", function (request) {
var geoPoint = request.object.get("myCurrentLocation");
var pushQuery = new Parse.Query(Parse.Installation);
pushQuery.near("significantLocationUpdate", geoPoint);
pushQuery.limit(100);
Parse.Push.send({
where: pushQuery,
data: {
alert: "some user is nearby"
}
}, {
success: function() {
console.log("push was successful");
},
error: function(error) {
console.log("sending push failed")// Handle error
}
});
});
Now, my question is, how can i pass along the user object that triggered the push notification along with his current location to the the users i am sending push notification to?
You can add additional data to the push. For example:
data: {
alert: "some user is nearby",
user: [user objectId],
latitude: [user latitude],
longitude: [user longitude]
}

Parse: Dynamic datas in push notification

Notification Using Parse from Server.
I have to send different message for a set of users
like,
you got 1st rank - to User A
you got 2nd rank - to User B
you got 3rd rank - to User C
In Parse, i have save the rank details for each users like
device_id userA rank1
device_id userB rank2
device_id userc rank3
While pushing the message, i have the send the message with the rank value
url = 'https://api.parse.com/1/push'
message = 'you got Xth rank'
data = {:data => message}.to_json
HTTParty.post(url,:body => data)
I can able to send the static message with the above code.
But how to send the message with dynamic values from parse database of respective record.
Looping through users and sending them push one by one may be the solution to your problem, Here is an example code in JS
var installationQuery = new Parse.Query(Parse.Installation);
installationQuery.each(
function(result) {
var tempQuery = new Parse.Query(Parse.Installation);
tempQuery.equalTo("username", result.get('username'));
// Send push notification to query
Parse.Push.send({
where: tempQuery,
//
data: {
alert: "Hey "+result.get('name')+" your Rank ."+ result.get('rank')
}
}, {
success: function() {
response.success("Pushed to "+result.get('name'));
},
error: function(error) {
// Handle error
response.success("Error in push to"+result.get('name'));
}
});
},
{
success: function(result) {
console.log("push sent to all users.");
response.success();
},
error: function() {
} }
);
And if your data for ranks isn't in installation e.g. it's in Users Table then your first query would be on Users table and in function on each to send push you second query will remain on installation table.
Any query?

Resources