| [ Web Proxy ] |
| Viewing: https://docs.leanplum.com/docs/adding-images-to-push-notifications | [Back] [Original] |
Push notification images and requirements
Apart from text, push notifications can include an image or gif, enriching the customer experience. Before you start sending Rich Push Notifications, there are a few steps that must be followed:
Before you can add images to your push notifications, you should check with your development team to ensure your app has been properly configured to receive rich push. See our full push setup instructions and rich push setup for more.
The image will only be visible if your app is configured to support rich push, and only on devices with the minimum required OS version. Otherwise, users will see just the message text.
iOS limitations
Android limitations
We recommend thoroughly testing on both iOS and Android devices to ensure the image is rendering as expected (see Android limitations above).
Make sure your message copy still makes sense without the image so that users on incompatible app versions will still understand the message. If you would like to send your message only to users who are rich push-compatible, reach out to your customer success manager and they can add a custom target for you.
1. Create a Notification Service Extension
Within your project, you must create a Service Extension. A Service Extension allows for the modification of a notification to include rich media. To add a notification service extension, click on File > New > Target and select Notification Service Extension.
2. Setting up Notification Service Extension
Since the Notification Service Extension has its own bundle id, it must be set up with its own App ID and provisioning profile. Please verify through the Apple Developer Service.
3. Add the following code to Notification Service Extension
While you are free to implement your own method within the Notification Service Extension, you will need to make sure that your code is correctly handling the media that is being sent with Leanplum. The key that is associated with the rich media in the Leanplum Payload is: LP_URL.
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
let imageKey = "LP_URL"
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
// MARK: - Leanplum Rich Push
if let bestAttemptContent = bestAttemptContent {
let userInfo = request.content.userInfo;
// LP_URL is the key that is used from Leanplum to
// send the image URL in the payload.
//
// If there is no LP_URL in the payload than
// the code will still show the push notification.
if userInfo[imageKey] == nil {
contentHandler(bestAttemptContent);
return;
}
// If there is an image in the payload,
// download and display the image.
if let attachmentMedia = userInfo[imageKey] as? String {
let mediaUrl = URL(string: attachmentMedia)
let LPSession = URLSession(configuration: .default)
LPSession.downloadTask(with: mediaUrl!, completionHandler: { temporaryLocation, response, error in
if let err = error {
print("Leanplum: Error with downloading rich push: \(String(describing: err.localizedDescription))")
contentHandler(bestAttemptContent);
return;
}
let fileType = self.determineType(fileType: (response?.mimeType)!)
let fileName = temporaryLocation?.lastPathComponent.appending(fileType)
let temporaryDirectory = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(fileName!)
do {
try FileManager.default.moveItem(at: temporaryLocation!, to: temporaryDirectory)
let attachment = try UNNotificationAttachment(identifier: "", url: temporaryDirectory, options: nil)
bestAttemptContent.attachments = [attachment];
contentHandler(bestAttemptContent);
// The file should be removed automatically from temp
// Delete it manually if it is not
if FileManager.default.fileExists(atPath: temporaryDirectory.path) {
try FileManager.default.removeItem(at: temporaryDirectory)
}
} catch {
print("Leanplum: Error with the rich push attachment: \(error)")
contentHandler(bestAttemptContent);
return;
}
}).resume()
}
}
}
override func serviceExtensionTimeWillExpire() {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
// MARK: - Leanplum Rich Push
func determineType(fileType: String) -> String {
// Determines the file type of the attachment to append to URL.
if fileType == "image/jpeg" {
return ".jpg";
}
if fileType == "image/gif" {
return ".gif";
}
if fileType == "image/png" {
return ".png";
} else {
return ".tmp";
}
}
}@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];
NSDictionary *userInfo = request.content.userInfo;
// LP_URL is the key that is used from Leanplum to
// send the image URL in the payload.
//
// If there is no LP_URL in the payload than
// the code will still show the push notification.
if (userInfo == nil || userInfo[@"LP_URL"] == nil) {
self.contentHandler(self.bestAttemptContent);
return;
}
NSString *attachmentMedia = userInfo[@"LP_URL"];
// If there is an image in the payload, this part
// will handle the downloading and displaying of the image.
if (attachmentMedia) {
NSURL *URL = [NSURL URLWithString:attachmentMedia];
NSURLSession *LPSession = [NSURLSession sessionWithConfiguration:
[NSURLSessionConfiguration defaultSessionConfiguration]];
[[LPSession downloadTaskWithURL:URL completionHandler: ^(NSURL *temporaryLocation, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Leanplum: Error with downloading rich push: %@",
[error localizedDescription]);
self.contentHandler(self.bestAttemptContent);
return;
}
NSString *fileType = [self determineType: [response MIMEType]];
NSString *fileName = [[temporaryLocation.path lastPathComponent] stringByAppendingString:fileType];
NSString *temporaryDirectory = [NSTemporaryDirectory() stringByAppendingPathComponent:fileName];
[[NSFileManager defaultManager] moveItemAtPath:temporaryLocation.path toPath:temporaryDirectory error:&error];
NSError *attachmentError = nil;
UNNotificationAttachment *attachment =
[UNNotificationAttachment attachmentWithIdentifier:@""
URL:[NSURL fileURLWithPath:temporaryDirectory]
options:nil
error:&attachmentError];
if (attachmentError != NULL) {
NSLog(@"Leanplum: Error with the rich push attachment: %@",
[attachmentError localizedDescription]);
self.contentHandler(self.bestAttemptContent);
return;
}
self.bestAttemptContent.attachments = @[attachment];
self.contentHandler(self.bestAttemptContent);
[[NSFileManager defaultManager] removeItemAtPath:temporaryDirectory error:&error];
}] resume];
}
}
- (NSString*)determineType:(NSString *) fileType {
// Determines the file type of the attachment to append to NSURL.
if ([fileType isEqualToString:@"image/jpeg"]){
return @".jpg";
}
if ([fileType isEqualToString:@"image/gif"]) {
return @".gif";
}
if ([fileType isEqualToString:@"image/png"]) {
return @".png";
} else {
return @".tmp";
}
}
- (void)serviceExtensionTimeWillExpire {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
self.contentHandler(self.bestAttemptContent);
}
@end4. Update didReceiveRemoteNotification

