在react native中的通知有分兩種,一種是本地通知(自己寫按鈕就可以觸發通知),一種是遠程通知。

遠程通知需要一個firebase帳號,並且創建firebase專案,這部分之後再更新(茶

因為新公司只有提供windows電腦,所以本篇只示範android平台的local通知…QQ

安裝步驟可以參考這裡,但是你懶得看,所以我寫了這篇。


安裝

$ yarn add react-native-push-notification
// or
$ npm install --save react-native-push-notification

修改android/app/arc/main/AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.transport">

    <uses-permission android:name="android.permission.INTERNET" />
    <!-- notification -->
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <!-- notification -->
    
    <application
      android:name=".MainApplication"
      android:label="@string/app_name"
      android:icon="@mipmap/ic_launcher"
      android:roundIcon="@mipmap/ic_launcher_round"
      android:allowBackup="false"
      android:theme="@style/AppTheme"
      android:usesCleartextTraffic="true">
      <!-- notification -->
      <meta-data  android:name="com.dieam.reactnativepushnotification.notification_foreground"
                  android:value="false"/>
      <meta-data  android:name="com.dieam.reactnativepushnotification.notification_color"
                  android:resource="@color/white"/> 

      <receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationActions" />
      <receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationPublisher" />
      <receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationBootEventReceiver">
          <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>
      <!-- notification -->

      <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
        android:launchMode="singleTask"
        android:windowSoftInputMode="adjustResize">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
      </activity>
      <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
    </application>
</manifest>

可以看到夾在notification註解中的那些都是我新增的。

在android/app/src/main/res/values 新增一個檔案叫做 colors.xml

貼上以下程式碼,如果通知的視窗想改顏色就是從這裡改。

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

到目前為止就安裝完了。

接下來就可以開始寫code啦!


在utils/新增一個檔案叫做NotifService.js

你也可以新增在其他地方,反正找得到就好,建議是工具類都放在自己一個資料夾。

引入套件 :

import { Platform } from 'react-native';
import PushNotification from 'react-native-push-notification';

設定config :

PushNotification.configure({
  popInitialNotification: true,
  requestPermissions: Platform.OS === 'ios' // 因為我是local通知,所以他官網叫我這樣寫。
});

輸出方法 :

會用到3種方法 — 創建channel、查詢channel是否存在、推送local通知,另外你可能會有一些給你測試用的方法像是 : 查詢所有channels、delete channel…

export default {
  getChannelExists(channelId) {
    //....
  },
  createChannel(channelId) {
    //...
  },
  localNotif(channelId) {
    //...
  }
}

最下面會補充完整 NotifService.js內的寫法,其實就是官網整個貼過來,然後刪掉option那些沒用到的部分。

接著在頁面中引用 :

import NotifService from '@/utils/NotifService';

如果要推送通知,必須要先有至少一個channel,每個channel都會要給他一個channelId,送出通知的時候,要指定是要送到哪個channel才能成功收到,所以也就是說你可以有很多個channel推送不同分類的通知,跟socket訂閱頻道有點像。

假設我這邊要接收通知的類型是訂單,channelId就可以假設為 'orderChannel'

以下程式碼是先判斷你是否已經有 id 叫做 'orderChannel'channel,沒有的話就創建一個。

const [notif, setNotif] = useState(null);
useEffect(() => {
  notif || setNotif(NotifService);
  const asyncFunc = async () => {
    const hasOrderChannel = await notif.getChannelExists(
      'orderChannel'
    );
    hasOrderChannel || notif.createChannel('orderChannel');
  };
  notif && asyncFunc();
}, [notif]);
const pushOrderNotif = () => {
  NotifService.localNotif('orderChannel');
};
pushOrderNotif(); // 你可以把方法綁定在按鈕上測試

以下是完整程式碼 :

import { Platform } from 'react-native';
import PushNotification from 'react-native-push-notification';
PushNotification.configure({
  popInitialNotification: true,
  requestPermissions: Platform.OS === 'ios'
});
export default {
  deleteChannel(channelId) {
    PushNotification.deleteChannel(channelId);
  },
  getChannelExists(channelId) {
    return new Promise((resolve, reject) => {
      PushNotification.channelExists(channelId, function (exists) {
        resolve(exists);
      });
    });
  },
  getChannels() {
    return new Promise((resolve, reject) => {
      PushNotification.getChannels(function (channels) {
        resolve(channels);
      });
    });
  },
  createChannel(channelId) {
    PushNotification.createChannel(
      {
        channelId: channelId,
        channelName: channelId
      },
      created => console.log(`createChannel ${channelId} returned '${created}'`)
    );
  },
  localNotif(channelId) {
    PushNotification.localNotification({
      channelId: channelId,
      autoCancel: true,
      bigText: '有新訂單!', 
      subText: '租車管理新訂單通知',
      actions: ['ok'], 
      message: 'new order notif' // (required)
    });
  }
};
import React, {
  useEffect,
  useState
} from 'react';
import NotifService from '@/utils/NotifService';

const Home = () => {
  const [notif, setNotif] = useState(null);
  
  useEffect(() => {
    notif || setNotif(NotifService);
    const asyncFunc = async () => {
      const hasOrderChannel = await notif.getChannelExists('orderChannel');
      hasOrderChannel || notif.createChannel('orderChannel');
    };
    notif && asyncFunc();
  }, [notif]);
  
  const pushOrderNotif = () => {
    NotifService.localNotif('orderChannel');
  };
  
   return (<button onPress={pushOrderNotif}>發送通知</button>);
}
0
0 回復

發表評論

想要加入討論嗎?
請盡情發表您的想法!

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。