본문 바로가기

일::개발

Flutter Push Notification (4) - 푸시 알림에 이미지 넣어서 보내기

계획에 없었지만, 된다고 해서 해본 푸시 알림에 이미지 넣어서 보내는 방법.

 

일단 안드로이드의 경우에는 특별히 해줄 것이 없다. 그냥 메시지 전송할 때 이미지 URL을 넣어서 보내주기만 하면 된다.

Firebase Console 에서는 테스트 메시지 발송할 때 Notification image 필드에 이미지 URL을 넣어주면 되고,

Firebase API를 이용해서 서버에서 발송할 경우에는 메시지를 아래와 같이 구성해주면 된다.

 

message = {
  notification: {
    body: 'This is an FCM notification that displays an image!',
    title: 'FCM Notification',
  },
  android: {
    notification: {
      image: '{image-url}',
    },
  },
};

 

그 다음으로 iOS가 문제인데, iOS에서 이미지가 포함된 푸시메시지를 보여주기 위해서는 service extension을 만들어야 한다.

 

xcode에서 File > New > Target 선택한 후에 타겟 종류 고르는 dialog 에서 iOS, Notification Service Extension 찾아서 선택해준다.

이름은 아무거나 해 줘도 되는데, 가이드에 있는 것처럼 ImageNotification으로 해주고,

Language는 Objective-C로 골라준다. (Runner는 swift로 만들었어도 Objective-C 로 만든 extension을 사용하는데 문제 없다.)

 

추가된 ImageNotification Extension에 만들어진 NotificationService.m 파일을 다음과 같이 수정한다.

 

#import "NotificationService.h"
#import "FirebaseMessaging.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];
//
//    self.contentHandler(self.bestAttemptContent);
    [[FIRMessaging extensionHelper] populateNotificationContent:self.bestAttemptContent withContentHandler:contentHandler];
}

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

@end

 

다음으로 Podfile 에

target 'ImageNotification' do
  use_frameworks!
  pod 'Firebase/Messaging'
end

를 추가해주면 된다.

 

여기까지가 Firebase에서 제공하는 가이드의 끝인데, 이 다음에 고생을 좀 했다.

 

1. 빌드 실패

 

FirebaseMessaging.h file not found 에러가 나면서 빌드가 되지 않을 때는 Pod 파일들을 지우고 다시 설치해준다.

Podfile.lock 와 Pods 디렉토리를 지우는 것 만으로는 정상동작 하지 않을 수 있다.

 

> sudo gem install cocoapods-deintegrate cocoapods-clean
> pod deintegrate
> pod cache clean --all
> flutter clean
> rm Podsfile.lock
> rm -rf Pods
> flutter pub get
> pod install

나의 경우에는 이렇게 프로젝트에서 CocoaPods를 제거했다가 다시 설치하니 FirebaseMessaging.h file not found 문제가 해결되었다.

 

또 다른 문제로 빌드가 안 될 때 ImageNotification 의 Build Settings 메뉴에서 Enable Bitcode 를 No 로 설정하라는 말도 있는데, 나의 경우에는 Yes로 설정해도 빌드에 문제가 없었다.

 

몇 가지 영향을 줄 수 있는 설정을 보자면 (TARGET을 ImageNotification 으로 설정한 것에 주의하자)

 

1

 

2. 시뮬레이터에서 빌드 실패

위의 1번 과정을 거친 후에 실제 디바이스에서는 빌드가 되지만 시뮬레이터에서는 안 된다면 Runner에서처럼 ImageNotification Target에서도 Excluded Architectures에 arm64와 i386을 추가해준다.

 

 

3. 빌드는 되지만 푸시 메시지에 이미지가 노출되지 않을 때

정상적으로 빌드가 되었으나 푸시 메시지에 이미지가 노출되지 않으면

1) 메시지에 이미지를 올바르게 넣어서 보냈는지 확인 (아래 메시지 샘플 확인)

2) 안드로이드에서는 정상적으로 동작하는지 확인

3) ImageNotification 의 Deployment 대상 확인 : General 탭에서 Deployment Info 에 iOS 버전이 Runner와 맞게 되어 있는지 확인한다. 이 값이 테스트하는 디바이스보다 크게 되어 있으면 이미지가 보이지 않는다.

 

 

이렇게 하면 메시지에 이미지가 같이 표시된다.

단, 안드로이드에서 Foreground 일 때는 알림을 flutter_local_notifications 패키지를 사용해서 별도로 표시해줬기 때문에 역시 별도로 처리해줘야 한다.

이것은 다음에 기회 되면 포스트하기로 하고,

 

아래는 Firebase API를 이용해서 이미지가 포함된 메시지 전송할 때 메시지 파라미터이다. 

 

[iOS에서 Push notificatin에 이미지 추가]

message = {
  notification: {
    body: 'This is an FCM notification that displays an image!',
    title: 'FCM Notification',
  },
  apns: {
    payload: {
      aps: {
        'mutable-content': 1, // 1 or true
      },
    },
    fcm_options: {
      image: '{image-url}',
    },
  },
};

 

[iOS, 안드로이드 모두 한번에 이미지 넣어서 전송]

message = {
  tokens: registrationTokens,
  notification: {
    body: 'This is an FCM notification that displays an image!',
    title: 'FCM Notification',
  },
  apns: {
    payload: {
      aps: {
        'mutable-content': 1,
      },
    },
    fcm_options: {
      image: '{image-url}',
    },
  },
  android: {
    notification: {
      image: '{image-url}',
    },
  },
};

 

 

아래는 참고한 reference

https://firebase.flutter.dev/docs/messaging/apple-integration/#advanced-optional-allowing-notification-images

https://documentation.onesignal.com/docs/notification-images-not-showing

https://documentation.onesignal.com/docs/service-extensions#troubleshooting-the-ios-notification-service-extension

 

Service Extensions

Using the iOS and Android Notification Service Extension in your mobile apps.

documentation.onesignal.com