React Native推送通知:完整的操作指南

發表於2024-02-25
首發於公眾號 前端混合開發,歡迎關注。

推送通知已成為構建移動應用時需要考慮的重要功能。由於它們類似於簡訊,但傳送不需要任何費用,許多企業現在更喜歡使用推送通知嚮應用使用者傳送資訊和警報。

在這篇文章中,我們將看到如何在React Native應用中建立和傳送推送通知。

什麼是推送通知?

推送通知是從應用程式傳送到已安裝該應用的使用者的訊息或警報。主要有兩種型別的通知:

  • 前臺通知:當應用程式正在開啟並執行時傳送給使用者的通知
  • 後臺通知:無論應用程式是否當前開啟,都會傳送

推送通知在移動應用開發世界中非常流行,原因有很多。例如:

  • 使公司能夠以較低的成本推廣產品和優惠
  • 提升整體使用者體驗
  • 可以更快地提供交易收據
  • 轉化更多使用者
  • 可靠的,因為使用者在開啟手機時總是會收到離線訊息

這些優勢使得推送通知對幾乎所有型別的移動應用都非常有用,從手機遊戲到電商應用等等。

React Native 中的推送通知架構

在我們深入瞭解如何在 React Native 應用中實現推送通知的技術細節之前,理解React Native推送通知的工作原理可能會有所幫助。這裡有一個圖表,簡化了通知服務如何與裝置進行通訊:

image.png

