0%

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

上一篇 中,我們完成了:

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

這篇我們的目標是:

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

先來認識手機中的 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