4

My question might be bad, but I can't find any answer anywhere, I'm lost...


So I want to display a rich notification with a nice image in iOS 10+.

For this I'm using FCM and an UNNotificationServiceExtension which, if I understood correctly, should get the Data payload, find the image URL and load it before modifying the UNNotificationContent.

The issue I have is that I can't get a hold of this "data".

What I'm sending to FCM is the following :

{
"to": "device_token",
"content_available": true,
"mutable_content": true,
"badge" : 9,
"notification": {
    "title": "You still need the iPhone ?",
    "body": "Give it back if you finished you tests !"
},
"data": {
    "message": "test !",
    "mediaUrl": "http://usr.audioasylum.com/images/2/20352/Cat_and_rose.jpg"
},
"priority": "high"
}

What I get in the phone is :

{
aps =     {
    alert =         {
        body = "Give it back if you finished you tests !";
        title = "You still need the iPhone ?";
    };
    "content-available" = 1;
    "mutable-content" = 1;
};
"gcm.message_id" = "0:1489054783357873%1ee659bb1ee659bb";
mediaUrl = "http://usr.audioasylum.com/images/2/20352/Cat_and_rose.jpg";
message = "Offer!";
}

As I understand it, the mediaURL and message should end up in "aps" and not outside, which is why I can't find them in the extension.

And inside the extension I get : (I split it on coma for more readability)

<UNNotificationRequest: 0x117d3c170;
identifier: FDC13B60-FE5A-40C6-896D-06D422043CCE
content: <UNNotificationContent: 0x117d3a650; title: You still need the iPhone ?
subtitle: (null)
body: Give it back if you finished you tests !
categoryIdentifier: 
launchImageName: 
peopleIdentifiers: ()
threadIdentifier: 
attachments: ()
badge: (null)
sound: (null)
hasDefaultAction: YES
shouldAddToNotificationsList: YES
shouldAlwaysAlertWhileAppIsForeground: NO
shouldLockDevice: NO
shouldPauseMedia: NO
isSnoozeable: NO
fromSnooze: NO
darwinNotificationName: (null)
darwinSnoozedNotificationName: (null)
trigger: <UNPushNotificationTrigger: 0x117d3fe90; contentAvailable: YES
 mutableContent: YES>>

Is the problem how I send information with FCM, or the way I retrieve them? Maybe it's the way I treat them ?

As always, thanks for the help!

Edit : Added code for the receiver (which is just a print in the extension)

@interface NotificationService ()

@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;

@end

@implementation NotificationService

- (void) didReceiveNotificationRequest: (UNNotificationRequest *) request
                    withContentHandler: (void (^)(UNNotificationContent *_Nonnull))contentHandler
{
    self.contentHandler = contentHandler;
    self.bestAttemptContent = [request.content mutableCopy];

    NSLog(@"------------------- %@ -------------------", request);

    // Modify the notification content here...
    self.bestAttemptContent.title = [NSString stringWithFormat:@"%@ [modified]", self.bestAttemptContent.title];
    self.bestAttemptContent.body = [NSString stringWithFormat:@"%@", request.content];
    self.contentHandler(self.bestAttemptContent);
}
SeikoTheWiz
  • 853
  • 1
  • 10
  • 27
  • Hi. I think it would help the community if you could post your code snippets for receiving the messages. :) – AL. Mar 10 '17 at 23:09
  • 1
    Done, but it's really just a print in the code sample :) – SeikoTheWiz Mar 11 '17 at 08:16
  • Hi @SeikoTheWiz Sorry I haven't been much help here. I also saw your comment in my answer [here](http://stackoverflow.com/a/42263795/4625829) (is it related to this post?). I'll try to look around and see what I find for you here (but can't really promise anything). One thing that caught my attention in your post so far though is that the `badge` parameter should be inside your `notification`. Anyways, you were hoping for an explanation on how the behavior is for `data` payloads, right? On why the data appears outside of `aps`? – AL. Mar 15 '17 at 04:41
  • 1
    Yes exactly, my understanding is that in the case of a NotificationServiceExtension everything that can be accessed from the extension is what's inside "aps". If you take this post https://blog.pusher.com/how-to-send-ios-10-notifications-using-the-push-notifications-api/ , in this example the payload he sends has a data inside the "aps" which can then be used inside with request.content.userInfo["data"]. edit : didn't realise it was you also in the other topic :D – SeikoTheWiz Mar 15 '17 at 08:16
  • I haven't delved much on APNs behavior with FCM yet. But I'll sure to let you know (hopefully provide an answer) if I got look into it more. :) – AL. Mar 15 '17 at 09:41
  • Thanks a lot :) ! – SeikoTheWiz Mar 15 '17 at 10:04
  • @SeikoTheWiz, could you guide me how to put field 'mutable_content' into field 'aps' using Firebase Console. Firebase seems not to support changing field 'aps' in Console yet – Scofield Tran Mar 06 '18 at 00:56
  • @ScofieldTran sorry I can't I've only done payload manually. Never actually used their console. – SeikoTheWiz Mar 06 '18 at 07:44

2 Answers2

2

I think you should check self.bestAttemptContent?.userInfo for mediaUrl data.

redism
  • 500
  • 7
  • 18
1

I'm seeing two main questions here:

The issue I have is that I can't get a hold of this "data".

You mentioned that you're expecting that the mediaUrl parameter should be inside aps.

Seeing as you included the mediaUrl in your data payload, the behavior is just as expected (mediaUrl is outside aps). To get the details, you'll have to implement what was stated in the documentation:

Receive data messages on iOS 10

To receive data messages when your app is in the foreground, on iOS 10 devices, you'll need to handle applicationReceivedRemoteMessage:. Your app can still receive data messages when it is in the background without this callback, but for foreground cases you'll need logic like the following in your app delegate:

#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
// Receive data message on iOS 10 devices while app is in the foreground.
- (void)applicationReceivedRemoteMessage:(FIRMessagingRemoteMessage *)remoteMessage {
  // Print full message
  NSLog(@"%@", remoteMessage.appData);
}
#endif

P.S.: I'm not entirely sure if you already tried this out, but there wasn't any similar code in your post so I figured this should be tried.

As I understand it, the mediaURL and message should end up in "aps" and not outside, which is why I can't find them in the extension.

The thing is, there are only specific parameters that are to be expected inside aps:

Any other keys in the aps dictionary are ignored by Apple.

At the same time, there are only some corresponding parameters that you can use in FCM that will appear in the aps payload. With that, you should simply expect that any custom key-value pair you include will be outside the aps parameter. From the Apple docs above (emphasis mine):

In addition to the aps dictionary, the JSON dictionary can include custom keys and values with your app-specific content.

With regards to the blog you linked in the comments, I haven't looked to deeply into it since it's not really using FCM, where it would be best to presume that the behavior is different.

AL.
  • 36,815
  • 10
  • 142
  • 281
  • It took some time before I got back here and managed to go through the question with *fresh eyes*. I hope I did get what you need on point. The documentation usually has what you need on [Receiving Messages in iOS](https://firebase.google.com/docs/cloud-messaging/ios/receive). – AL. Mar 31 '17 at 06:39
  • Thank you for your answer! The issue is when I want to push a notification when the application is not running. The only way to modify what's happening is running through the UNNotificationServiceExtension, which then modify the notification and let the system display it. applicationReceivedRemoteMessage is not called in this scenario. Or maybe I'm doing something wrong and the extension should wake the application up and go through the normal process afterward? – SeikoTheWiz Mar 31 '17 at 12:31