Android

  1. project level 의 build.gradle 에 buzzvil maven repoisotry 추가합니다.

    allprojects {
    	repositories {
    		maven { url "<https://dl.buzzvil.com/public/maven>" }
    	}
    }
    
  2. app level 의 build.gradle 에 BuzzBooster sdk 를 추가합니다.

    dependencies {
    	implementation("com.buzzvil:buzz-booster:4.23.+") // BuzzBooster SDK 라이브러리
    }
    
  3. BuzzBoosterModule.kt, BuzzBoosterPackage 파일을 추가합니다.

    // BuzzBoosterModule.kt
    
    package com.boostersample
    
    import android.app.Activity
    import android.content.Intent
    import android.os.Build
    import androidx.appcompat.app.AppCompatDelegate
    import com.buzzvil.booster.external.BuzzBooster
    import com.buzzvil.booster.external.BuzzBoosterActivityTag
    import com.buzzvil.booster.external.BuzzBoosterConfig
    import com.buzzvil.booster.external.BuzzBoosterJavaScriptInterface
    import com.buzzvil.booster.external.BuzzBoosterUser
    import com.buzzvil.booster.external.UserEvent
    import com.buzzvil.booster.external.UserEventListener
    import com.buzzvil.booster.external.campaign.CampaignType
    import com.buzzvil.booster.external.campaign.OptInMarketingCampaignMoveButtonClickListener
    import com.facebook.react.bridge.ActivityEventListener
    import com.facebook.react.bridge.Arguments
    import com.facebook.react.bridge.Promise
    import com.facebook.react.bridge.ReactApplicationContext
    import com.facebook.react.bridge.ReactContext
    import com.facebook.react.bridge.ReactContextBaseJavaModule
    import com.facebook.react.bridge.ReactMethod
    import com.facebook.react.bridge.ReadableMap
    import com.facebook.react.bridge.WritableMap
    import com.facebook.react.modules.core.DeviceEventManagerModule
    
    class BuzzBoosterModule(
        private val reactContext: ReactApplicationContext
    ) : ReactContextBaseJavaModule(reactContext), ActivityEventListener, OptInMarketingCampaignMoveButtonClickListener, UserEventListener {
        init {
            reactContext.addActivityEventListener(this);
        }
    
        override fun getName(): String {
            return "BuzzBooster"
        }
    
        override fun onClick() {
            BuzzBooster.getInstance().finishActivity(reactContext, BuzzBoosterActivityTag.CAMPAIGN)
            BuzzBooster.getInstance().finishActivity(reactContext, BuzzBoosterActivityTag.HOME)
            val params = Arguments.createMap()
            sendEvent(reactContext, "OptInMarketingCampaignMoveButtonClicked", params)
        }
    
        override fun onUserEvent(userEvent: UserEvent) {
            val params = Arguments.createMap().apply {
                putString("userEventName", userEvent.name)
                if (userEvent.values != null) { // null 처리 없어도 되나 iOS랑 맞추기 위해 처리
                    putMap("userEventValues", Arguments.makeNativeMap(userEvent.values))
                }
            }
            sendEvent(reactContext, "onUserEventDidOccur", params)
        }
    
        override fun onNewIntent(intent: Intent) {
            currentActivity?.apply {
                if (BuzzBooster.hasUnhandledNotificationClick(intent)) {
                    BuzzBooster.handleNotification(this, intent)
                }
            }
        }
    
        override fun onActivityResult(activity: Activity, requestCode: Int, resultCode: Int, data: Intent?) { }
    
        private fun sendEvent(reactContext: ReactContext, eventName: String, params: WritableMap?) {
            reactContext
                .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
                .emit(eventName, params);
        }
    
        @ReactMethod(isBlockingSynchronousMethod = true)
        fun initAndroidApp(appKey: String) {
            val config = BuzzBoosterConfig(appKey)
            BuzzBooster.init(reactContext, config)
            BuzzBooster.getInstance().setOptInMarketingCampaignMoveButtonClickListener(this)
            BuzzBooster.getInstance().addUserEventListener(this)
        }
    
        @ReactMethod
        fun setUser(userMap: ReadableMap?) {
            if (userMap != null) {
                val map: HashMap<String, Any> = userMap.toHashMap()
                val userId = map["userId"] as String
                val optInMarketing = map["optInMarketing"] as Boolean?
                val properties = map["properties"] as HashMap<String, Any>?
    
                val userBuilder = BuzzBoosterUser.Builder()
                    .setUserId(userId)
    
                if (optInMarketing != null){
                    userBuilder.setOptInMarketing(optInMarketing)
                }
                properties?.forEach { entry ->
                    userBuilder.addProperty(entry.key, entry.value)
                }
                BuzzBooster.setUser(userBuilder.build())
            } else {
                BuzzBooster.setUser(null)
            }
        }
    
        @ReactMethod
        fun setPushToken(token: String) {
            BuzzBooster.setFCMToken(token)
        }
    
        @ReactMethod
        fun sendEvent(eventName: String, eventValues: ReadableMap?) {
            if (eventValues == null) {
                BuzzBooster.getInstance().sendEvent(eventName)
            } else {
                try {
                    val readableMap: HashMap<String, Any> = eventValues.toHashMap()
                    val map = readableMap as Map<String, Any>
                    BuzzBooster.getInstance().sendEvent(eventName, map)
                } catch (e : RuntimeException) {
                    throw RuntimeException("${eventValues.toString()} is not validate format")
                }
            }
        }
    
        @ReactMethod
        fun showInAppMessage() {
            val activity = currentActivity
            if (activity != null) {
                BuzzBooster.getInstance().showInAppMessage(currentActivity!!)
            }
        }
    
        @ReactMethod
        fun showHome() {
            val activity = currentActivity
            if (activity != null) {
                BuzzBooster.getInstance().showHome(currentActivity!!)
            }
        }
    
        @ReactMethod
        fun showNaverPayExchange() {
            val activity = currentActivity
            if (activity != null) {
                BuzzBooster.getInstance().showNaverPayExchange(currentActivity!!)
            }
        }
    
        @ReactMethod
        fun showCampaignWithId(campaignId: String) {
            if (currentActivity != null) {
                BuzzBooster.getInstance().showCampaign(currentActivity!!, campaignId)
            }
        }
    
        @ReactMethod
        fun showCampaignWithType(campaignType: String) {
            try {
                val campaignTypeOrigin = CampaignType.valueOf(campaignType)
                if (currentActivity != null) {
                    BuzzBooster.getInstance().showCampaign(currentActivity!!, campaignTypeOrigin)
                }
            } catch (e : RuntimeException) {
                throw RuntimeException("$campaignType is not a member of CampaignType")
            }
        }
    
        @ReactMethod
        fun setTheme(theme: String) {
            when(theme) {
                "Light" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
                "Dark" -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
                "System" -> {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
                    } else {
                        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY)
                    }
                }
                else -> throw RuntimeException("$theme is not a member of Theme")
            }
        }
    
        @ReactMethod
        fun showPage(pageId: String) {
            if (currentActivity != null) {
                BuzzBooster.getInstance().showPage(currentActivity!!, pageId)
            }
        }
    
        @ReactMethod
        public fun addListener(eventName: String) { }
    
        @ReactMethod
        public fun removeListeners(count: Int) { }
    
        @ReactMethod
        public fun isBuzzBoosterNotification(data: ReadableMap, promise: Promise) {
            val readableMap: HashMap<String, Any> = data.toHashMap()
            val map = readableMap as Map<String, String>
            promise.resolve(BuzzBooster.isBuzzBoosterNotification(map))
        }
    
        @ReactMethod
        public fun handleNotification(data: ReadableMap) {
            val readableMap: HashMap<String, Any> = data.toHashMap()
            val map = readableMap as Map<String, String>
            BuzzBooster.handleNotification(map)
        }
    
        @ReactMethod
        public fun hasUnhandledNotificationClick(promise: Promise) {
            if (currentActivity != null) {
                promise.resolve(BuzzBooster.hasUnhandledNotificationClick(currentActivity!!))
            } else {
                promise.resolve(false)
            }
        }
    
        @ReactMethod
        public fun handleNotificationClick() {
            currentActivity?.let {
                BuzzBooster.handleNotification(it)
            }
        }
    
        @ReactMethod
        public fun postJavaScriptMessage(message: String) {
            currentActivity?.let {
                BuzzBoosterJavaScriptInterface(it).postMessage(message)
            }
        }
    }
    
    
    // BuzzBoosterPackage.kt
    package com.boostersample
    import com.facebook.react.ReactPackage
    import com.facebook.react.bridge.NativeModule
    import com.facebook.react.bridge.ReactApplicationContext
    import com.facebook.react.uimanager.ViewManager
    
    class BuzzBoosterPackage : ReactPackage {
        override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
            return listOf(BuzzBoosterModule(reactContext))
        }
    
        override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
            val list = mutableListOf<ViewManager<*, *>>()
            return list
        }
    }
    
    
  4. MainApplication 의 reactNativeHost의 getPacakge 함수 안에 BuzzBoosterPacakge 를 추가합니다.

    // MainApplication.kt
    ...
    override val reactNativeHost: ReactNativeHost =
    	object : DefaultReactNativeHost(this) {
    		override fun getPackages(): MutableList<ReactPackage> {
    			val packages = PackageList(this).packages
    			packages.add(BuzzBoosterPackage())
    			return packages
    		}
    		...
    	}
    }
    ...
    

