Backendless Support
 
Waiting for user's response

Sending Silent Push Notifications from JS Server Code

Hi,

I am having trouble sending silent push notifications. My intention is that in the iOS Notification Center, the notification does not show up by default, but is first handled by the app, and based on the payload, the app decides how to handle it.

I am on backendless 3, JS server code. This is what I came up with so far:

const channel = "default";

const message = "test"; // --- > I MUST SET THIS, otherwise "Error: MEssage property can't be null"

const publishOptions = new PublishOptions({

headers: {

// "ios-alert": null, // ---> my attempt to HIDE the alert

a: "a",

b: 2,

c: false // custom fields

}

});

const deliverOptions = new DeliveryOptions({

pushPolicy: 'ONLY'

});

return Backendless.Messaging.publish(channel, message, publishOptions, deliverOptions);

Leave a Comment

Comments (15)

photo
1

Hello Gal,

Could you please clarify the problem?

To send silent notifications please add this header: "content-avaliable" : 1 to awake your app in background.

Also you should omit the "ios-sound" header instead of assigning null value to it.

Regards, Olga

photo
1

Hi Olga,

The problem is that I want to send silent push notifications, but instead they show up on the iOS device's notification center (They are not silent).

const channel = "default";

const message = "1";

const publishOptions = new PublishOptions({

headers: { "content-available": 1,

a: 1,

b: 'b',

c: false

}

});

const deliverOptions = new DeliveryOptions({

pushPolicy: 'ONLY'

});

return Backendless.Messaging.publish(channel, message, publishOptions, deliverOptions);

When I use the code above in the JS server code to send a push notification, it shows up in the device's Notification Center with the title "1", taken from my message var. I only passed it in because I had to, I tried passing in both null and empty string instead and both resulted in an "Error: Message property can't be null" error being thrown.

With regards to content-available, i tried that as well, as you can see above, with 1, 0, true and false, just to be sure - in all cases the notification is still not silent.

photo
1

Hi!

Please try these headers:

  1. {"ios-alert":"","ios-badge":0, "ios-sound":"", "content-avaliable":1}

Regards, Olga

photo
1

Thanks. That didn't work either, as far as I can tell, no push notification comes through (at all, not silent nor regular)

photo
photo
1

Hello!

I've checked this issue once more. That should work fine:

Headers:

  1. "ios-content-available":1, "ios-alert":""

And then you can handle notification in didReceiveRemoteNotification method in AppDelegate

Regards, Olga

photo
1

Hi Olga,

While backendless reports

{

"errorMessage": null,

"messageId": "6A34E9D7-36A7-3520-FF54-0E914B626E00",

"status": "scheduled"

}

my app does not receive the notifications. I know this because I have an alert that is supposed

to pop up from didReceiveRemoteNotification and it doesn't show up. Also, if i remove the these

headers, (the ones you suggested above) I do see the alert.

photo
1

Hi Gal,

That's weird because everything should work fine.

1. Please make sure you have enabled background fetch and remote notifications for the background modes of capabilities tab.

2. Use these headers:

  1. {"ios-alert":"","ios-badge":0, "ios-sound":"", "content-avaliable":1}

3. Handle silent notification with didReceiveRemoteNotification method. E.g:

  1. func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
  2. switch application.applicationState {
  3. case .inactive:
  4. print("Inactive")
  5. //Show the view with the content of the push
  6. completionHandler(.newData)
  7. case .background:
  8. print("Background")
  9. //Refresh the local model
  10. completionHandler(.newData)
  11. case .active:
  12. print("Active")
  13. //Show an in-app banner
  14. completionHandler(.newData)
  15. }
  16. }

Screenshot with the results attached.

Regards, Olga

photo
1