當涉及到在React Native中設定推送通知時,有幾種設定方式:

  • 原生平臺特定的通知服務(FCM/APNS
  • Expo推送通知服務和其他雲服務
  • 像Notifee這樣的React Native庫

下面我們更深入地瞭解這些方法,然後深入我們的演示。

原生平臺特定的通知服務(FCM/APNs)

Android和iOS平臺都提供了用於接收推送通知的原生平臺特定API

  • 適用於安卓裝置的Firebase雲訊息傳遞(FCM)
  • 蘋果推送通知服務(APNs)適用於iOS裝置

我們可以使用React Native Firebase庫來在Android上整合FCM,使用 push-notification-ios 庫來在iOS上整合APNs。

React Native Firebase 庫也提供了一種透過 FCM 在iOS上傳送推送通知的方法。可以從Node.js伺服器透過 firebase-adminnode-apn 向註冊的移動裝置傳送遠端通知

Expo推送通知和其他雲服務

FCMAPNs 都是特定平臺的原生推送通知服務。如果我們直接使用這些原生推送通知服務,我們通常需要在應用的前端和後端使用不同的庫。

由於這可能會帶來不便,因此有幾個雲服務提供了使用統一原始碼同時處理FCM和APNs的方法。一些流行的推送通知服務包括:

這些通知服務在原生推送通知系統之上提供了一個抽象層,透過一個託管的中間推送通知伺服器,正如你在之前顯示的圖表中看到的那樣。

其他的React Native庫,比如react-native-push-notification

Notifeereact-native-notifications 這樣的庫提供了原生模組,可以透過統一的庫API輕鬆接收遠端通知並顯示本地通知。

你可以直接使用 FCM/APNs 或者使用這些庫的託管推送通知服務。然而,請記住,我們必須在 Expo 中使用裸工作流來使用這些庫,因為這些庫不包含在 Expo 應用程式中。

演示:如何在 React Native 中設定推送通知

要在React Native應用程式中使用推送通知,我們首先需要註冊應用程式以獲取推送通知令牌。這個令牌是一個長字串,可以唯一標識每個裝置。然後,我們將在伺服器上的資料庫中儲存該令牌,傳送通知,並處理我們傳送的已接收到的通知。

在我們深入研究之前,我們將向一個已經開發的專案新增推送通知。這個專案是一個用於出售二手物品的電子商務React Native應用程式。使用現有的專案將使我們能夠專注於我們演示的推送通知方面。

要將專案的原始碼下載到你的電腦中,請在你的終端執行以下命令:

git clone https://github.com/codezri/Done-With-It-App.git

接下來,我們將安裝專案所需的依賴項,並啟動React Native開發伺服器:

yarn install 
yarn start 

上述命令安裝依賴項並啟動Expo開發伺服器,因此你可以透過在Android或iOS上使用Expo應用來測試你的應用程式。帶有工作後端的示例應用如下所示:

image.png

接下來,我們將從React Native Expo獲取推送通知令牌,以開始接收應用程式的通知。

獲取推送通知令牌

記住,要在React Native應用程式中使用推送通知,我們首先需要註冊應用程式以獲取推送通知令牌。在這裡,我們將使用Expo中的通知API。

為了做到這一點,讓我們進入 navigation 目錄和 AppNavigator 元件。在這裡,我們將從Expo中獲取一個令牌。讓我們從下面的Expo獲取 Notifications 函式:

import * as Notifications from 'expo-notifications';

上述功能幫助我們請求使用者許可權以傳送推送通知,併為特定裝置接收一個獨特的 Expo 通知令牌。

現在,我們將在 AppNavigator 元件中編寫一個 async function ,它將從 React Native Expo 請求一個令牌:

async function registerForPushNotificationsAsync() {
    let token;

    const { status: existingStatus } = await Notifications.getPermissionsAsync();
    let finalStatus = existingStatus;

    if (existingStatus !== 'granted') {
        const { status } = await Notifications.requestPermissionsAsync();
        finalStatus = status;
    }
    if (finalStatus !== 'granted') {
        alert('Failed to get push token for push notification!');
        return;
    }
    token = (await Notifications.getExpoPushTokenAsync()).data;
    console.log(token);

    return token;
}

在上述程式碼中,我們使用 expo-notifications 模組來獲取使用者接收通知的許可權。該函式等待接收通知許可權 status

接下來,我們檢查是否已授予許可權。如果沒有,我們會顯示一個關於錯誤的警告,並立即從函式中 return 。如果令牌請求過程成功,我們將從函式中返回令牌。否則,目前,我們將Expo的 token 記錄到控制檯,以便於開發。

為了在我們的應用中呼叫上述函式,我們將使用來自React的 useEffect 鉤子:

const AppNavigator = () => {
    useEffect(() => {
        registerForPushNotificationsAsync();
    }, []);

在上述程式碼中,我們傳遞了從 React 匯入的 useEffect Hook,並傳遞了一個名為 registerForPushNotificationsAsync 的函式,以確保它只被呼叫一次。

現在,透過Expo應用程式開啟應用。一旦你開啟應用,你可以在控制檯上看到Expo推送通知令牌。

當新使用者開啟應用時,這個獨特的令牌將會被生成,所以我們可以在伺服器中儲存這些令牌,並以程式設計方式向所有註冊的裝置傳送通知。將令牌儲存在某處——我們很快就會用它來測試通知。

傳送測試通知

我們可以透過新增推送通知令牌,使用Expo通知工具向裝置傳送測試通知。進入Expo通知工具,輸入你的令牌,輸入標題和描述,保持你的應用在後臺,然後點選傳送通知按鈕來傳送測試通知。

現在你可以在你的裝置上看到通知,如下預覽所示:

image.png

如果你需要在應用處於前臺時顯示通知,你可以在 AppNavigator.js 原始檔中新增以下配置:

Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true
  }),
});

