밝을희 클태

[react native / 리액트 네이티브] react-native-push-notification IOS, Android 푸시 알람 설치하기 본문

마모리(My Memory) 프로젝트

[react native / 리액트 네이티브] react-native-push-notification IOS, Android 푸시 알람 설치하기

huipark 2023. 9. 22. 00:49

푸시 알람을 보내기 위해선 IOS, Android 둘다 푸시 알람에 대한 권한을 받아야 해서 react-native-permissions 라이브러리도 함께 설치해야 한다.

https://gaebarsaebal.tistory.com/21

 

[react native / 리액트 네이티브]react-native-permissions 설치 방법

https://github.com/zoontek/react-native-permissions#supported-permissions GitHub - zoontek/react-native-permissions: An unified permissions API for React Native on iOS, Android and Windows. An unified permissions API for React Native on iOS, Android and Wi

gaebarsaebal.tistory.com

 

react native를 사용해서 ios와 android의 푸시 알람을 보내는 방식에는 두 가지 방식이 있다.

로컬 푸쉬 알람

  • 방식
    • 로컬 푸쉬 알람은 사용자의 디바이스에서 직접 스케쥴링하고 발송하는 방식입니다. 앱이 로컬에서 알람을 스케줄링하고, 설정한 시간에 도달하면 디바이스가 사용자에게 알람을 보냅니다.
  • 장점
    • 인터넷 연결이 없어도 알람이 도달합니다.
    • 외부 서버와의 통신이 필요 없어 구현이 상대적으로 간단합니다.
  • 단점
    • 사용자의 디바이스 상태(배터리 상태, 시간 변경 등)에 따라 알람의 정확도가 달라질 수 있습니다.
    • 디바이스에서 직접 관리하기 때문에 대규모 사용자를 대상으로 한 일괄적인 알람 발송이 어렵습니다.

FCM 원격 알람(Firebase Cloud Messaging)

  • 방식
    • FCM을 이용한 원격 푸쉬 알람은 Google의 Firebase Cloud Messaging 서비스를 사용하여 알람을 전송하는 방식입니다. 앱 서버가 FCM 서버에 알람을 요청하면, FCM 서버가 사용자의 디바이스에 알람을 전송합니다.
  • 장점
    • 사용자의 디바이스 상태에 영향을 받지 않고, 정확한 시간에 알람을 전송할 수 있습니다.
    • 한 번의 요청으로 대규모 사용자에게 알람을 전송할 수 있습니다.
    • 사용자의 디바이스와 상호작용하지 않고, 서버에서 모든 관리를 할 수 있습니다.
    • 사용자 세그먼테이션, 알람 트래킹 등 다양한 기능을 사용할 수 있습니다.
  • 단점
    • 인터넷 연결이 끊어진 경우 알람이 도달하지 않을 수 있습니다.
    • FCM 서비스의 설정과 서버 구축이 필요하여 구현이 복잡할 수 있습니다.

 

 

나는 저장해 놓은 메모를 사용자가 원할 때 푸시 알람을 보낼 거 기 때문에 FCM까지는 필요 없고 로컬 푸시 알람으로 세팅을 했다.

 

 


라이브러리 설치

$ npm install --save react-native-push-notification
$ npm i @react-native-community/push-notification-ios --save

 

 

IOS 설치

https://github.com/react-native-push-notification/ios

 

GitHub - react-native-push-notification/ios: React Native Push Notification API for iOS.

React Native Push Notification API for iOS. Contribute to react-native-push-notification/ios development by creating an account on GitHub.

github.com

 

 

 

react native 0.60+

$ cd ios && pod install

 

 

 

프로젝트의 xcode를 열고 프로젝트의 Signing & Capabilities 에서 아래 두 가지를 추가

 ✴︎ 유료 개발자 계정에서만 가능

  • Background Mode capability and tick Remote Notifications.
  • Push Notifications capability

 

 

AppDelegate.h 파일 수정

#import <UserNotifications/UNUserNotificationCenter.h>
@interface AppDelegate : RCTAppDelegate //코드를 아래로 변경
@interface AppDelegate : RCTAppDelegate <UNUserNotificationCenterDelegate>

 

 

 

 

AppDelegate.m 파일 수정

#import <UserNotifications/UserNotifications.h>
#import <RNCPushNotificationIOS.h>

 

 

 

 

@implementation AppDelegate 밑에 아래의 코드를 추가