Please make sure to update the application instance method didReceiveRemoteNotification so that it does execute the download of the rich media. See below for a simple example.
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable : Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
completionHandler(.newData)
}- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
completionHandler(UIBackgroundFetchResultNewData);
}5. Create a Rich Push from our Dashboard

After implementing the code above, you are free to create a rich push notification from our dashboard. Make sure to try it out on a registered test device before sending to users.
You can use Jinja syntax to set a rich push image that changes based on a parameter value for a triggered push notification.
Create a new Push notification message.
Set the URL of the image using new syntax Jinja to include your parameter.
https://myimages.com/destinations/cities/{{parameter['dest_code']}}.jpg
Make sure you use brackets around the parameter name (see 'dest_code' above).
Android event with parameter example:
HashMap<String, Object> paramsFlight = new HashMap<String, Object>();
paramsFlight.put("dest_code", "Varna");
Leanplum.track("flight_search", paramsFlight);
iOS event with parameter example:
Leanplum.track("flight_search", withParameters: ["dest_code": "Varna"])
See iOS and Android examples below:
Things to note:

In the following section, we will show you how to enable Android Notification Badges(Notification Dots) for your Android application. With this option, a dot on the app icon will be shown, when there is a pending push notification. It can show images as well.
The badges feature is supported from Leanplum Android SDK 3.0.0 and above. It is available for devices on Android O (API 26) and above and the Dots could vary in different launchers.
For more information, refer to the below-attached articles from Android:
Step-by-step guide:
Example:
{
"appId": "APP_ID",
"clientKey": "DEV_KEY",
"apiVersion": "1.0.6",
"id": "badges_vibr_magenta",
"name": "Badge, vibration and magenta",
"importance": 3,
"enableLights": true,
"enableVibration": true,
"default": true,
"showBadge": true, // Enabled Badge
"light_color": -65281 // Magenta
}Things to note:
The notification will appear in the drawer (default behavior), as well as in the notification dots. For rich pushes including an image, the image will not be shown, only the icon (app icon). The image will still be available in the notification drawer.
If you can not see the Notification Badge, verify if the Notification Dots are enabled as well since you can disable them per app or globally:
Updated 11 months ago
| Web Proxy Viewer | New URL | Original Page |