const AppNavigator = () => {
// ----
// ----

既然我們已經手動測試了Expo通知,那麼讓我們在伺服器中儲存推送通知令牌,並以程式設計方式傳送通知。

在專案中儲存推送通知令牌

為了儲存和使用我們伺服器的推送通知,我們需要以一種可以註冊新使用者和裝置的方式配置我們的應用程式使用者介面。

為了實現這個,讓我們進入我們專案的 api 目錄並開啟一個我們將命名為 expoPushTokens.js 的新檔案。然後按照以下步驟操作:

import client from './client';
const register = (pushToken) => client.post('/expoPushTokens', { token: pushToken });
export default {
    register,
}

在上述程式碼中,我們首先匯入了客戶端模組,該模組也在 api 目錄中。

我們定義了一個函式 register ,它接受一個 pushToken

現在,我們將在後端的 /expoPushToken 上釋出一個客戶端或新使用者到 url 。在請求的主體中,我們將新增一個設定為 pushToken 的物件 token 。然後,我們將以 register 方法匯出為預設物件。

接下來,我們回到 AppNavigator 元件。我們將不再在控制檯上記錄我們的令牌,而是將其傳送到伺服器:

const AppNavigator = () => {

    useEffect(() => {
        registerForPushNotificationsAsync()
            .then(token => expoPushTokensApi.register(token));
    }, []);

現在,我們正在將新使用者傳送去獲取令牌,同時也將使用者資訊傳送到我們的後端伺服器。稍後,我們可以使用這些令牌向所有註冊的裝置傳送通知。

在伺服器上傳送通知

要向伺服器傳送推送通知,我們需要使用Expo提供的一個SDK。如果你訪問Expo的文件,你會找到關於如何在許多語言中實現伺服器上的推送通知的資訊。

在這個教程中,我將使用一個Node.js伺服器。你可以檢視這個GitHub倉庫,這是我在這個教程中使用的伺服器原始碼。我們將訪問伺服器中的 utilities 目錄,並在其中包含 Expo SDK。要做到這一點,我們首先需要做以下操作:

# # cd into the newly cloned Git repository.
git clone https://github.com/iamfortune/DoneWithIt-Backend.git

# Next we install the npm packages using this command:
npm install 

接下來,將你的計算機的本地網路IP地址新增到React Native應用的 baseURL 和後端專案的 assetsBaseUrl 中。

然後我們用以下命令啟動我們的開發伺服器:

npm start 

如果你將電腦和移動裝置保持在同一網路中,你可以在React Native應用中看到一些預先包含的列表。

現在,前往後端專案中的 utilities/pushNotifications.js 檔案。在那裡,將 Expo SDK新增到包中:

npm i expo-server-sdk #install the package

//file name: utilities/pushNotifications.js
const { Expo } = require("expo-server-sdk");

接下來,我們將編寫一個函式,該函式將接收我們的推送通知——既包括推送令牌,也包括我們想要傳送給使用者的訊息。然後,我們將建立一個新的塊方法來處理推送通知:

const sendPushNotification = async (targetExpoPushToken, message) => {
  const expo = new Expo();
  const chunks = expo.chunkPushNotifications([
    { to: targetExpoPushToken, sound: "default", body: message }
  ]);

現在,可以在伺服器程式碼的任何地方呼叫 sendPushNotification 函式,根據 Expo 推送通知令牌向任何裝置傳送通知,如下所示:

const { Expo } = require('expo-server-sdk');
const sendPushNotification = require('../utilities/pushNotifications');
// ----
// ----
if (Expo.isExpoPushToken(expoPushToken)) {
  await sendPushNotification(expoPushToken, message);
}
// ----

你可以在 routes/messages.js 檔案中檢視 sendPushNotification 函式的示例用法。接下來,讓我們確定如何處理在React Native應用中收到的通知。

在 React Native 中處理接收到的通知

要處理接收到的通知,我們首先需要有一個事件監聽器,每當使用者點選通知時都會被呼叫。讓我們在 AppNavigator 函式內部新增一個事件監聽器,它接收 Notifications 物件:

const AppNavigator = () => {

    const responseListener = useRef();

    useEffect(() => {
        registerForPushNotificationsAsync()
            .then(token => expoPushTokensApi.register(token));

        // Works when app is foregrounded, backgrounded, or killed
        responseListener.current = Notifications.addNotificationResponseReceivedListener(response => {
            console.log('--- notification tapped ---');
            console.log(response);
            console.log('------');
        });

        // Unsubscribe from events
        return () => {
            Notifications.removeNotificationSubscription(responseListener.current);
        };
    }, []);
// ----
// ----

你可以透過Expo推送通知工具傳送測試通知,並點選收到的通知。一旦這樣做,將在控制檯上看到通知點選響應。

Expo notifications 包提供了一個監聽器,如果應用程式在前臺,它可以檢測到接收到的通知事件。以下程式碼片段會在你的前臺應用透過Expo推送通知系統接收到通知時,記錄一個特定的通知物件:

// ----
// ----

Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true
  }),
});

