invertase / react-native-firebase

🔥 A well-tested feature-rich modular Firebase implementation for React Native. Supports both iOS & Android platforms for all Firebase services.
https://rnfirebase.io
Other
11.71k stars 2.22k forks source link

Rich Notification : attachments && BigPictureStyle #1996

Closed tgensol closed 5 years ago

tgensol commented 5 years ago

Documentation Feedback

Hi,

I want to display image in the notification on both iOS and Android. I did not find any stuff about it in the documentation.

I thought you didn't implement it, and I searched for some methods into the code, and I did find some in the DisplayNotificationTask.java or in the RNFirebaseNotifications.m.

The fact is that I did not achieve to display an image or a largeIcon after so many tries... What payload do I need to send ? Do you have any example ?

Thanking you in advance, Best regards

remigijusbalc commented 5 years ago

Hey! Check this out: https://rnfirebase.io/docs/v5.x.x/notifications/displaying-notifications https://developer.android.com/guide/topics/ui/notifiers/notifications

tgensol commented 5 years ago

Hey @remigijusbalc ,

Thanks ! I looked at your stuff but didn't see how that what is the payload I need to send for having a picture displayed in both iOS and Android ?

I think it is more linked to https://rnfirebase.io/docs/v5.x.x/messaging/receiving-messages, and the messaging part than the notification, no ?

mwillems1994 commented 5 years ago

I have the same question, have you found an answer to this. The docs keep pointing to the setLaunchImage but this doesn't seem to work.

imsantoshyadav commented 5 years ago

I am also facing this same issue.

ghost commented 5 years ago

Hi,

¿Does this means that react-native-firebase does NOT support rich notifications?

mikehardy commented 5 years ago

messaging != notifications in the firebase worldview

messaging is a massive complicated hard-to-get-right distributed system that allows mobile devices to receive data from cloud services

notifications is showing things to the user

  1. Use messaging to send a silent push with a command to the device
  2. Handle the command by building a notification
  3. Make the notification big picture if you like https://rnfirebase.io/docs/v5.x.x/notifications/reference/AndroidNotification

Unless I'm wrong, that's the chain to follow

stale[bot] commented 5 years ago

Hello 👋, to help manage issues we automatically close stale issues. This issue has been automatically marked as stale because it has not had activity for quite some time. Has this issue been fixed, or does it still require the community's attention?

This issue will be closed in 15 days if no further activity occurs. Thank you for your contributions.

DivakarPM commented 5 years ago

I am able to get the rich notification with image in push notification when app is open. But when app is not active and in background only texts are coming in notification and no images. Can somebody tell is this achievable.

tomasz89nowak commented 5 years ago

@DivakarPM yes, it is achievable. You just have to do it this way:

bgMessaging.js

import firebase from "react-native-firebase";

/**
 * this code is resolved in background, so debugger and logs doesn't work here.
 * It's easier to test code somewhere else in foreground and then paste here.
 */
export default async message => {
  const notification = new firebase.notifications.Notification();
  notification.android
    .setChannelId("notifications-channel")
    .setNotificationId(message.messageId)
    .setTitle(message.data.title)
    .setBody(message.data.body);

  if (message.data.largeIcon) {
    notification.android.setLargeIcon(message.data.largeIcon);
  }
  if (message.data.bigPicture) {
    notification.android.setBigPicture(message.data.bigPicture);
  }
  firebase.notifications().displayNotification(notification);
  return Promise.resolve();
};

index.js

AppRegistry.registerComponent("articleApp", () => AppContainer);
AppRegistry.registerHeadlessTask(
  "RNFirebaseBackgroundMessage",
  () => bgMessaging
);

important: you must send data message - there shouldn't be notification field, only data:{title, body, largeIcon | bigPicture}

tgensol commented 5 years ago

Your code is for Android right ? For iOS, if we follow your important message, it is working from scratch ?

tomasz89nowak commented 5 years ago

Your code is for Android right ? For iOS, if we follow your important message, it is working from scratch ?

Sorry, my bad, I wrote it a long time ago and I forgot that it does not work on iOS.

tgensol commented 5 years ago

@tomasz89nowak So How do you do for iOS ?

DivakarPM commented 5 years ago

@tomasz89nowak thanks for the solution.

tgensol commented 5 years ago

@tomasz89nowak Thanks for your solution. I only had to create a notification channel in my app (with the same channelID in the bgMessaging.js)

For iOS, you need to create a Notification Service. I found this stackoverflow that helped me to make it works : https://stackoverflow.com/questions/39673707/ios-10-rich-media-push-notification-media-attachment-in-objective-c

Rajesh3R commented 5 years ago

@tgensol RIch image not show in ios notification, but android working proper when app open or close

minhajul-islam commented 5 years ago

and in background only tex

i have faced this problem ,did you solve the problem

tgensol commented 5 years ago

@Rajesh3R Yes!

You have to create a Notification Service with that content for example :

//
//  NotificationService.m
//  NotificationService
//
//  Created by Thibaut on 19/07/2019.
//  Copyright © 2019 Facebook. All rights reserved.
//

