# \[React Native]プッシュ通知を受信する

{% hint style="warning" %}
**iOSで画像などを添付したプッシュ通知に対応する場合**

画像や動画などを添付したリッチプッシュ通知に対応するにはExtensionの作成が必要です。\
詳しくは [リッチプッシュ通知に対応する](/ios-sdk-appendix/appendix-rich-notification-ios-sdk.md) をご覧ください。
{% endhint %}

## 前提条件

事前に、 `@react-native-karte/core` パッケージの導入を行う必要があります。

* 参考：[SDKを導入する](/react-native-sdk/setup-react-native-sdk.md)、[SDKを導入する (Expo)](/react-native-sdk/setup-react-native-sdk-expo.md)

KARTE ではプッシュ通知の送信に、Firebase Cloud Messaging（以下FCM）を利用しています。\
そのためFCM経由でプッシュ通知を送信するための各種設定を行う必要があります。

また受信側のアプリケーションでもFirebaseライブラリの導入などの対応が必要となります。

なお本ドキュメントでは、[React Native Firebase](https://rnfirebase.io/) を利用する前提で説明します。\
これ以外のライブラリを利用する場合は、読み替えた上で導入を行ってください。

## 導入手順

### STEP1: React Native Firebase を導入する

1. SDKを導入する\
   導入に関しては、下記ドキュメントをご覧ください。

* [React Native Firebase | React Native Firebase](https://rnfirebase.io/)
* [Cloud Messaging | React Native Firebase](https://rnfirebase.io/messaging/usage)

2. Notification Composer で通知のテストを行う\
   Firebase の Notification Composer から通知メッセージを送信し、メッセージが受信できるか確認してください。\
   [Send a notification message](https://firebase.google.com/docs/cloud-messaging/ios/first-message#send_a_notification_message)

### STEP2: サービスアカウントの設定を行う

KARTEからFCMに対して通知の送信リクエストを行うために、KARTE側にサービスアカウントの設定を行う必要があります。\
[サービスアカウントを設定する](/app-send-notification/app-setup-service-account.md)

### STEP3: React Native KARTE Notification を導入する

#### 共通

npm または yarn を利用して `@react-native-karte/notification` パッケージをインストールしてください。

{% tabs %}
{% tab title="npm" %}
{% code overflow="wrap" %}

```shell
npm install --save @react-native-karte/notification
```

{% endcode %}
{% endtab %}

{% tab title="yarn" %}
{% code overflow="wrap" %}

```shell
yarn add @react-native-karte/notification
```

{% endcode %}
{% endtab %}
{% endtabs %}

パッケージのインストールが完了したら、対応するプラットフォーム毎の導入手順に従い設定を進めてください。

#### iOS

Pod をインストールしてください。

{% code overflow="wrap" %}

```shell
npx pod-install ios
```

{% endcode %}

#### Android

導入にあたり必要な手順はありません。

### STEP4: FCMトークンを送信する

KARTE からプッシュ通知を送信するためには、FCMトークンが必要となります。\
そのためアプリケーションからKARTEにFCMトークンを送信する処理を実装します。

{% code title="App.tsx" overflow="wrap" %}

```typescript
import { Notification } from '@react-native-karte/notification';

export default function App() {
  React.useEffect(() => {
    messaging()
      .getToken()
      .then((fcmToken) => {
        // 取得したトークンをKARTEに送信
        Notification.registerFCMToken(fcmToken);
      })
      .catch((e) => {
        console.error(e);
      });

    messaging().onTokenRefresh((fcmToken) => {
      // 更新されたトークンをKARTEに送信
      Notification.registerFCMToken(fcmToken);
    });
  });

  // ...
}
```

{% endcode %}

### STEP5: プラットフォーム毎の実装

#### iOSの場合

受信したプッシュ通知をタップ（開封）した際、通知メッセージに含まれているリンクを開くためには下記の実装が必要となります。\
※iOSでは`setBackgroundMessageHandler`がトリガーされないため、アプリ未起動時(quit状態)では下記形式の実装が必要です\
<https://rnfirebase.io/messaging/usage#ios-background-limitation>

{% code title="App.tsx" overflow="wrap" %}

```typescript
import { Notification } from '@react-native-karte/notification';

export default function App() {
  React.useEffect(() => {
    // アプリ未起動状態から通知が開かれた際の処理
    messaging()
      .getInitialNotification()
      .then((remoteMessage) => {
        if (remoteMessage) {
          const notification = Notification.create(remoteMessage);
          if (notification) {
            notification.handle();
          }
        }
      });

    // アプリ起動状態から通知が開かれた際の処理
    messaging().onNotificationOpenedApp((remoteMessage) => {
      if (remoteMessage) {
        const notification = Notification.create(remoteMessage);
        if (notification) {
          notification.handle();
        }
      }
    });
  });

  // ...
}
```

{% endcode %}

**foreground時に受信した際に通知が表示されない場合**

RNFBMessagingライブラリの実装・仕様の影響で、アプリがforegroundの際にKARTEの通知が自動で表示されないケースがあります。\
その際はAndroid同様、`onMessage` コールバックをハンドルし、ローカル通知を表示する必要があります。

{% code title="App.tsx" overflow="wrap" %}

```typescript
import { Notification } from '@react-native-karte/notification';

export default function App() {
  React.useEffect(() => {
    messaging().onMessage((remoteMessage) => {
      if (remoteMessage) {
        const notification = Notification.create(remoteMessage);
        if (notification) {
          // ここでローカル通知を用いた表示を行います。
        }
      }
    });
  });

  // ...
}
```

{% endcode %}

**受信時のリンク遷移を制御したい場合**

Universal Links等への対応でリンク遷移を制御したい場合には、独自にハンドリング処理を記述する必要があります。\
※`notification.hundle()`を呼び出す場合、内部的にUIApplication.openURL()を呼び出す形式となり、ブラウザに遷移します

{% code title="App.tsx" overflow="wrap" %}

```typescript
import { Notification } from '@react-native-karte/notification';

export default function App() {
  React.useEffect(() => {
    // アプリ未起動状態から通知が開かれた際の処理
    messaging()
      .getInitialNotification()
      .then((remoteMessage) => {
        if (remoteMessage) {
          const notification = Notification.create(remoteMessage);
          if (notification) {
            if (notification.url?.startsWith('https://example.com')) {
              // 対応する画面を開く処理を書く
            } else {
              notification.handle();
            }
          }
        }
      });

    // アプリ起動状態から通知が開かれた際の処理
    messaging().onNotificationOpenedApp((remoteMessage) => {
      if (remoteMessage) {
        const notification = Notification.create(remoteMessage);
        if (notification) {
          if (notification.url?.startsWith('https://example.com')) {
            // 対応する画面を開く処理を書く
          } else {
            notification.handle();
          }
        }
      }
    });
  });

  // ...
}
```

{% endcode %}

#### Androidの場合

KARTEから送信されるメッセージはデータメッセージとして送信されます。\
データメッセージのため、アプリの状態（foreground / background）によって実装する処理が異なります。\
※quit状態もbackgroundと同様の`setBackgroundMessageHandler`のハンドラで検知可能です。\
<https://rnfirebase.io/messaging/usage#message-handlers>

**foreground時に受信する場合の実装**

{% code title="App.tsx" overflow="wrap" %}

```typescript
import { Notification } from '@react-native-karte/notification';

export default function App() {
  React.useEffect(() => {
    messaging().onMessage((remoteMessage) => {
      if (remoteMessage) {
        const notification = Notification.create(remoteMessage);
        if (notification) {
          notification.show();
        }
      }
    });
  });

  // ...
}
```

{% endcode %}

**background時に受信する場合の実装**

実装上の注意事項等については、[React Native Firebaseのドキュメント](https://rnfirebase.io/messaging/usage#background--quit-state-messages) もご確認ください。

{% code title="index.js" overflow="wrap" %}

```typescript
import { Notification } from '@react-native-karte/notification';

messaging().setBackgroundMessageHandler(async (remoteMessage) => {
  const notification = Notification.create(remoteMessage);
  if (notification) {
    notification.show();
  }
});
```

{% endcode %}

## 動作確認

最後に正しく導入が行われているか確認を行うためにテストメッセージを送信して確認を行います。

詳細については、下記ドキュメントをご覧ください。\
[テストメッセージを送信する](/app-send-notification/app-test-notification.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://app.developers.karte.io/react-native-sdk/notification-react-native-sdk.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