iOS

  1. podfile 에 BuzzBooster를 추가합니다.

      pod 'BuzzBoosterSDK', '~> 4.23.3'
    
  2. RNBNotificationRenderer / RNBuzzBooster 를 추가합니다.

    // RNBNotificaionRenderer.h
    @import Foundation;
    @import UserNotifications;
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface RNBNotificationRenderer : NSObject
    
    + (void)renderWithUserInfo:(NSDictionary *)userInfo;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    
    // RNBNotificationRenderer.m
    #import "RNBNotificationRenderer.h"
    
    @implementation RNBNotificationRenderer
    + (void)renderWithUserInfo:(NSDictionary *)userInfo {
      UNNotificationContent *content = [self createNotificationContentWithUserInfo:userInfo];
      UNNotificationRequest *request = [self createNotificationRequestWithContent:content userInfo:userInfo];
    
      [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
        if (error != nil) { }
      }];
    }
    
    #pragma mark -private
    + (UNNotificationContent *)createNotificationContentWithUserInfo:(NSDictionary *)userInfo{
      UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
      content.title = userInfo[@"title"];
      content.body = userInfo[@"body"];
      content.userInfo = userInfo;
      if (@available(iOS 15.0, *)) {
        content.interruptionLevel = UNNotificationInterruptionLevelCritical;
      }
      return content;
    }
    
    + (UNNotificationRequest *)createNotificationRequestWithContent:(UNNotificationContent *)content
                                                           userInfo:(NSDictionary *)userInfo {
      NSString *requestId = userInfo[@"id"];
      return [UNNotificationRequest
              requestWithIdentifier:requestId
              content:content
              trigger:nil];
    }
    
    @end
    
    
    // RNBuzzBooster.h
    #import <React/RCTBridgeModule.h>
    #import <React/RCTEventEmitter.h>
    #import <UIKit/UIKit.h>
    #import <BuzzBoosterSDK/BuzzBoosterSDK.h>
    #import <UserNotifications/UserNotifications.h>
    
    @interface RNBuzzBooster : RCTEventEmitter <RCTBridgeModule, BSTOptInMarketingCampaignDelegate, BSTUserEventDelegate>
    
    + (void)userNotificationCenter:(UNUserNotificationCenter *)center
    didReceiveNotificationResponse:(UNNotificationResponse *)response
             withCompletionHandler:(void (^)(void))completionHandler;
    
    @end
    
    
    // RNBuzzBooster.m
    #import "RNBuzzBooster.h"
    #import "RNBNotificationRenderer.h"
    
    #ifdef RCT_NEW_ARCH_ENABLED
    #import "RNBuzzBoosterSpec.h"
    #endif
    
    @implementation RNBuzzBooster {
      BOOL hasListeners;
    }
    
    + (void)userNotificationCenter:(UNUserNotificationCenter *)center
    didReceiveNotificationResponse:(UNNotificationResponse *)response
             withCompletionHandler:(void (^)(void))completionHandler {
      [BuzzBooster userNotificationCenter:center
                               didReceive:response
                    withCompletionHandler:completionHandler];
    }
    // Will be called when this module's first listener is added.
    -(void)startObserving {
      hasListeners = YES;
    }
    
    // Will be called when this module's last listener is removed, or on dealloc.
    -(void)stopObserving {
      hasListeners = NO;
    }
    
    - (NSArray<NSString *> *)supportedEvents{
      return @[@"OptInMarketingCampaignMoveButtonClicked", @"onUserEventDidOccur"];
    }
    
    RCT_EXPORT_MODULE(BuzzBooster) //Specify Module name for using in JS
    
    - (dispatch_queue_t)methodQueue
    {
      return dispatch_get_main_queue();
    }
    
    RCT_EXPORT_METHOD(initIosApp:(NSString *)appKey) {
      BSTConfig *config = [BSTConfig configWithBlock:^(BSTConfigBuilder * _Nonnull builder) {
        builder.appKey = appKey;
      }];
      [BuzzBooster initializeWithConfig:config];
      [BuzzBooster setOptInMarketingCampaignDelegate:self];
      [BuzzBooster addUserEventDelegate:self];
    }
    
    RCT_EXPORT_METHOD(setPushToken:(NSString *)deviceToken) {
      [BuzzBooster setPushToken:deviceToken];
    }
    
    RCT_EXPORT_METHOD(isBuzzBoosterNotification:(NSDictionary *)userInfo
                      resolver:(RCTPromiseResolveBlock)resolve
                      rejecter:(RCTPromiseRejectBlock)reject) { // promise를 사용하려면 reject를 넣어줘야함
      if (userInfo[@"BuzzBooster"] != nil) {
        resolve(@YES);
      } else {
        resolve(@NO);
      }
    }
    
    RCT_EXPORT_METHOD(setUser:(nullable NSDictionary *)userDictionary) {
      if (userDictionary) {
        BSTUser *user = [BSTUser userWithBlock:^(BSTUserBuilder * _Nonnull builder) {
          builder.userId = userDictionary[@"userId"];
          builder.properties = userDictionary[@"properties"];
          NSNumber *_Nullable optInMarketing = userDictionary[@"optInMarketing"];
          if (optInMarketing == nil || [optInMarketing isKindOfClass:[NSNull class]]) {
            builder.marketingStatus = BSTMarketingStatusUndetermined;
          } else {
            if ([optInMarketing boolValue]) {
              builder.marketingStatus = BSTMarketingStatusOptIn;
            } else {
              builder.marketingStatus = BSTMarketingStatusOptOut;
            }
          }
        }];
        [BuzzBooster setUser:user];
      } else {
        [BuzzBooster setUser:nil];
      }
    }
    
    RCT_EXPORT_METHOD(showInAppMessage) {
      UIViewController *vc = [UIApplication sharedApplication].delegate.window.rootViewController;
      [BuzzBooster showInAppMessageWithViewController:vc];
    }
    
    RCT_EXPORT_METHOD(showHome) {
      UIViewController *vc = [UIApplication sharedApplication].delegate.window.rootViewController;
      [BuzzBooster showHomeWithViewController:vc];
    }
    
    RCT_EXPORT_METHOD(showNaverPayExchange) {
      UIViewController *vc = [UIApplication sharedApplication].delegate.window.rootViewController;
      [BuzzBooster showNaverPayExchangeWithViewController:vc];
    }
    
    RCT_EXPORT_METHOD(showCampaignWithId:(NSString *)campaignId) {
      UIViewController *viewController = [UIApplication sharedApplication].delegate.window.rootViewController;
      [BuzzBooster showCampaignWithId:campaignId viewController:viewController];
    }
    
    RCT_EXPORT_METHOD(showCampaignWithType:(NSString *)campaignType) {
      UIViewController *vc = [UIApplication sharedApplication].delegate.window.rootViewController;
      if ([campaignType isEqualToString:@"Attendance"]) {
        [BuzzBooster showCampaignWithType:BSTCampaignTypeAttendance viewController:vc];
      } else if ([campaignType isEqualToString:@"Referral"]) {
        [BuzzBooster showCampaignWithType:BSTCampaignTypeReferral viewController:vc];
      } else if ([campaignType isEqualToString:@"OptInMarketing"]) {
        [BuzzBooster showCampaignWithType:BSTCampaignTypeOptInMarketing viewController:vc];
      } else if ([campaignType isEqualToString:@"ScratchLottery"]) {
        [BuzzBooster showCampaignWithType:BSTCampaignTypeScratchLottery viewController:vc];
      } else if ([campaignType isEqualToString:@"Roulette"]) {
        [BuzzBooster showCampaignWithType:BSTCampaignTypeRoulette viewController:vc];
      } else {
        NSException *exception = [NSException exceptionWithName:@"Unknown Campaign Type"
                                                         reason:@""
                                                        userInfo:nil];
        @throw exception;
      }
    }
    
    RCT_EXPORT_METHOD(showPage:(NSString *)pageId) {
      [BuzzBooster showPageWithId:pageId];
    }
    
    RCT_EXPORT_METHOD(sendEvent:(NSString *)eventName eventValues:(nullable NSDictionary *)eventValues) {
      if (eventValues) {
        @try {
          [BuzzBooster sendEventWithName:eventName values:eventValues];  
        } @catch(id Exception) {
          NSLog(@"Cast is Failed, Input wrong format");
        }
      } else {
        [BuzzBooster sendEventWithName:eventName];
      }
    }
    
    RCT_EXPORT_METHOD(setTheme:(NSString *)theme) {
      if ([theme isEqualToString:@"Light"]) {
        [BuzzBooster setUserInterfaceStyle:BSTUserInterfaceStyleLight];
      } else if ([theme isEqualToString:@"Dark"]) {
        [BuzzBooster setUserInterfaceStyle:BSTUserInterfaceStyleDark];
      } else if ([theme isEqualToString:@"System"]) {
        [BuzzBooster setUserInterfaceStyle:BSTUserInterfaceStyleSystem];
      } else {
        NSException *exception = [NSException exceptionWithName:@"Unknown Theme"
                                                         reason:@""
                                                       userInfo:nil];
        @throw exception;
      }
    }
    
    RCT_EXPORT_METHOD(handleForegroundNotification:(NSDictionary *)userInfo) {
      [RNBNotificationRenderer renderWithUserInfo:userInfo];
    }
    
    RCT_EXPORT_METHOD(handleInitialNotification:(NSDictionary *)userInfo) {
      [BuzzBooster application:UIApplication.sharedApplication didReceiveRemoteNotification:userInfo fetchCompletionHandler:^(UIBackgroundFetchResult result) { }
      ];
    }
    
    RCT_EXPORT_METHOD(onNotificationOpenedApp:(NSDictionary *)userInfo) {
      [BuzzBooster application:UIApplication.sharedApplication didReceiveRemoteNotification:userInfo fetchCompletionHandler:^(UIBackgroundFetchResult result) { }
      ];
    }
    
    RCT_EXPORT_METHOD(postJavaScriptMessage:(NSString *)message) {
      NSError *error;
      UIViewController *viewController = [UIApplication sharedApplication].delegate.window.rootViewController;
      [BuzzBoosterWebKit handleWith:viewController
                        messageName:@"BuzzBooster"
                        messageBody:message
                              error:&error];
      if (error) {
        NSLog(@"%@", [error localizedDescription]);
      }  
    }
    
    #pragma mark --BSTOptInMarketingCampaignDelegate
    - (void)onMoveButtonTappedIn:(UIViewController *)viewController {
      // Dimiss using rootViewController not tapped in viewcontroller
      UIViewController *rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController;
      [rootViewController dismissViewControllerAnimated:NO completion:nil];
      if (hasListeners) {
        [self sendEventWithName:@"OptInMarketingCampaignMoveButtonClicked"
                           body:@{}];
      }
    }
    
    #pragma mark --BSTUserEventDelegate
    - (void)userEventDidOccur:(BSTUserEvent * _Nonnull)userEvent {
      if (hasListeners) {
          NSString * _Nonnull userEventName = userEvent.name;
          NSDictionary<NSString *, id> * _Nullable userEventValues = userEvent.values;
        
          // Prevent Crash
          if (userEventValues != nil && ![userEventValues isKindOfClass:[NSNull class]]){
            [self sendEventWithName:@"onUserEventDidOccur"
                            body:@{
                                    @"userEventName": userEventName,
                                    @"userEventValues": userEventValues
                                  }
            ];
          } else {
            [self sendEventWithName:@"onUserEventDidOccur"
                            body:@{
                                    @"userEventName": userEventName,
                                  }
            ];
          }
          
      }
    }
    
    // Don't compile this code when we build for the old architecture.
    #ifdef RCT_NEW_ARCH_ENABLED
    - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
        (const facebook::react::ObjCTurboModule::InitParams &)params
    {
        return std::make_shared<facebook::react::NativeBuzzBoosterSpecJSI>(params);
    }
    #endif
    
    @end
    
    

