Azure / azure-notificationhubs-dotnet

.NET SDK for Azure Notification Hubs
MIT License
70 stars 122 forks source link

How to set high priority of push notification which is send to NotificationHub #127

Closed JanNepras closed 3 years ago

JanNepras commented 4 years ago

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?

marstr commented 4 years ago

Howdy @JanNepras,

The priority setting looks to be sent with the body of the notification. For that reason you'll need to update the priority field in your template body instead of sending it as a header.

If you want to determine priority at the time of send, instead of with device registration, you could embed the priority as a template parameter.

Hope that helps!

mpodwysocki commented 3 years ago

Closing as per stale issue. If this does not work, please reopen the issue.

stpatrick2016 commented 3 years ago

Unfortunately, this doesn't seem to work, or at least I couldn't figure out the way to make it work. In order to set priority, one need to define priority tag on the same level as data tag, like this (the link shows the new version of the protocol, where priority should be under android tag, but that doesn't change the point):

{
    "data":{
        "message":"$(message)",
    },
    "priority":"high"
}

But looking in the code of FcmTemplateRegistrationDescription.OnValidate, line 294, it explicitly requires to have only 1 root:

foreach (XElement element in payloadDocument.Root.DescendantsAndSelf())

and that's confirmed by getting an exception when trying to register a device with the above template:

System.AggregateException: One or more errors occurred. (There are multiple root elements.)
 ---> System.Xml.XmlException: There are multiple root elements.
   at System.Xml.XmlExceptionHelper.ThrowXmlException(XmlDictionaryReader reader, String res, String arg1, String arg2, String arg3)
   at System.Xml.XmlBaseReader.EnterScope()
   at System.Runtime.Serialization.Json.XmlJsonReader.ReadNonExistentElementName(StringHandleConstStringType elementName)
   at System.Runtime.Serialization.Json.XmlJsonReader.Read()
   at System.Xml.Linq.XContainer.ReadContentFrom(XmlReader r)
   at System.Xml.Linq.XContainer.ReadContentFrom(XmlReader r, LoadOptions o)
   at System.Xml.Linq.XDocument.Load(XmlReader reader, LoadOptions options)
   at Microsoft.Azure.NotificationHubs.FcmTemplateRegistrationDescription.OnValidate()
   at Microsoft.Azure.NotificationHubs.RegistrationDescription.Validate(Boolean checkExpirationTime)
   at Microsoft.Azure.NotificationHubs.RegistrationSDKHelper.ValidateRegistration(RegistrationDescription registration)
   at Microsoft.Azure.NotificationHubs.NotificationHubClient.CreateOrUpdateRegistrationImplAsync[TRegistration](TRegistration registration, EntityOperatonType operationType, CancellationToken cancellationToken)

Reproduction code

Here a simple code example to reproduce the issue (just put your own connection string of course):

var hub = NotificationHubClient.CreateClientFromConnectionString("put your connection string here", "your hub name");
var registration = new FcmTemplateRegistrationDescription(token, @"
            {
                ""data"":{
                    ""message"":""$(message)"",
                },
                ""priority"":""high""
            }");
registration.RegistrationId = await hub.CreateRegistrationIdAsync();
await hub.CreateOrUpdateRegistrationAsync(registration); //will raise exception
stpatrick2016 commented 3 years ago

Opened a new issue, since I cannot reopen this one: #176

stpatrick2016 commented 3 years ago

@JanNepras I see you have the same problem as me - I already commented in the bug I opened and closed it. The problem is the extra comma in your json: ""title"":""value2"",<--this comma, it should be removed