const AppNavigator = () => {

    const notificationListener = useRef();

    useEffect(() => {
        registerForPushNotificationsAsync()
            .then(token => expoPushTokensApi.register(token));

        notificationListener.current = Notifications.addNotificationReceivedListener(notification => {
            console.log('--- notification received ---');
            console.log(notification);
            console.log('------');
        });

        // Unsubscribe from events
        return () => {
            Notifications.removeNotificationSubscription(notificationListener.current);
        };
    }, []);
// ----
// ----

如果你的應用程式在前臺,上述程式碼會記錄通知物件。看看下面的預覽:

你可以從這個GitHub倉庫瀏覽這個React Native應用的完整原始碼。同樣,你也可以從這個GitHub倉庫瀏覽完整的伺服器端程式碼。

請注意,在這裡,我沒有設定 FCM 就收到了我的 Android 裝置的通知,因為我在使用 Expo 應用進行開發。如果你需要在沒有 Expo 應用的情況下測試你的應用,或者你希望將你的應用部署到 Google Play 或 Apple App Store,請確保正確生成 FCM 和 APNs 憑證。

官方的Expo文件可以指導你為生產應用設定FCM和APNs。然而,由於Expo應用,你可以在不配置FCM或APNs的情況下開發和測試你的應用程式。

使用Expo傳送本地通知

在某些情況下,開發者不需要遠端伺服器來傳送通知。一個例子可以是音樂播放器,當一首歌曲正在播放時,應用需要顯示一個通知。

在某些情況下,開發者不需要遠端伺服器來傳送通知。其中一個例子可以是音樂播放器,當播放音軌時,應用需要顯示一個通知:

image.png

以下程式碼塊展示瞭如何建立一個本地通知:

import { StyleSheet, Text, View, Button } from "react-native";
import * as Notifications from "expo-notifications";

{
  /*Configure our notification settings:*/
}

Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: true,
    shouldSetBadge: true,
  }),
});

const generateNotification = async () => {
  //show the notification to the user
  Notifications.scheduleNotificationAsync({
    //set the content of the notification
    content: {
      title: "Demo title",
      body: "Demo body",
    },
    trigger: null,
  });
};
return (
  <View style={styles.container}>
    {/*When clicked, execute the generateNotification function*/}
    <Button
      title="Generate notification"
      onPress={() => generateNotification()}
    />
  </View>
);

這將是程式碼的結果:

使用Notifee顯示通知

除了Expo的通知服務,我們還可以使用 Notifee 來為我們生成推送通知。這個庫擁有許多特性,其中包括:

  • Firebase 和 OneSignal 整合:與Expo不同,Notifee也支援OneSignal令牌。這為使用者在使用通知服務時提供了更多的選擇。
  • 透過 style 屬性進行自定義樣式:開發者現在可以在通知中嵌入圖片和大量文字
  • 基於觸發器的訊息:如果滿足某個條件,允許應用程式傳送通知
  • 易於使用的互動API:顧名思義,這使得使用者可以透過按鈕或文字欄位與通知進行互動

首先,讓我們建立一個空白的React Native專案,並安裝 notifee 模組以開始使用 Notifee:

npx react-native@latest init notifeeLearn
npm install notifee

然後,要使用這個庫,在 App.tsx 檔案中編寫這段程式碼:

import notifee from "@notifee/react-native";

function App(): React.JSX.Element {
  // 定義我們的處理函式:
  async function onDisplayNotification() {

    // 請求許可權(iOS 需要)
    await notifee.requestPermission();

    // 建立一個頻道(Android 需要)
    const channelId = await notifee.createChannel({
      id: "default",
      name: "預設頻道",
    });

    // 顯示一個通知
    await notifee.displayNotification({
      title: "通知標題",
      body: "通知的主體內容",
      android: {
        channelId,
        // 如果你想要通知被按下時開啟應用,需要 pressAction
        pressAction: {
          id: "default",
        },
      },
    });
  }
  return (
    <SafeAreaView style={styles.main}>
    {/*建立一個按鈕,點選時,應向使用者顯示一個通知*/}
      <Button
        title="顯示通知"
        onPress={() => onDisplayNotification()}
      />
    </SafeAreaView>
  );
}

結果:

現在我們已經看到了 Notifee 的一個非常基本的實現,讓我們來看一個更復雜的例子。

後臺通知

感謝 Notifee,我們甚至可以建立後臺通知,即使應用程式關閉,也可以傳送。這適用於我們想要傳送一個無聲通知的情況,無論應用程式是否開啟,例如文字訊息或已完成的下載,都需要傳送。

作為第一步,我們必須配置後臺事件。為了實現這一點,請導航到 index.js 檔案。編寫以下程式碼:

// 檔名:index.js
import notifee, {EventType} from '@notifee/react-native';

