Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to send push notifications from Swift ? #768

Closed
fraxool opened this issue Mar 2, 2016 · 25 comments
Closed

How to send push notifications from Swift ? #768

fraxool opened this issue Mar 2, 2016 · 25 comments

Comments

@fraxool
Copy link

fraxool commented Mar 2, 2016

Since the PFPush class is not working anymore, how can I send a push notification from Swift or how can I call some cloud code to send a push notification to my users ?

Example : User_1 sends a friend request to User_2. I want User_2 to receive a notification on his device. I know I can do this with Javascript / PHP, but is it possible to do it from Swift directly without having some files hosted on a web server ?

I am actually using Heroku.

Thanks,
Axel

@fraxool fraxool changed the title How to send push notification from Swift ? How to send push notifications from Swift ? Mar 2, 2016
@nlutsenko
Copy link
Contributor

PFPush since it talks to /push endpoint and it's implemented should actually work on the latest version of the server. Do you see something that suggests that it's not?

@fraxool
Copy link
Author

fraxool commented Mar 2, 2016

Thanks for your answer. In fact, when I am trying to send a push notification, it tells me that I need to use the master key in order to send it. However, from the swift code, I'm not sure if I can set the master key somewhere...

@nlutsenko
Copy link
Contributor

Aha, here is something we uncovered then.
You should be able to send a notification from CloudCode then.

The client SDKs don't have an ability to use MasterKey just yet, though we could safely add it, but it exposes a bad programming practice, since you should never put a master key on the client.

@fraxool
Copy link
Author

fraxool commented Mar 2, 2016

So I need to have some code hosted somewhere (a web hosting) in order to send push notifications ? Isn't it possible to do that only by using Heroku and Swift code ?

@nlutsenko
Copy link
Contributor

You can host Cloud Code actually on Parse Server.
This wiki page describes how to migrate over your code from classic Parse, but overall - all you need is to place Cloud Code in the cloud folder of your Parse Server on Heroku and it should automatically pick it up.

@nlutsenko
Copy link
Contributor

Also, here are two good guides on how to get Push Notifications in Parse Server land working with Cloud Code:

@nlutsenko
Copy link
Contributor

Going to close out this issue, feel free to comment here or reopen it if you still having trouble sending push via Cloud Code.

@otymartin
Copy link

@nlutsenko Do you have a guide for how to trigger cloud code push notifications from my swift iOS app?