Sorry Olga, still stuck here :(

I was able to get both silent and normal push notifications to be sent and received using the iOS SDK:

  1. public func sendPushNotificationSync(headers:[String:String?]){

    let deliveryOptions = DeliveryOptions()

    deliveryOptions.pushPolicy(PUSH_ONLY)

    let publishOptions = PublishOptions()

    let backendless = Backendless.sharedInstance()

    for (header, value) in headers {

    publishOptions.addHeader(header, value: value)

    }

    var error: Fault?

    let messageStatus = backendless?.messaging.publish("default",

    message: "",

    publishOptions:publishOptions,

    deliveryOptions:deliveryOptions,

    error: &error)

    if error == nil {

    print("MessageStatus = \(String(describing: messageStatus?.status)) ['\(String(describing: messageStatus?.messageId))']")

    }

    else {

    print("Server reported an error: \(String(describing: error))")

    }

    }

normal:

  1. let headers = ["ios-alert" : "Webview notification for iOS",

    "pushType" : "webView",

    "contentUrl" : "https://www.google.com"; ,

    "preventExit" : "false",

    "ios-sound" : "default",]

    sendPushNotificationSync(headers: headers)

silent:

  1. let headers = ["ios-alert" : nil,

    "ios-sound" : "",

    "pushType" : "callEnded",

    "showRating" : "true" ,

    "userCode" : "testCode"]

    sendPushNotificationSync(headers: headers)

I was NOT able to accomplish the same thing with the javascript SDK (backendless servercode)

  1. const channel = "default";

    const message = "1";

    const publishOptions = new PublishOptions({

    headers: {

    "ios-alert":"",

    "ios-badge":0,

    "ios-sound":"",

    "content-available": 1,

    a: "a",

    b: 2,

    c: false

    }

    });

    const deliverOptions = new DeliveryOptions({

    pushPolicy: 'ONLY'

    });

    Backendless.Messaging.publish(channel, message, publishOptions, deliverOptions);

photo
1

Hi Gal,

Have you checked whether you are able to receive normal push notifications (not silent) from JS business logic, to begin with?

photo
1

Yeah, normal push notifications work from the business logic too

photo
photo
1

I also see that you don't set the 'content-available' header from iOS code:

  1. let headers = ["ios-alert" : nil,
  2. "ios-sound" : "",
  3. "pushType" : "callEnded",
  4. "showRating" : "true" ,
  5. "userCode" : "testCode"]
  6. sendPushNotificationSync(headers: headers)

Is it a typo or you receive a silent push without setting it?

photo
1

I think I forgot to include it in my code, but as far as I can tell it worked regardless of the content-available in that case

photo
1

Actually, when I added content-available: 1, it broke the silent notification - it was delivered as a normal one.

If I throw up an alert in the appDelegate, this is what the payload looks like for a working silent notification (from the iOS SDK and the code above) :

{

ios-sound: "",

showRating: true,

ios-content-available: 1,

userCode: testCode,

pushType: callEnded

aps: {

alert: "",

content-available: 1,

sound: ""

}

photo
1

Hi Gal,

I use this JS-code for sending silent push notifications to iOS device.

  1. Backendless.enablePromises();
  2. const channel = "default";
  3. const message = "test";
  4. const publishOptions = new Backendless.PublishOptions({
  5. headers: {
  6. "ios-alert": "",
  7. "ios-badge": 0,
  8. "ios-sound": "",
  9. "ios-content-available": 1,
  10. a: "a",
  11. b: 2,
  12. c: false
  13. }
  14. });
  15. const deliverOptions = new DeliveryOptions({
  16. pushPolicy: 'ONLY'
  17. });
  18. Backendless.Messaging.publish(channel, message, publishOptions, deliverOptions).then(
  19. console.log,
  20. console.err
  21. );

Is it helpful for you?

Regards Ilya

photo
photo
1

Guys - I think I figured it out...

to anyone else following along with us here, this was the answer (see above post). The problem was that when using backendless SDK you have to set the header ios-content-available, NOT the standard "content-available" (notice how the correct one has "ios-" in the front...)

Also, make sure you spell "available" correctly, it was misspelled earlier in the thread :)