// Required for the register event.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
 [RNCPushNotificationIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
// Required for the notification event. You must call the completion handler after handling the remote notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
  [RNCPushNotificationIOS didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
// Required for the registrationError event.
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
 [RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error];
}
// Required for localNotification event
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
         withCompletionHandler:(void (^)(void))completionHandler
{
  [RNCPushNotificationIOS didReceiveNotificationResponse:response];
}

 

 

 

나머지 코드도 원래 정의돼 있던 코드는 두고 아래처럼 추가

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  ...
  // Define UNUserNotificationCenter
  UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
  center.delegate = self;

  return YES;
}

//Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
  completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
}

 

안드로이드 설치

https://github.com/zo0r/react-native-push-notification

 

GitHub - zo0r/react-native-push-notification: React Native Local and Remote Notifications

React Native Local and Remote Notifications. Contribute to zo0r/react-native-push-notification development by creating an account on GitHub.

github.com

 

 

 

나는 firebase/messaging은 사용하지 않기 때문에 하진 않았지만 만약 firebase/messaging으로 원격 푸시 알람을 사용할 거라면 아래처럼 해야 한다.

 

 

android/build.gradle

ext {
    googlePlayServicesVersion = "<Your play services version>" // default: "+"
    firebaseMessagingVersion = "<Your Firebase version>" // default: "21.1.0"

    // Other settings
    compileSdkVersion = <Your compile SDK version> // default: 23
    buildToolsVersion = "<Your build tools version>" // default: "23.0.1"
    targetSdkVersion = <Your target SDK version> // default: 23
    supportLibVersion = "<Your support lib version>" // default: 23.1.1
}

 

 

예약 푸시 알람기능을 사용 할 거라면 아래와 같이 해야 한다

 

android/app/src/main/AndroidManifest.xml

여기서 공식 문서대로 했는데 안 돼서 한참 헤맸는데 Android 12 (API 레벨 31)부터는 android:exported 속성이 의도적으로 명시되어야 한다.

애플리케이션이 Android 12 이상을 대상으로 할 때 AndroidManifest.xml 파일에 intent filter가 정의된 component에 대해 android:exported 속성을 명시적으로 지정해야 합니다.

    .....
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

    <application ....>
        <!-- Change the value to true to enable pop-up for in foreground on receiving remote notifications (for prevent duplicating while showing local notifications set this to false) -->
        <meta-data  android:name="com.dieam.reactnativepushnotification.notification_foreground"
                    android:value="false"/>
        <!-- Change the resource name to your App's accent color - or any other color you want -->
        <meta-data  android:name="com.dieam.reactnativepushnotification.notification_color"
                    android:resource="@color/white"/> <!-- or @android:color/{name} to use a standard color -->

        <receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationActions" />
        <receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationPublisher" />
        <!-- 아래처럼 <intent-filter> 가 정의된 컴포넌트는 android:exported 를 반드시 명시해 줘야한다 -->
        <receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationBootEventReceiver" android:exported="false">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="android.intent.action.QUICKBOOT_POWERON" />
                <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
            </intent-filter>
        </receiver>

        <service
            android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationListenerService"
            android:exported="false" >
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>
     .....

 

공식 문서에는 없지만 안드로이드 12 이상이라면 이 코드도 포함시켜 주어야 한다

<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>

 

 

android/app/src/main/res/values/colors.xml 가 없으면 파일을 만들어줘야 한다.

<resources>
    <color name="white">#FFF</color>
</resources>

 

 

❋MainActivity.java에 onNewIntent에 대한 @Override가 있는 경우 해당 함수에 onNewIntent에 대한 슈퍼 호출이 포함되어 있는지 확인하고 onNewIntent에 대한 @Override가 있는 경우에만 아래와 같이 작성한다.

    @Override
    public void onNewIntent(Intent intent) {
        ...
        super.onNewIntent(intent);
        ...
    }

 

 

 

 

❋원격 알림을 사용할 거라면 아래처럼 설정해야 하고 나는 로컬 알림만 쓸 거라서 설정을 하지 않았다.

 

android/build.gradle

buildscript {
    ...
    dependencies {
        ...
        classpath('com.google.gms:google-services:4.3.3')
        ...
    }
}

 

android/app/build.gradle

dependencies {
  ...
  implementation 'com.google.firebase:firebase-analytics:17.3.0'
  ...
}

apply plugin: 'com.google.gms.google-services'