Do I just paste this code in my main.js file then in swift call PFCloud.callFunctionInBackground(<#T##function: String##String#>, withParameters: <#T##[NSObject : AnyObject]?#>)

@nlutsenko
Copy link
Contributor

Yup, that would work just great as well. That repo tutorial is actually very very good.

@otymartin
Copy link

@nlutsenko Hey im still abit(very) lost. This is previously how I sent pushes in my messaging app.
How could I rewrite this method using the cloud code part to send the push?

 func sendPushNotification(contact: PFUser) {

        let pushQuery = PFInstallation.query()
        pushQuery?.whereKey("user", equalTo: contact)

        let push = PFPush()
        push.setQuery(pushQuery)
        let pushDictionary = ["alert": PFUser.currentUser()!.valueForKey("name") as! String, "badge": "increment", "sound":""]

        push.setData(pushDictionary)
        push.sendPushInBackgroundWithBlock(nil)

    }

@craiggrummitt
Copy link

craiggrummitt commented Jun 17, 2016

@nlutsenko Can I second @otymartin's comment about being lost.

So I successfully got to Step 4 "Send Push Notifications" in the Parse Push tutorial https://github.com/ParsePlatform/parse-server/wiki/Push and have notifications working in my app from 'curl'.

But that's where the tutorial seems to stop. I was hoping to request a notification directly from Swift code... Can you fill in the gap?

I have no experience in cloud code, but I'm guessing what's missing is that I need to set up a function in cloud code with the appropriate parameters that I need to pass it, and then I need to call this function to dispatch the notification, is that correct?

@hasso92
Copy link

hasso92 commented Jun 17, 2016

You could usw a Code like:
Parade.Cloud.define("SendPushToUser", function(request,response){
Parse.Push.send({useMasterKey: true},
{
Query: request.params.query
data: {
alert: request.params.message
}
},
{ success: function() {
// Push was successful
Response.success("push sent")
}, error: function(error) {
Response.error("push failed: " + error.message)
} });
});

You call the cloud fund with the Parms ["query" : YourQuery,"message" :
Pushmessage]

PS: I'm not sure about the location of useMasterKey... I haven't gotten to
the part of sending push notifications. Once I do I would post complete
cloud codes for sending to channels and specific users.
Am Samstag, 18. Juni 2016 schrieb Craig Grummitt :

@nlutsenko https://github.com/nlutsenko Can I second @otymartin
https://github.com/otymartin's comment about being lost.

So I successfully got to Step 4 "Send Push Notifications" in the Parse
Push tutorialhttps://github.com/ParsePlatform/parse-server/wiki/Push and
have notifications working in my app from 'curl'.

But that's where the tutorial seems to stop. I was hoping to request a
notification directly from Swift code... Can you fill in the gap?

I have no experience in cloud code, but I'm guessing what's missing is
that I need to set up a function in cloud code with the appropriate
parameters that I need to pass it, and then I need to call this function to
dispatch the notification, is that correct?


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
#768 (comment),
or mute the thread
https://github.com/notifications/unsubscribe/AQWahgiEDVoSUPyxd2ZoIkkH_wH4KLC2ks5qMx6YgaJpZM4HnjLo
.

@craiggrummitt
Copy link

Thanks @hasso92 for your help. It was the push I needed to keep going, I had reached my input limit for the day!

The Cloud code function I ended up using had similarities to the CloudPath example:

// iOS push testing
Parse.Cloud.define("iosPush", function(request, response) {

  var user = request.user;
  var params = request.params;
  var someKey = params.someKey
  var data = params.data

  var pushQuery = new Parse.Query(Parse.Installation);
  pushQuery.equalTo('deviceType', 'ios'); // targeting iOS devices only
  pushQuery.equalTo("someKey", someKey)

  Parse.Push.send({
    where: pushQuery, // Set our Installation query
    data: data
  }, { success: function() {
      console.log("#### PUSH OK");
  }, error: function(error) {
      console.log("#### PUSH ERROR" + error.message);
  }, useMasterKey: true});

  response.success('success');
});

I then called it from Swift using the PFCloud.callFunctionInBackground method:

let data = [
    "badge" : "Increment",
    "alert" : "Some message",
]
let request = [
    "someKey" : someKey,
    "data" : data
]
PFCloud.callFunctionInBackground("iosPush", withParameters: request as [NSObject : AnyObject])

I go into this in more detail on my blog.

@StevenArmandLee
Copy link

StevenArmandLee commented Sep 13, 2016

here is the cloud code function that I modified to fits your requirements

Parse.Cloud.define("iosPush", function(request, response) {

  var user = request.user;
  var params = request.params;
  var someKey = params.someKey
  var data = params.data

  var recipientUser = new Parse.User();
  recipientUser.id = someKey;

  var pushQuery = new Parse.Query(Parse.Installation);
  pushQuery.equalTo('deviceType', 'ios'); // targeting iOS devices only
  pushQuery.equalTo("user", recipientUser);

  Parse.Push.send({
    where: pushQuery, // Set our Installation query
    data: data
  }, { success: function() {
      console.log("#### PUSH OK");
  }, error: function(error) {
      console.log("#### PUSH ERROR" + error.message);
  }, useMasterKey: true});

  response.success('success');
});

swift code

let data = [
                    "badge" : "Increment",
                    "alert" : text,
                ]
                let request = [
                    "someKey" : self.incomingUser.objectId!,
                    "data" : data
                ]
                PFCloud.callFunctionInBackground("iosPush", withParameters: request as [NSObject : AnyObject])
                PFCloud.callFunctionInBackground("iosPush", withParameters: request as [NSObject : AnyObject], block: { (results:AnyObject?, error:NSError?) in
                    if error == nil {
                        print (results)
                    }
                    else {
                        print (error)
                    }
                })

@cubycode
Copy link

hi,
i've tried your code too and it prints results: success, but my ios 10 device doesn't receive any push notification. if i use the Parse Push system from back4app.com, for example, i get the push notif., so that means that my .p12 certificates for APS are correct.
Any suggestion about this will be greatly appreciated

@StevenArmandLee
Copy link

@fvimagination make sure that you have enabled the push notification at the xcode and make sure you push it from iOS real device and the one receiving it also an iOS real device

@cubycode
Copy link

@StevenArmandLee Push Notifications is enabled in Capabilities, but if i send a push from the iOS Simulator to a real device, it should work, right?
Also, if i send a push from the same real device, shouldn't i still receive it?

@michaelsalvador
Copy link

fvimagination, I'm having the same issue. Did you ever figure out how to fix this?

@StevenArmandLee
Copy link

ok so it's my certificate that has a problem, therefore I re-created the certificate.

@cubycode
Copy link

@michaelsalvador that was my issue as well, now it works perfectly.
Can anyone post the proper code for Manifest.xml to configure an Android app for GCM push notifications? @StevenArmandLee @hasso92 @craiggrummitt

@michaelsalvador
Copy link

@fvimagination So you're saying that after you recreated the development or production push certificate it sent to your device perfectly? Just to be clear

@cubycode
Copy link

@michaelsalvador yes, exactly, the code posted from StevenArmand works perfectly on my side, with Parse Server hosted on back4app.com

@jbschaff
Copy link

jbschaff commented Aug 1, 2017

Just solved this same issue. Will attempt to help, just @ me.

@otymartin
Copy link

@jbschaff best to document it here because others will experience the same problems and look for solutions.

@jbschaff
Copy link

jbschaff commented Aug 3, 2017

Will need to modify someKey on client to target user 2 when user 1 performs action. My purpose is to send a notification to all followers of user 1 (which I haven't solved yet). However, just to get it working I was able to send the notification from user 1 to user 1.

Swift code

let text = "\(PFUser.current()!.username!) followed you, or whatever you want to say here";
let data = [
"badge" : "Increment",
"alert" : text,
]
let request: [String : Any] = [
"someKey" : PFUser.current()!.objectId!,
"data" : data
]
print("sending push notification...")
PFCloud.callFunction(inBackground: "pushToFollowers", withParameters: request as [NSObject : AnyObject], block: { (results:AnyObject?, error:NSError?) in
print("push (String(describing: results!))")
if error == nil {
print (results!)
}
else {
print (error!)
}
} as? PFIdResultBlock)

Cloud code

Parse.Cloud.define("pushToFollowers", function (request, response) {
console.log("Inside pushToFollowers");
var params = request.params;
var user = request.user;
var sessionToken = user.getSessionToken();
var someKey = request.someKey;
var data = params.data;

var recipientUser = new Parse.Query(Parse.User);
recipientUser.equalTo("objectId", request.params.someKey);

// Set our installation query
var pushQuery = new Parse.Query(Parse.Installation);
pushQuery.equalTo('deviceType', 'ios');
pushQuery.matchesQuery('user', recipientUser);
pushQuery.find({ useMasterKey: true }).then(function(object) {
response.success(object);
console.log("pushQuery got " + object.length);
}, function(error) {
response.error(error);
console.error("pushQuery find failed. error = " + error.message);
});

// Send push notification to query
Parse.Push.send({
where: pushQuery,
data: data
}, { useMasterKey: true })
.then(function() {
// Push sent!
console.log("#### push sent!");
}, function(error) {
// There was a problem :(
console.error("#### push error" + error.message);
});
response.success('success, end of pushToFollowers')
});

Edit: Function to target all followers of User 1 is now solved.

Parse.Cloud.define("pushToFollowers", function (request, response) {
  console.log("Inside pushToFollowers");
  var params = request.params;
  var user = request.user;
  var sessionToken = user.getSessionToken();
  var someKey = request.someKey;
  var data = params.data;

  var recipientUser = new Parse.Query(Parse.User);
  recipientUser.equalTo('user', request.user.get('toUser'));
  recipientUser.find({ useMasterKey: true }).then(function(object) {
        response.success(object); 
        console.log("recipientUser found this many: " + object.length);
        }, function(error) {
          response.error(error);
            console.error("recipientUser find failed. error = " + error.message);
    });

// Set our installation query
  var pushQuery = new Parse.Query(Parse.Installation);
   pushQuery.equalTo('deviceType', 'ios');
   pushQuery.matchesQuery('user', recipientUser);
   pushQuery.notEqualTo('user', request.user);  
   pushQuery.find({ useMasterKey: true }).then(function(object) {
        response.success(object); 
        console.log("pushQuery found this many: " + object.length);
        }, function(error) {
          response.error(error);
            console.error("pushQuery find failed. error = " + error.message);
    });

  // Send push notification to query
  Parse.Push.send({
    where: pushQuery,
    data: data  
  }, { useMasterKey: true })
    .then(function() {
      // Push sent!
      console.log("#### push sent!");
    }, function(error) {
      // There was a problem :(
      console.error("#### push error" + error.message);
    });
response.success('success, end of pushToFollowers')
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants