question

joel-2 avatar image
joel-2 asked

Getting custom data from push notifications via RemoteNotification.userInfo on Unity iOS

I'm sending a push notification via server.SendPushNotification to an iOS Unity client. It shows up in

NotificationServices.remoteNotifications

However, the userData field is empty. As I understand it, this should contain the whole payload, including any custom fields that I add, but it doesn't.

My payload looks a bit like this:

const applePayload = {
    alert: {
      title: "some subject",
      body: "some body"
    },
    custom_info: "some custom info"
  };  
  
  const pushRequest = {
    Recipient: currentPlayerId,
    {
      Platform: "ApplePushNotificationService",          
      Json: JSON.stringify(applePayload)
    }]
  };


  server.SendPushNotification(pushRequest);  

Is this not currently supported on iOS? I know Android had advanced features first but I was under the impression that both had them now (I haven't tried with Android yet).

As a note, I also tried using the 'Package' field of the SendPushNotificationRequest and setting the CustomData, but that didn't work either. I tested both receiving inside and outside my application.

Push Notifications
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Andy avatar image
Andy answered

It looks like your request may be malformed. You're missing an AdvancedPushPlatformMsg identifier.

1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

joel-2 avatar image joel-2 commented ·

Oh sorry, you're right but that wasn't the actual code. You can check it on title 1218. I didn't want to confuse the issue with other stuff but here's the real function:

handlers.sendPushNotification = function (args, context) {
  const androidPayload = {
    title: args.subject,
    body: args.message,
    android_channel_id: args.android_channel_id,
    sound: args.sound_file_name,
    custom_info: args.custom_info
  };
  
  const applePayload = {
    alert: {
      title: args.subject,
      body: args.message
    },
    sound: "Data/Raw/" + args.sound_file_name,
    custom_info: args.custom_info
  };  
  
  const pushRequest = {
    Recipient: currentPlayerId,
    AdvancedPlatformDelivery : [{
      Platform: "GoogleCloudMessaging",          
      Json: JSON.stringify(androidPayload)
    }, 
    {
      Platform: "ApplePushNotificationService",          
      Json: JSON.stringify(applePayload)
    }]
  };


  server.SendPushNotification(pushRequest);  
}

As you can see, I havent missed out the identifer :)

0 Likes 0 ·
Seth Du avatar image
Seth Du answered

I am not sure if JSON.stringify() can generate the data in a proper format that PlayFab accepts.

the proper JSON data is like:

Escape characters should be used for quote marks and you may try again and see if you can receive the correct payload.


13 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

joel-2 avatar image joel-2 commented ·

Thanks Seth. I'm still trying but I haven't had any luck with what you wrote. I'm not sure it's the issue since using the 'Package' field didn't work. Any other ideas?

0 Likes 0 ·
Seth Du avatar image Seth Du ♦ joel-2 commented ·

Please try the below code, I have successfully received these two notifications in onMessageReceived Function, and be aware that AdvancedPlatformDelivery will not show in the notification bar):

handlers.push = function (context) {
    //Please try the Following code:


    var request1 = {
        "Recipient": currentPlayerId,
        "Package":
        {
            "Message": "Package test filled",
            "Title": "package title",
        }
    };


    var request2 = {
        "Recipient": currentPlayerId,
        "AdvancedPlatformDelivery": [{
            "Platform": "GoogleCloudMessaging",
            "Json": "{\"title\": \"args.subject\",\"body\": \"args.message\",\"android_channel_id\":\"args.android_channel_id\"}"
        }]
    };


    //to send Package notification
    server.SendPushNotification(request1);


    //to send AdvancedPlatformDelivery notification
    server.SendPushNotification(request2);
};
0 Likes 0 ·
joel-2 avatar image joel-2 Seth Du ♦ commented ·

I do receive the message. That works well. There just isn't anything in the userData field.

So for example if you added a field to request2.AdvancedPlatformDelivery.Json, have you checked that that shows up? You can read the userData field and process the data?

0 Likes 0 ·
Show more comments
joel-2 avatar image joel-2 commented ·

Oh sorry I should have been more clear. I'm talking about the Unity SDK and what is reported by UnityEngine.iOS.NotificationServices.

Do I need a plugin to handle that 'onMessageReceived' function and pass it through to Unity?

0 Likes 0 ·
Seth Du avatar image Seth Du ♦ joel-2 commented ·

I was trying to say that both message, package and AdvancedPlatformDelivery can work fine. I was using an Android App to receive notifications and I believe these methods will work as well on Unity iOS App. For now, according your code,all I can to say is to be aware of the format of Json string.

Currently, I do not have iOS development environment hence it will be hard for me to do a full test, but there is an tutorial you can refer to from Unity official website: https://docs.unity3d.com/Packages/com.unity.mobile.notifications@1.0/manual/index.html

0 Likes 0 ·
joel-2 avatar image joel-2 commented ·

OK yeah sounds like it should work, but I can't get it going right now.

It could be the JSON format but there is no error to diagnose unfortunately. The extra fields just aren't there. That's a shame you don't have an iOS dev environment now. So are you saying that you haven't tested the iOS userData field of RemoteNotifications in the past?

Thanks for the tutorial but it doesn't seem to mention the custom data. I also should mention that we are on 2017.3

0 Likes 0 ·
Andy avatar image Andy ♦♦ joel-2 commented ·

Are you following the guidance for crafting a JSON payload for APNS? https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html#//apple_ref/doc/uid/TP40008194-CH17-SW1 That calls out a fairly specific structure for the advanced payload. Specifically, this bit is of interest:

The JSON dictionary object must contain an aps key, the value of which is a dictionary containing data used by the system to deliver the notification.

0 Likes 0 ·
joel-2 avatar image joel-2 Andy ♦♦ commented ·

Yeah I tried but no joy. Well if it required the APS thing the neither what I wrote or what Seth wrote would get delivered at all right? I did try sending it with an APS key but it didn't work, so I assumed that everything in the payload is what is contained in the APS section. It is received, there are just no extra data fields, as there should be as specified here about custom keys: https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/generating_a_remote_notification

0 Likes 0 ·
Show more comments
joel-2 avatar image joel-2 commented ·

The full JSON copied from PlayStream is too long for a comment unfortunately. Can I send it somewhere?

0 Likes 0 ·
Andy avatar image Andy ♦♦ joel-2 commented ·

Assuming this is title 1218, the unescaped JSON from one of the push notifications I saw looked like this:

"APNS":{
 "aps":{
  "alert":{
   "title":"test sound subject",
   "body":"test sound message"
  },
  "sound":"Data/Raw/push_notification_sound"
 }
}

I don't see any custom data in there. I assume there's a push notification message in there with a significantly different payload. If the comment character length is getting in the way, you can post it as an "answer" instead.

0 Likes 0 ·
joel-2 avatar image joel-2 Andy ♦♦ commented ·

That title is correct, but the latest revision didn't have my experimental changes.
Reading back through the thread, I feel like I haven't been as clear as I could be on some points so I'm going to post an answer that includes all of the relevant information to make it easier for you guys to debug.

0 Likes 0 ·
joel-2 avatar image
joel-2 answered
On title 1218, I run cloud script sendIosPushWithCustomData on Revision 306. Here it is:


handlers.sendIosPushWithCustomData = function (args, context) {
  const applePayload = {
    alert: {
      title: "A title",
      body: "A body"
    },
    custom_info: "Some custom data"
  };
  
  log.info(JSON.stringify(applePayload));
  
  const pushRequest = {
    Recipient: currentPlayerId,
    AdvancedPlatformDelivery : [ 
    {
      Platform: "ApplePushNotificationService",          
      Json: JSON.stringify(applePayload)
    }]
  };


  server.SendPushNotification(pushRequest);  
}


I ran this from the GameManager section for that player, with no arguments.


Result was:
'SUCCESS'
{
    "FunctionResult": null,
    "Logs": [
        {
            "Level": "Info",
            "Message": "{\"alert\":{\"title\":\"A title\",\"body\":\"A body\"},\"custom_info\":\"Some custom data\"}",
            "Data": null
        }
    ],
    "ExecutionTimeSeconds": 0.054545699999999996,
    "MemoryConsumedBytes": 34728,
    "APIRequestsIssued": 1,
    "HttpRequestsIssued": 0,
    "Error": null
}


In the PlayStream, there are two new events. One about executing the cloud script, and the other saying 'Sent Push notification'.
In the second one, here is the raw event JSON:
{
    "EventName": "sent_push_notification",
    "PushNotificationTemplateId": null,
    "PushNotificationTemplateName": null,
    "Success": true,
    "ErrorName": null,
    "ErrorMessage": null,
    "Subject": null,
    "Body": "{\"default\":null,\"GCM\":\"{\\\"notification\\\":{},\\\"data\\\":{}}\",\"APNS\":\"{\\\"aps\\\":{\\\"alert\\\":{\\\"title\\\":\\\"A title\\\",\\\"body\\\":\\\"A body\\\"},\\\"custom_info\\\":\\\"Some custom data\\\"}}\",\"APNS_SANDBOX\":\"{\\\"aps\\\":{\\\"alert\\\":{\\\"title\\\":\\\"A title\\\",\\\"body\\\":\\\"A body\\\"},\\\"custom_info\\\":\\\"Some custom data\\\"}}\"}",
    "Language": null,
    "EventNamespace": "com.playfab",
    "EntityType": "player",
    "Source": "PlayFab",
    "TitleId": "1218",
    "EntityId": "AC3DB8681C59704A",
    "EventId": "2451aec57ab0427fb9f416aa8eaba921",
    "SourceType": "BackEnd",
    "Timestamp": "2019-04-08T06:26:35.3704376Z",
    "History": null,
    "CustomTags": null,
    "Reserved": null,
    "PlayFabEnvironment": {
        "Vertical": "master",
        "Cloud": "main",
        "Application": "mainservercloudscriptint",
        "Commit": "adf7bd3"
    }
}


This was run when that player did not have the app running (not in the background either).
The push notification shows up on the device as expected with our app icon, 'A title' and 'A body'.
Clicking it opens the Unity app.


In the Unity app, I run this code:
Debug.LogErrorFormat("=====\nFound {0} notifications\n=====",
                     NotificationServices.remoteNotificationCount);


if (NotificationServices.remoteNotificationCount == 1)
{
    RemoteNotification push = NotificationServices.remoteNotifications[0];
    Debug.LogErrorFormat("=====\nFound {0} user entries\n=====",
                         push.userInfo.Count);
}


The result is 1 notifications with 0 user entries.


According to this: https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html#//apple_ref/doc/uid/TP40008194-CH17-SW1
"In addition to the aps dictionary, the JSON dictionary can include custom keys and values with your app-specific content. Custom values must use the JSON structure and use only primitive types such as dictionary (object), array, string, number, and Boolean. "


As you can see from the PlayStream event body, everything that I included in the Json field of the AdvancedPlatformDelivery is *inside* the aps dictionary, whereas custom fields must be alongside it. That's the reason why it seems like custom data isn't supported.


So therefore, could you find out if it actually isn't supported?
1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

joel-2 avatar image joel-2 commented ·

Any follow-up on this please?

0 Likes 0 ·

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.