Skip to content

How to send push notifications from Swift ? #768

Description

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

Activity

  1. changed the title [-]How to send push notification from Swift ?[/-] [+]How to send push notifications from Swift ?[/+] on Mar 2, 2016
  2. nlutsenko commented on Mar 2, 2016

    @nlutsenko
    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?

  3. nlutsenko commented on Mar 2, 2016

    @nlutsenko
    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.

  4. nlutsenko commented on Mar 2, 2016

    @nlutsenko
    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.

  5. nlutsenko commented on Mar 2, 2016

    @nlutsenko
    Contributor

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

  6. nlutsenko commented on Mar 3, 2016

    @nlutsenko
    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.

  7. otymartin commented on Mar 5, 2016

    @otymartin

    @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]?#>)

  8. nlutsenko commented on Mar 5, 2016

    @nlutsenko
    Contributor

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

  9. otymartin commented on Mar 5, 2016

    @otymartin

    @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)
    
        }
  10. craiggrummitt commented on Jun 17, 2016

    @craiggrummitt

    @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?

  11. hasso92 commented on Jun 17, 2016

    @hasso92

    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
    .

  12. craiggrummitt commented on Jun 25, 2016

    @craiggrummitt

    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.

  13. StevenArmandLee commented on Sep 13, 2016

    @StevenArmandLee

    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)
                        }
                    })
    
  14. cubycode commented on Sep 24, 2016

    @cubycode

    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

  15. StevenArmandLee commented on Sep 24, 2016

    @StevenArmandLee

    @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

  16. cubycode commented on Sep 24, 2016

    @cubycode

    @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?

  17. michaelsalvador commented on Nov 29, 2016

    @michaelsalvador

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

  18. StevenArmandLee commented on Nov 29, 2016

    @StevenArmandLee

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

  19. cubycode commented on Nov 29, 2016

    @cubycode

    @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

  20. michaelsalvador commented on Nov 29, 2016

    @michaelsalvador

    @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

  21. cubycode commented on Nov 29, 2016

    @cubycode

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

  22. jbschaff commented on Aug 1, 2017

    @jbschaff

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

  23. otymartin commented on Aug 2, 2017

    @otymartin

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

  24. jbschaff commented on Aug 3, 2017

    @jbschaff

    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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions