Custom Push Notification with image

Are you looking for help?

Backendless Version (3.x / 5.x, Online / Managed / Pro )

4.5.0 iOS

Client SDK (REST / Android / Objective-C / Swift / JS )

4.5.0 iOS (Objective C)

Application ID

96CDE131-62F9-4B38-FF04-45D11DF21000

Expected Behavior

I would like to add two keys to iOS payload, with key “category” and “mutable-content” inside “aps” like, in order to show image in push notification with iOS Notification Service Extension, example in https://medium.com/@lucasgoesvalle/custom-push-notification-with-image-and-interactions-on-ios-swift-4-ffdbde1f457

{
“aps”:{
alert = {
body = “message boday“;
subtitle = “”;
title = “Message title”;
};
“badge”:1,
“sound”:“default”,
"category":“imageNotification”,
"mutable-content":"1"
}
}

Please describe the expected behavior of the issue, starting from the first action.

1.Sending message from iOS or Android devices.
2. Customize the payload for iOS with the key “aps”, add two keys to iOS payload, with key “category” and “mutable-content”
3.On iOS device, using Notification Service Extension, I could show an image on the right of the push notification message.
4. I have tried to construct the whole payload from iOS with the PublishOptions, but the two new keys “category” and “mutable-content” wouldn’t be in the message sent out.

PublishOptions *publishOptions = [PublishOptions new];
    [publishOptions removeHeader:@"aps"];
    
    NSDictionary *header = [[NSMutableDictionary alloc] init];
    [header setValue:chatTitle forKey:@"android-alert-title"];
    [header setValue:chatTitle forKey:@"ios-alert-title"];
    [header setValue:@"default" forKey:@"ios-sound"];

    if (imageUrl) {
        [header setValue:imageUrl forKey:@"imageUrl"];
    }
    
    NSDictionary *alert = [[NSMutableDictionary alloc] init];
    [alert setValue:body forKey:@"body"];
    [alert setValue:@"" forKey:@"subtitle"];
    [alert setValue:chatTitle forKey:@"title"];

    NSDictionary *aps = [[NSMutableDictionary alloc] init];
    [aps setValue:alert forKey:@"alert"];
    [aps setValue:@"default" forKey:@"sound"];
    
    if (imageUrl) {
        [aps setValue:@"attachmentCategory" forKey:@"category"];
        [aps setValue:@"1" forKey:@"mutable-content"];
    }
    
    [header setValue:aps forKey:@"aps"];
   
    [publishOptions assignHeaders:header];

Actual Behavior

Please provide a description of what actually happens, working from the same starting point.

  1. When iOS device received the push notification, the key “category” and “mutable-content” doesn’t exist in “aps” of the response.notification.request.content.userInfo
  2. No image is in the push notification because “mutable-content” not in the payload.

Hello Jay,

I highly recommend you to use our Swift-SDK instead of iOS-SDK.
iOS-SDK is outdated since v5.6.0 and there won’t be any new features or fixes available for Swift-SDK.

Please make sure you’ve configured your project correctly: https://backendless.com/docs/ios/push_xcode_setup_for_apn.html

Here is a valid code for push notification with attachment using Swift-SDK and it works just fine. Obj-C code is similar.

let publishOptions = PublishOptions()
publishOptions.setHeaders(headers: ["ios-alert": "Alert message",
                                    "ios-badge": 1,
                                    "ios-sound": "default",
                                    "mutable-content" : 1,
                                    "attachment-url": "https://upload.wikimedia.org/wikipedia/commons/c/c9/Moon.jpg"])

let deliveryOptions = DeliveryOptions()
deliveryOptions.setPublishPolicy(publishPolicy: PublishPolicyEnum.PUSH.rawValue)

Backendless.shared.messaging.publish(channelName: "default", message: "Test message", publishOptions: publishOptions, deliveryOptions: deliveryOptions, responseHandler: { messageStatus in
    print("Message status: \(messageStatus)")
}, errorHandler: { fault in
    print("Error: \(fault.message ?? "")")            
})

Regards,
Olha

I have update to pod ‘BackendlessSwift’. - BackendlessSwift (5.6.6):
Here’s my new code

#import <Backendless/Backendless-Swift.h>

PublishOptions *publishOptions = [PublishOptions new];

[publishOptions setHeadersWithHeaders:@{@“ios-alert-title”:chatTitle,
@“attachment-url”:imageUrl,
@“ios-alert-body”:message,
@“android-alert-title”:chatTitle,
@“mutable-content”:@“1”,
@“ios-sound”:@“default”}];

DeliveryOptions *deliveryOptions = [DeliveryOptions new];
[deliveryOptions setPushBroadcastWithPushBroadcast:PushBroadcastEnumFOR_ALL];
[deliveryOptions setPublishPolicyWithPublishPolicy:PublishPolicyEnumPUSH];

[Backendless.shared.messaging publishWithChannelName:channel
message:nil
publishOptions:publishOptions
deliveryOptions:deliveryOptions
responseHandler:^(MessageStatus *status) {
NSLog(@“message push to chancel %@, MessageStatus = %@”, channel, status);
} errorHandler:^(Fault *fault) {
NSLog(@“message push to chancel %@, fail %@”, channel, fault.message);
}];

It keep crashing in class PersistenceServiceUtils at line 471
let resultClass = type(of: entity) as ! NSObject.Type

Hello, @jay-maharaj

I’ve checked with Swift-SDK v5.7.6.

You should receive this warning

Null passed to a callee that requires a non-null argument

when calling

[Backendless.shared.messaging publishWithChannelName:channel
message:nil...]

The publish method requires message != nil. In case you have alert-title and alert-body they will show instead of that message.

Here is a part of code that works fine:

PublishOptions *publishOptions = [PublishOptions new];
[publishOptions setHeadersWithHeaders:@{
    @"ios-alert-title": @"Title",
    @"attachment-url": @"https://upload.wikimedia.org/wikipedia/commons/c/c9/Moon.jpg",
    @"ios-alert-body": @"Body",
    @"android-alert-title": @"Title",
    @"mutable-content": @1,
    @"ios-sound": @"default"
 }];
    
DeliveryOptions *deliveryOptions = [DeliveryOptions new];
[deliveryOptions setPushBroadcastWithPushBroadcast:PushBroadcastEnumFOR_ALL];
[deliveryOptions setPublishPolicyWithPublishPolicy:PublishPolicyEnumPUSH];
    
[Backendless.shared.messaging publishWithChannelName:@"default" message:@"Message" publishOptions:publishOptions deliveryOptions:deliveryOptions responseHandler:^(MessageStatus *status) {
    NSLog(@"Pushed");
} errorHandler:^(Fault *fault) {
    NSLog(@"Push error: %@", fault.message);
}];

And the result notification looks like

Regards,
Olha