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);

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

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.

Hi!

Please try these headers:

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

Regards, Olga

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

Hello!

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

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

And then you can handle notification in didReceiveRemoteNotification method in AppDelegate

Regards, Olga

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.

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:
{"ios-alert":"","ios-badge":0, "ios-sound":"", "content-avaliable":1}
  1. Handle silent notification with didReceiveRemoteNotification method. E.g:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        switch application.applicationState {
            
        case .inactive:
            print("Inactive")
            //Show the view with the content of the push
            completionHandler(.newData)
            
        case .background:
            print("Background")
            //Refresh the local model
            completionHandler(.newData)
            
        case .active:
            print("Active")
            //Show an in-app banner
            completionHandler(.newData)
        }
    }

Screenshot with the results attached.

Regards, Olga

Sorry Olga, still stuck here :frowning:

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

 
 
 
 
 
 
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:

 
 
 
 
 
 
let headers = ["ios-alert" : "Webview notification for iOS",
 
 "pushType" : "webView", 
 
 "contentUrl" : "[url=https://www.google.com]https://www.google.com"[/url]; , 
 
 "preventExit" : "false", 
 
 "ios-sound" : "default",] 
 
 sendPushNotificationSync(headers: headers)


silent:

 
 
 
 
 
 
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)

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);


Hi Gal,

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

Yeah, normal push notifications work from the business logic too

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

let headers = ["ios-alert" : nil,
"ios-sound" : "",
"pushType" : "callEnded",
"showRating" : "true" ,
"userCode" : "testCode"]
sendPushNotificationSync(headers: headers)

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

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

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: “”
}

Hi Gal,

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

Backendless.enablePromises();
const channel = "default";
const message = "test";
const publishOptions = new Backendless.PublishOptions({
headers: {
"ios-alert": "",
"ios-badge": 0,
"ios-sound": "",
"ios-content-available": 1,
a: "a",
b: 2,
c: false
}
});
const deliverOptions = new DeliveryOptions({
pushPolicy: 'ONLY'
});
Backendless.Messaging.publish(channel, message, publishOptions, deliverOptions).then(
console.log,
console.err
);

Is it helpful for you?

Regards Ilya

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 :slight_smile:

Back to this… still got another a problem: push notifications both silent and not, work. BUT push notifications sent to a specific deviceID do not.

  1. Where do I get the deviceID?

  2. What should it look like?

Thank you

UPDATE:

I got it working. The problem was not the deviceID, but the key in which it is stored. In the it should be:

 const deliverOptions = new DeliveryOptions({
     pushPolicy: 'ONLY',
     pushSingleCast: ['DEVICE-ID-HERE']
 });

NOTICE THE CASING OF “pushSingleCast” vs. “pushSinglecast”… this was a mistake cause by the documentation:
https://backendless.com/documentation/messaging/js/messaging_publish_push_notifications.htm

Hi Gal,
Thank you for pointing us this mistake. We will investigate it and fix it ASAP.
Sorry about it.

Regards Ilya

Hi Gal,

What version of the JS library do you use? I am looking at the latest version for 3.x and in there the property is written just like in the doc, “pushSinglecast”:
https://api.backendless.com/sdk/js/v3/backendless.js

Mark