0%

【Expo Android 推播整合 04】 裝置註冊:請求通知權限與通知種類介紹

上一篇 中,我們完成了:

  • 初始化 Firebase 與 Azure Notification Hub
  • 成功從 Firebase 取得 FCM token
  • 註冊裝置至 Azure Notification Hub(使用 FCM v1 註冊格式)

這篇我們的目標是:

  • 如何顯示 前景通知
  • 如何 請求 Android 13+ 的通知權限
  • 如何處理 通知點擊事件(背景與關閉狀態)

先來認識手機中的 App 通知類型!

App 通知行為分類

App 狀態 行為說明 顯示位置
關閉(not running) App 關閉狀態顯示的通知,通知由系統顯示,點擊會啟動 App 並可帶參數 通常在手機待機畫面列表,以及運行畫面頂部顯示小圖示
背景(background) App 在背景模式時顯示,通知由系統顯示,點擊會觸發 onNotificationOpenedApp 同上
前景(foreground) App 在畫面上運行時顯示。顯示方法由開發者自行設定。 由開發者處理

請求 Android 13 通知權限

從 Android 13(API 33)開始,需要向使用者明確請求 POST_NOTIFICATIONS 權限。

1
2
3
4
5
6
7
8
9
10
11
import { PermissionsAndroid, Platform } from 'react-native'

async function requestAndroidNotificationPermission() {
if (Platform.OS === 'android' && Platform.Version >= 33) {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS
)
return granted === PermissionsAndroid.RESULTS.GRANTED
}
return true
}

顯示前景通知(App 開啟中)

當 App 正在使用中,通知不會由系統自動顯示。我們必須手動接收並彈出提醒。你也可以改用 Toast 或 Modal 呈現。

1
2
3
4
5
6
import messaging from '@react-native-firebase/messaging'
import { Alert } from 'react-native'

messaging().onMessage(async (remoteMessage) => {
Alert.alert('前景通知', remoteMessage.notification?.title || '收到通知')
})

背景狀態通知點擊

1
2
3
4
5
6
messaging().onNotificationOpenedApp((remoteMessage) => {
const messaage = remoteMessage?.data?.messaage
if (typeof messaage === 'string') {
Alert.alert('來自背景通知訊息:', messaage)
}
})

關閉狀態通知點擊

1
2
3
4
5
const initialMsg = await messaging().getInitialNotification()
const url = initialMsg?.data?.messaage
if (typeof messaage === 'string') {
Alert.alert('來自關閉通知訊息:', messaage)
}

完整程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import { useEffect, useRef, useState } from 'react';
import { StyleSheet, PermissionsAndroid, Platform, Alert } from 'react-native';
import messaging from '@react-native-firebase/messaging';
import registerDeviceToAzure from '@/hooks/useAzureRegistration';

// 清理資源和取消事件監聽器
const cleanupFns = useRef<(() => void)[]>([])

export default function HomeScreen() {
useEffect(() => {
const setupPush = async () => {
try {
const granted = await requestAndroidNotificationPermission()
if (!granted) {
Alert.alert('未授權通知權限')
return
}

const authStatus = await messaging().requestPermission()
const enabled =
authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
authStatus === messaging.AuthorizationStatus.PROVISIONAL

if (!enabled) {
Alert.alert('FCM 權限未啟用')
return
}

const token = await messaging().getToken()
await registerDeviceToAzure(token)

const unsub1 = messaging().onMessage(async (remoteMessage) => {
Alert.alert('前景通知', remoteMessage.notification?.title || '收到通知')
})

const unsub2 = messaging().onNotificationOpenedApp((remoteMessage) => {
const url = remoteMessage?.data?.url
if (typeof url === 'string') {
Alert.alert('背景點通知跳轉:', url)
}
})

const initialMsg = await messaging().getInitialNotification()
const url = initialMsg?.data?.url
if (typeof url === 'string') {
Alert.alert('關閉狀態點通知跳轉:', url)
}

cleanupFns.current = [unsub1, unsub2]
} catch (err) {
Alert.alert('推播初始化錯誤', JSON.stringify(err))
}
}

setupPush()

return () => {
cleanupFns.current.forEach((unsub) => unsub())
}
}, [])

return ( ...略 );
}

我們已經完成裝置註冊與 App 端的通知顯示了 🎉
因為我們之前已經有使用 prebuild 生成 android 資料夾,接著只要在終端機執行

1
./gradlew assembleRelease

打包成功後,release APK 會放在 release 資料夾中

1
專案資料夾/android/app/build/outputs/apk/release

app-release.apk 放進手機完成安裝,就可以使用 Azure 做測試發送囉~
AzureSetup-3