I am creating an app that uses Parse cloud. I am trying to send a message from a user to all others. After writing the message in a textfield and pressing send, the delegate calls the following method and the push is handled as shown below:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
//hide keyboard
[textField resignFirstResponder];
NSString *message = self.broadcastText.text;
//create a user query
PFQuery *query = [PFUser query];
PFUser *current = [PFUser currentUser];
NSString *currentUsername = current[#"username"];
[query whereKey:#"username" notEqualTo:currentUsername];
//send push in background
PFPush *push = [[PFPush alloc] init];
[push setQuery:query];
[push setMessage:message];
[push sendPushInBackground];
//clear text field
textField.text = #"";
return YES;}
What's happening is when I send the message, the sender (in this case me) is receiving the push notification as well. What I tried to do is get the current user's username and then create a user query that queries for all users whose usernames are not equal to the current user's username.
However, it didn't work, the message was also being sent to all users including the sender.
Note: I also tried using [query whereKey:#"username" notEqualTo:currentUsername]; just for debugging, and when I try to send the message, neither the sender nor any other device receives it. (when actually no one should receive it except the sender).
Any help would be greatly appreciated. Thank you.
Your problem is that a PFPush can't take any query, it needs a PFInstallation query. When you store your PFInstallation for each user, you could add a field that points to the current user, something like:
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
currentInstallation[#"user"] = [PFUser currentUser];
[currentInstallation saveInBackground];
Then, do an installation query like this:
PFQuery *installationQuery = [PFInstallation query];
PFUser *current = [PFUser currentUser];
[installationQuery whereKey:#"user" notEqualTo:current];
Then, continue with your push using this query:
PFPush *push = [[PFPush alloc] init];
[push setQuery:installationQuery]; // <<< Notice query change here
[push setMessage:message];
[push sendPushInBackground];
In theory you send push notifications to all users that are subscribed to some channel ok.
Now you have a table with all users and all channels. Some users are subscribed other are not. First create a query for the installation, than find users that are not current user.
PFQuery *pushQuery = [PFInstallation query];
[pushQuery whereKey:"user" notEqualTo:[PFUser currentUser]];
Create a Push object and use this query.
PFPush *push = [[PFPush alloc] init];
[push setQuery:pushQuery]; // Set our Installation query
[push setMessage:#"Ciao."];
[push sendPushInBackground];
In pushQuery you can use other key, example: deviceID,installationID, deviceType etc..
I use Parse Cloud but i never use push notification so you need to try this code.
Related
I am working on an app that allows "current user" to view an event posted by another user. When the current user join the event I'd like to send a push notification to the user who posted the event. I have set up push notification for my app with Parse. I am able to send push notifications to all users via a channel, but I still cannot figure out how to send a push notification to the specific user. I am able to receive the push notifications on my phone.
I tried to associate the device with a user with the following code:
PFInstallation *installation = [PFInstallation currentInstallation];
installation[#"user"] = [PFUser currentUser];
[installation saveInBackground];
Unfortunately - this makes my app crash. Not sure why there is not error message.
I was thinking of using the following code to send the push notification to a specific user. (This is code i got from Parse Documentation)
// Create our Installation query
PFQuery *pushQuery = [PFInstallation query];
[pushQuery whereKey:#"injuryReports" equalTo:YES];
// Send push notification to query
PFPush *push = [[PFPush alloc] init];
[push setQuery:pushQuery]; // Set our Installation query
[push setMessage:#"Willie Hayes injured by own pop fly."];
[push sendPushInBackground];
How do you associate the installation with the current user?
Am I in the right track?
If you know of a good tutorial, please let me know or if you have implemented something similar and could help me with this problem.
Thank you,
You first need to create a relationship between a user and it's installation. Remember that notifications on iOS are send to devices as the Apple notification system knows nothing about your users.
[[PFInstallation currentInstallation] setObject:[PFUser currentUser] forKey:#"user"];
[[PFInstallation currentInstallation] saveEventually];
Now your code is easier to use:
// Create our Installation query
PFQuery *pushQuery = [PFInstallation query];
// only return Installations that belong to a User that
// matches the innerQuery
[query whereKey:#"user" matchesQuery: pushQuery];
// Send push notification to query
PFPush *push = [[PFPush alloc] init];
[push setQuery:pushQuery]; // Set our Installation query
[push setMessage:#"Willie Hayes injured by own pop fly."];
[push sendPushInBackground];
Hi I'm making a messaging app that uses the internet to send messages. I need to give a notification from user a to user b.
I use this code:
if (toUser!= nil){
parseMessage[#"toUser"]=toUser;
//PFPush *push = [[PFPush alloc] init];
// [push setQuery://whatshouldiputhere?];
// [push setMessage:[NSString stringWithFormat: #"New Message from %#!", [PFUser currentUser].username]];
// [push sendPushInBackground];
}
This code is executed when the message is being sent. This just doesn't work. What am I doing wrong? Could you please help me?
Thanks for any help.
Sending Push Notifications from User to User are quite similar to using channels, first you have to do a query to find the user then pass that query into the push notification.
So for example:
User A sends User B a message, you have to do a query to find User B in your backend. You can do that many ways, using channels, arrays etc, but for this example I will use an objectId:
-(void)sendPushNotificationToUserBWithObjectId:(NSString *)objectId {
// Build a query that matches user B's objectId (note you would have to save User B's objectId or retrieve it from a different query
PFQuery *subQuery = [PFUser query];
[subQuery whereKey:#"objectId" equalTo:objectId];
// Build the actual push notification from targeted query
PFQuery *finalQuery = [PFInstallation query];
// only return Installations that belong to a User that matches the subQuery & 'toUser' is objectId
[finalQuery whereKey:toUser matchesQuery:innerQuery];
// Send the notification.
PFPush *push = [[PFPush alloc] init];
[push setQuery:finalQuery];
[push setMessage:#"Message"];
[push sendPushInBackground];
}
You would call it at any time like this:
[self sendPushNotificationToUserBWithObjectId:#"xVyWO18"];
where #"xVyWO18" is User B's objectId
Say I need to get a particular installation from Parse. I don't have the objectId. How might I query for it? It's concerning iOS push notifications. I already have the deviceId. What is the curl command for that?
If you want to send push to individual user then you need to add some additional info to the installation object for example when the user sign in. So other users can query instalations to find a specific ones. I've done it like this:
PFInstallation *installation = [PFInstallation currentInstallation];
installation[#"client"] = [KZClient currentClient];
installation[#"phone"] = [KZClient currentClient].phoneNumber;
[installation saveInBackground];
And other user can find this installation object by querying like this:
PFUser *friend = [some method to get friend ...];
PFQuery *installationQuery = [PFInstallation query];
[installationQuery whereKey:#"client" equalTo:friend];
PFPush *push = [[PFPush alloc] init];
[push setQuery:installationQuery];
[push setMessage:#"Test message"];
[push sendPushInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
}];
I have saved user pointer in instalation class. Web backend shows 0 subscribers
I am sending notification using below code
PFQuery *qry = [PFUser query];
[qry getObjectWithId:friendObject.objectId]; //friend object is ok like #"Fefl5x7nhl"
PFQuery *pushQuery = [PFInstallation query];
[pushQuery whereKey:#"user" matchesQuery:qry];
// Send push notification to query
PFPush *push = [[PFPush alloc] init];
NSString *msgString=[NSString stringWithFormat:#"%# :%#",
[newMessage objectForKey:#"userName"],
tfEntry.text];
[push setQuery:pushQuery]; // Set our Installation query
NSDictionary *data = [NSDictionary dictionaryWithObjectsAndKeys:
msgString, #"alert",
#"ursound.caf", #"sound",
#"Increment", #"badge",
// #"Optionally a type was set", #"type",
nil];
[push setData:data];
[push sendPushInBackground];
My installation class does have this user pointer (friend object) and logically it should be receiver of the notification .
AM i missing something? any suggestion would be great . Thanks for your valuable time
As long as you have a column on the Installation class called user that is of type Pointer<My_User> and you've actually populated it, your code should work.
There's a section in the Push Notification documentation that talks about adding data to the Installation class:
https://parse.com/docs/push_guide#sending-queries/iOS
Based on the Parse guide to using Advanced Targeting for push notifications, I understand in order to associate PFInstallations with the current user, one should so in the following manner:
PFInstallation *installation = [PFInstallation currentInstallation];
installation[#"user"] = [PFUser currentUser];
[installation saveInBackground];
My question is, how would be able to do this "on the fly" for other users (i.e. not the current user). For example, I have a Message object that I would like to send to users Sally, Alex and Ben: how would be able to get just the PFInstallations of those users based on their user objectIds, and then set their PFInstallation's so that
//Sally, Alex and Ben's PFInstallations:
[installation setObject:YES forKey:message.objectId];
...so then when I sent out the message, only Sally, Alex and Ben will get the push notification that they received a message from me?
Thanks!
Here was how I managed to do it. Note that recipientIDs are the list of users (user objectIds, to be exact) that I am sending a push notification to.
if (recipientIDs.count > 0){
//Find the users that were just sent the message
PFQuery *userQuery = [PFUser query];
[userQuery whereKey:#"objectId" containedIn:recipientIDs];
//Find the devices associated with these users
PFQuery *pushQuery = [PFInstallation query];
[pushQuery whereKey:#"user" matchesQuery:userQuery];
//Send push to these users
PFPush *push = [[PFPush alloc] init];
NSDictionary *data = [NSDictionary dictionaryWithObjectsAndKeys:
[NSString stringWithFormat:#"New message from %#", [PFUser currentUser].username], #"alert",
#"Increment", #"badge",
nil];
[push setQuery:pushQuery]; // Set our Installation query
[push setData:data];
[push sendPushInBackground];
}
Not sure if this can work - the documentation says
A valid PFInstallation can only be instantiated via [PFInstallation
currentInstallation] because the required identifier fields are
readonly.
https://parse.com/docs/ios/api/Classes/PFInstallation.html