// 這個處理器將監聽後臺事件:
notifee.onBackgroundEvent(async ({type, detail}) => {
  const {notification, pressAction} = detail;
  // 記錄通知資料
  console.log('型別 ', type);
  console.log('通知資料 ', detail);

  // 檢查使用者是否已按下通知
  if (type === EventType.PRESS && pressAction.id === 'default') {
    // 進行一些處理..
    console.log('預設按鈕被按下');
    // 在事件被註冊後移除通知。
    await notifee.cancelNotification(notification.id);
  }
});

然後,當使用者點選通知時,React會將他們帶回應用程式,並列印出通知的 id 以及互動型別:

新增互動性和動作

如前所述,我們甚至可以使用 Notifee 的互動式 API 配置我們的通知以使其具有互動性。為此,在你的 displayNotifications 函式中的 actions 陣列新增一個 title 和一個 pressAction 欄位:

// 檔名:App.tsx
// 為簡潔起見,移除了不必要的程式碼
await notifee.displayNotification({
  //..後續程式碼..
  android: {
    //後續程式碼..
    pressAction: {
      /*更多程式碼*/
    },
    //在此配置動作:
    actions: [{ title: "點選我", pressAction: { id: "click-me" } }],
  },
});

現在我們已經建立了一個動作,接下來我們需要建立一個前臺服務處理程式:

// 檔名:App.tsx
useEffect(() => {
  // 註冊我們的前臺事件:
  notifee.onForegroundEvent(({ type, detail }) => {
    // 如果通知上的按鈕被點選:
    if (type === EventType.ACTION_PRESS && detail?.pressAction?.id) {
      console.log("detail", detail);
      // 列印出通知的 id:
      console.log(
        "使用者點選了一個帶有 id 的動作:",
        detail.pressAction.id,
      );
    }
  });
}, []);

結果:

有許多方法可以使用互動式通知。例如:

  • 如果你在你的社交應用上向使用者傳送通知,告訴他們有人關注了他們,你可以新增一個按鈕,讓你的使用者可以關注回那個人
  • 如果你提醒媒體應用的使用者,比如音樂分享平臺的使用者,有人分享了一首新歌,你可以新增一個按鈕,讓使用者將這首歌新增到他們的播放佇列中
  • 如果你透過你的應用提供了一個時間敏感的警報,你可以允許使用者靜音該警報或稍後傳送提醒。

應該使用哪個通知庫?

Expo 和 Notifee 都是執行相同任務的優秀開源庫。此外,它們具有類似的功能集和學習曲線。因此,這意味著你不需要花費大量時間來學習這些庫。

這裡有一個比較這兩個庫的表格:

特性Expo NotificationsNotifee
通知型別本地和遠端通知本地和遠端通知
整合FCM和APNFCM和OneSignal
定製有限的定製選項更多自定義選項
效能高效且輕量級略低於Expo通知的效率
文件體面的文件優秀的文件
社群良好的社群支援強大的社群支援
需要Expo模組嗎?YesNo
最佳使用案例簡單通知複雜通知

如果你想優先考慮效率並且只需要簡單的本地和遠端通知,Expo是理想的選擇。然而,對於更自定義或複雜的通知,你可以考慮使用Notifee。

解決設定推送通知時的常見問題

開發人員在使用 Expo 通知和 Notifee 時常常會遇到一些常見的問題。讓我們看看這些問題的原因以及如何解決它們:

  • 我無法在裸 React Native 應用中執行 Expo 通知:這是因為 Expo 通知庫依賴於其他 Expo 庫。要解決這個問題,請轉到 Expo 通知安裝文件並遵循設定步驟。
  • Notifee 無法在 Expo 專案中執行:不幸的是,截至撰寫本文時,這仍然是一個持續存在的問題。最好是從 Expo 中彈出或者啟動一個裸 React Native 專案。

總結

在這篇文章中,我們瞭解了為什麼推送通知如此受歡迎。我們還學習瞭如何在 React Native 應用程式中傳送推送通知,方法是新增通知令牌,從伺服器傳送它們,並使用 Expo 通知 API 在使用者裝置上顯示它們。

此外,我們探索瞭如何透過Notifee庫顯示本地和互動式通知。這個庫提供了定製推送通知或建立更復雜通知型別的方法。

交流

首發於公眾號 大遷世界,歡迎關注。📝 每週一篇實用的前端文章 🛠️ 分享值得關注的開發工具 ❓ 有疑問?我來回答

本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。

相關文章