#import "NotificationService.h"
@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];

    // Modify the notification content here...
//    self.bestAttemptContent.title = [NSString stringWithFormat:@"%@ [modified]", self.bestAttemptContent.title];
  NSDictionary *userInfo = request.content.userInfo;
  if (userInfo == nil) {
    [self contentComplete];
    return;
  }

  NSString *mediaUrl = userInfo[@"mediaUrl"];
  NSString *mediaType = userInfo[@"mediaType"];

  if (mediaUrl == nil || mediaType == nil) {
    [self contentComplete];
    return;
  }

  // load the attachment
  [self loadAttachmentForUrlString:mediaUrl
                          withType:mediaType
                 completionHandler:^(UNNotificationAttachment *attachment) {
                   if (attachment) {
                     self.bestAttemptContent.attachments = [NSArray arrayWithObject:attachment];
                   }
                   [self contentComplete];
                 }];

//    self.contentHandler(self.bestAttemptContent);
}

- (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);
}

- (void)contentComplete {
  self.contentHandler(self.bestAttemptContent);
}

- (NSString *)fileExtensionForMediaType:(NSString *)type {
  NSString *ext = type;

  if ([type isEqualToString:@"image"]) {
    ext = @"jpg";
  }
  return [@"." stringByAppendingString:ext];
}

- (void)loadAttachmentForUrlString:(NSString *)urlString withType:(NSString *)type completionHandler:(void(^)(UNNotificationAttachment *))completionHandler  {

  __block UNNotificationAttachment *attachment = nil;
  NSURL *attachmentURL = [NSURL URLWithString:urlString];
  NSString *fileExt = [self fileExtensionForMediaType:type];

  NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
  [[session downloadTaskWithURL:attachmentURL
              completionHandler:^(NSURL *temporaryFileLocation, NSURLResponse *response, NSError *error) {
                if (error != nil) {
                  NSLog(@"%@", error.localizedDescription);
                } else {
                  NSFileManager *fileManager = [NSFileManager defaultManager];
                  NSURL *localURL = [NSURL fileURLWithPath:[temporaryFileLocation.path stringByAppendingString:fileExt]];
                  [fileManager moveItemAtURL:temporaryFileLocation toURL:localURL error:&error];

                  NSError *attachmentError = nil;
                  attachment = [UNNotificationAttachment attachmentWithIdentifier:@"" URL:localURL options:nil error:&attachmentError];
                  if (attachmentError) {
                    NSLog(@"%@", attachmentError.localizedDescription);
                  }
                }
                completionHandler(attachment);
              }] resume];
}
@end

Then you need to send a payload like this :

apns: {
        "payload": {
            "aps": {
                "alert": {
                    "body": "YOUR MESSAGE",
                },
                "badge": 1,
                "mutable-content": 1
            },
            "mediaUrl": 'YOUR IMAGE',
            "mediaType": "image"
        }
    },
    "android": {
        "priority": "high",

        data: {
            "body": "YOUR MESSAGE",
            priority: 'high',
            largeIcon: 'YOUR IMAGE',
            bigPicture: 'YOUR IMAGE'
        }
    }

And that should work for iOS and Android (with the backgroundMessaging file)

stale[bot] commented 5 years ago

Hello 👋, to help manage issues we automatically close stale issues. This issue has been automatically marked as stale because it has not had activity for quite some time. Has this issue been fixed, or does it still require the community's attention?

This issue will be closed in 15 days if no further activity occurs. Thank you for your contributions.

stale[bot] commented 5 years ago

Closing this issue after a prolonged period of inactivity. If this is still present in the latest release, please feel free to create a new issue with up-to-date information.

luatnd commented 5 years ago

Hi, I cannot found any rnfirebase.io's documentation to push Rich notification for iOS in the background? Is react-native-firebase already support it and what was the format that I can use?

LOG-TAG commented 4 years ago

swift version of this code available?

tomonsoejang commented 4 years ago

@DivakarPM yes, it is achievable. You just have to do it this way:

bgMessaging.js

import firebase from "react-native-firebase";

/**
 * this code is resolved in background, so debugger and logs doesn't work here.
 * It's easier to test code somewhere else in foreground and then paste here.
 */
export default async message => {
  const notification = new firebase.notifications.Notification();
  notification.android
    .setChannelId("notifications-channel")
    .setNotificationId(message.messageId)
    .setTitle(message.data.title)
    .setBody(message.data.body);

  if (message.data.largeIcon) {
    notification.android.setLargeIcon(message.data.largeIcon);
  }
  if (message.data.bigPicture) {
    notification.android.setBigPicture(message.data.bigPicture);
  }
  firebase.notifications().displayNotification(notification);
  return Promise.resolve();
};

index.js

AppRegistry.registerComponent("articleApp", () => AppContainer);
AppRegistry.registerHeadlessTask(
  "RNFirebaseBackgroundMessage",
  () => bgMessaging
);

important: you must send data message - there shouldn't be notification field, only data:{title, body, largeIcon | bigPicture}

How to use this with @react-native-firebase (latest version)?