ReactNative

  1. BuzzBooster 모듈 사용을 위한 파일들을 추가합니다.
    1. BuzzBoosterCampaignType.tsx

      // BuzzBoosterCampaignType.tsx
      export enum BuzzBoosterCampaignType {
          Attendance = "Attendance",
          Referral = "Referral",
          OptInMarketing = "OptInMarketing",
          ScratchLottery = "ScratchLottery",
          Roulette = "Roulette"
      };
      
    2. BuzzBoosterReact.tsx

      //BuzzBoosterReact.tsx
      
      import { NativeModules, Platform, NativeEventEmitter, EmitterSubscription } from 'react-native';
      import { LogBox } from 'react-native';
      import type { BuzzBoosterUser } from './BuzzBoosterUser';
      import type { BuzzBoosterCampaignType } from './BuzzBoosterCampaignType';
      import type { BuzzBoosterTheme } from './BuzzBoosterTheme';
      
      LogBox.ignoreLogs(['new NativeEventEmitter']);
      
      const LINKING_ERROR =
        `The package 'react-native-buzz-booster' doesn't seem to be linked. Make sure: \\n\\n` +
        Platform.select({ ios: "- You have run 'pod install'\\n", default: '' }) +
        '- You rebuilt the app after installing the package\\n' +
        '- You are not using Expo managed workflow\\n';
      const BuzzBooster = NativeModules.BuzzBooster ? NativeModules.BuzzBooster : new Proxy(
        {},
        {
          get() { throw new Error(LINKING_ERROR); },
        }
      );
      
      const myModuleEvt = new NativeEventEmitter(BuzzBooster)
      
      interface AppKey {
        androidAppKey: string
        iosAppKey: string
      }
      
      export function init({ androidAppKey, iosAppKey }: AppKey) {
        console.log(NativeModules)
        console.log(BuzzBooster)
        if (Platform.OS === 'android') {
          BuzzBooster.initAndroidApp(androidAppKey)
        } else if (Platform.OS === 'ios') {
          BuzzBooster.initIosApp(iosAppKey)
        } else {
          throw new Error("unsupported platform");
        }
      }
      
      export function setUser(user: BuzzBoosterUser | null) {
        if (user != null) {
          let userObject = {
            "userId": user.userId,
            "optInMarketing": user.optInMarketing,
            "properties": user.properties,
          }
          BuzzBooster.setUser(userObject)
        } else {
          BuzzBooster.setUser(null)
        }
      }
      
      export function setPushToken(pushToken: String) {
        BuzzBooster.setPushToken(pushToken)
      }
      
      export function addUserEventChannel(listener: (eventName: string, eventValues: Object | undefined) => void): EmitterSubscription {
        return myModuleEvt.addListener('onUserEventDidOccur', (data) => listener(data['userEventName'], data['userEventValues']))
      }
      
      export function addOptInMarketingCampaignMoveButtonClickListener(listener: () => void): EmitterSubscription {
        return myModuleEvt.addListener('OptInMarketingCampaignMoveButtonClicked', (_) => listener())
      }
      
      export function sendEvent(eventName: string, eventValues?: Map<string, string | number | boolean> | null) {
        if (eventValues == null || typeof eventValues == 'undefined') {
          BuzzBooster.sendEvent(eventName, null)
        } else {
          BuzzBooster.sendEvent(eventName, eventValues)
        }
      }
      
      export function showInAppMessage() {
        BuzzBooster.showInAppMessage()
      }
      
      export function showHome() {
        BuzzBooster.showHome()
      }
      
      export function showNaverPayExchange() {
        BuzzBooster.showNaverPayExchange()
      }
      
      export function showCampaignWithId(campaignId: string) {
        BuzzBooster.showCampaignWithId(campaignId)
      }
      
      export function showPage(pageId: string) {
        BuzzBooster.showPage(pageId)
      }
      
      export function setTheme(theme: BuzzBoosterTheme) {
        let themeString = theme.valueOf()
        // BuzzBooster.setTheme(themeString)
      }
      
      export function showCampaignWithType(campaignType: BuzzBoosterCampaignType) {
        let campaignTypeString = campaignType.valueOf()
        BuzzBooster.showCampaignWithType(campaignTypeString)
      }
      
      export function isBuzzBoosterNotification(data: { [key: string]: string } | undefined): Boolean {
        if (data != undefined && data['BuzzBooster'] != undefined) {
          return true
        }
        return false
      }
      
      export function handleForegroundNotification(data: { [key: string]: string } | undefined) {
        if (Platform.OS === 'android') {
          handleNotification(data) // android use sample handler
        } else if (Platform.OS === 'ios') {
          BuzzBooster.handleForegroundNotification(data)
        }
      }
      
      export function handleInitialNotification(data: { [key: string]: string } | undefined) {
        if (Platform.OS === 'ios') {
          BuzzBooster.handleInitialNotification(data)
        } else {
          BuzzBooster.hasUnhandledNotificationClick()
            .then((exists) => {
              if (exists) {
                handleNotificationClick()
              }
            })
        }
      }
      
      export function postJavaScriptMessage(message: string) {
        BuzzBooster.postJavaScriptMessage(message)
      }
      
      // Only For iOS
      export function onNotificationOpenedApp(data: { [key: string]: string } | undefined) {
        if (Platform.OS === 'ios') {
          BuzzBooster.onNotificationOpenedApp(data)
        }
      }
      
      function handleNotificationClick() {
        if (Platform.OS === 'android') {
          BuzzBooster.handleNotificationClick()
        }
      }
      
      function handleNotification(data: { [key: string]: string } | undefined) {
        if (Platform.OS === 'android') {
          BuzzBooster.handleNotification(data)
        }
      }
      
      // 객체로 내보내기
      export const BuzzBoosterReact = {
        init,
        setUser,
        setPushToken,
        addUserEventChannel,
        addOptInMarketingCampaignMoveButtonClickListener,
        sendEvent,
        showInAppMessage,
        showHome,
        showNaverPayExchange,
        showCampaignWithId,
        showPage,
        setTheme,
        showCampaignWithType,
        isBuzzBoosterNotification,
        handleForegroundNotification,
        handleInitialNotification,
        postJavaScriptMessage,
        onNotificationOpenedApp,
      };
      
      
    3. BuzzBoosterTheme.tsx

      export enum BuzzBoosterTheme {
          dark = "Dark",
          light = "Light",
          system = "System",
      };
      
      
    4. BuzzBoosterUser.tsx

      export class BuzzBoosterUser {
          userId!: string
          optInMarketing!: boolean | null
          properties!: Map<string, string | boolean | number>
          
          constructor(builder: BuzzBoosterUserBuilder){
            this.userId = builder.userId
            this.optInMarketing = builder.optInMarketing
            this.properties = builder.properties
          }
      }
      
      export class BuzzBoosterUserBuilder {
          userId!: string
          optInMarketing!: boolean | null
          properties!: Map<string, string | boolean | number >
        
          constructor(userId: string) {
            this.userId = userId
            this.optInMarketing = null
            this.properties = new Map()
          }
          
          setOptInMarketing(optInMarketing: boolean): BuzzBoosterUserBuilder {
            this.optInMarketing = optInMarketing
            return this
          }
        
          addProperty(key: string, value: string | boolean | number): BuzzBoosterUserBuilder {
            this.properties[key] = value
            return this
          }
        
          build(): BuzzBoosterUser {
            return new BuzzBoosterUser(this)
          }
        }
      
      

기존 BuzzBooster ReactNative 모듈을 사용중인 경우

샘플 코드

https://github.com/Buzzvil/buzz-sdk-samples/tree/master/buzzbooster-react-native-nativemodules