How to set high priority of push notification which is send to NotificationHub
Asked Answered
B

1

9

I have successfully implemented Azure Function, which sends push notifications to NotificationHub for Android, iOS and UWP. During the testing I discovered that when Android device is in Doze mode push notification is not delivered on lock screen. It is only delivered when I unlock the phone.

I found out this stackoverflow post, which helped me to fix it with method SendFcmNativeNotificationAsync. I used this code:

string payload = @"{
                    ""data"":{
                        ""notificationtype"":""sap"",
                        ""title"":""value2"",
                    },
                        ""priority"":""high""
                    }";

await hub.SendFcmNativeNotificationAsync(payload);

However my implementation using SendNotificationAsync method which works for all 3 platforms, but not in Doze mode. This is my code to send notification:

Dictionary<string, string> templateParameters = new Dictionary<string, string>();

templateParameters["alert"] = "Test";
templateParameters["title"] = "Whosap";

var notification = new TemplateNotification(templateParameters);
await hub.SendNotificationAsync(notification);

I tried to set header of notification:

var headers = new Dictionary<string, string> { { "android", @"{""priority"": ""high""}" } };
notification.Headers = headers;

But this didn't work. Does anybody know how to set priority in TemplateNotification object and send it with SendNotificationAsync method?

This is how I force/unforce device to doze mode:

adb shell dumpsys deviceidle force-idle
adb shell dumpsys deviceidle unforce
Ballistics answered 28/5, 2020 at 14:50 Comment(2)
What kind of push notifications are you sending? Is it like a text message (where the user can interract), or is it like an informative one only?Kilauea
Right now I want to implement only informative push notifications.Discrete
K
3

Based on your comment that you want to have "only informative push notifications", unfortunately, you cannot force the phone to show your notifications every time. This doesn't come as a limitation to either Xamarin, or even Azure Functions in that matter. Even some of Google's own applications behave the same.

Looking at Doze checklist:

If your users must see a notification right away, make sure to use an FCM high priority message

Even if we look at Using FCM to interact with your app while the device is idle:

FCM is optimized to work with Doze and App Standby idle modes by means of high-priority FCM messages. FCM high-priority messages let you reliably wake your app to access the network, even if the user’s device is in Doze or the app is in App Standby mode. In Doze or App Standby mode, the system delivers the message and gives the app temporary access to network services and partial wakelocks, then returns the device or app to the idle state.

So far it all looks like that if you decide to use High priority messages, everything should work fine. However, that's not the whole story. You are correct in setting the priority to high "priority":"high". Unfortunately, there are some caveats to this setting (from docs):

High priority messages generally should result in user interaction with your app or its notifications. If FCM detects a pattern in which they don't, your messages may be de-prioritized.

What this means is that if you are sending only an informative notification, it won't be enough to wake the device from Doze mode and show the notification. There checks/restrictions got even tighter from Android P. Read about app standby buckets here.

The good thing is that exiting Doze mode comes in a form of various events/interactions:

As soon as the user wakes the device by moving it, turning on the screen, or connecting a charger, the system exits Doze and all apps return to normal activity.

At least on the phones that I have tried, in a normal every-day scenario, the notifications are being suspended during either your night sleep, or when the device is sitting there without any interactions/movements, etc.

However, if you really need to deliver every notification and it is crucial to the UX, then you have 2 options:

  1. If you want to have no user interaction - set the priority to high and simply hope that the system will occasionally show some of the notifications (during the maintenance window probably). Not the best way, but by default it may work from time to time.
  2. If you want to guarantee that the notifications will pop-up, then have some screen describing the issue to the user and then navigate the user to Settings -> Apps & notifications --> Advanced --> Special app access --> Battery optimisation. Then he/she can select your app and manually set it to Don't optimise. Keep in mind that this is not considered a best practice and: a) the user shouldn't know about the consequences from this action and b) it is better to leave everything to the OS in order for it to work as intended.

To sum up, you don't have to set your notification's priority to high, because the OS will see that it a simple informative notification and it will now wake the phone. Keep in mind that, when the phone goes into "deep sleep" Doze mode, it shouldn't and mustn't wake for an informative notifications, so there's no point in trying - that's by design. Otherwise, every other developer can set its notification priority to high and the phone may never go to Doze mode, which will make the feature useless.

Kilauea answered 1/6, 2020 at 11:13 Comment(4)
Thank you for your answer! Well in that case I can add some interactions to push notifications and I'll be fine. This is not a problem. Anyway I would like to use method SendNotificationAsync to send just one request to notification hub. If I don't use this method I have to call SendFcmNativeNotificationAsync, SendAppleNativeNotificationAsync and SendWindowsNativeNotificationAsync. Most of the time I send notification to specific user. This means that 2 requests are wasted. Do you know if it is possible to send it with SendNotificationAsync and set high priority?Discrete
This is not a good approach. The user may have 2 different devices with the same account logged-in. If you want to send a PN to a specific user, a better approach is to traverse the user's devices and send a PN to each device individually (in the context of different OSes). Let's say that I have 1 iOS device & 1 Android devices. I am logged-in in both devices within your app's context. Then, the best solution is for the user to receive the PN on both devices, that's why a better approach is to send the notifications separately. In this case too much abstractions is bad abstraction.Kilauea
I don't agree. Let's say I call SendNotificationAsync(notification, 123). Then user 123 is logged on Android and iOS. NotificationHub knows that he should send it to Android and iOS device and not to UWP. This approach could save 1 request. Anyway thank you for answer, it really helped me to understand the problem.Discrete
I see your point. Unfortunately, I haven't tried to do this myself. At least on theory, it should work. I think that I remember reading about this somewhere, where you may have to tinker with the Service Bus Explorer, but can't say for sure.Kilauea

© 2022 - 2024 — McMap. All rights reserved.