【Expo Android 推播整合 03】 裝置註冊:Azure Notification Hub 註冊與程式碼解析

更新於 發佈於 閱讀時間約 17 分鐘

這篇文章將完成把 Android 裝置註冊到 Azure 通知中樞的程式碼。

前置準備

在這篇文章中,你需要事先準備

前導知識

什麼是 APNS 與 FCM?

  • APNs(Apple Push Notification Service):Apple 提供的推播服務,用來將通知送到 Apple 裝置,需先申請 Apple 開發者帳號才能取得。
  • FCM(Firebase Cloud Messaging):Google 提供的推播服務,使用 Firebase SDK 取得。FCM 提供兩種 API:
    • Legacy API:舊版 API,用 server key 傳送請求,較簡單但功能有限,已經在 2024/06 被淘汰。
    • FCM v1(HTTP v1 API):新版 API,使用 OAuth 2.0 認證,支援多平台設定與更高安全性,Google 推薦使用。

Azure 推播通知運作方式

圖片來自 Azure 文件

圖片來自 Azure 文件

上圖來自 Azure 文件,我們可以從中了解 Azure 推播的運作流程。

  1. 裝置向 APNS(Apple)或 FCM(Google)索取推播識別碼,這將作為接收 Azure 的通道。
  2. Azure 使用識別碼,註冊到 Azure 上。
  3. 後端把通知送到通知中樞。
  4. 通知中樞轉給平台 APNS(Apple)或 FCM(Google),由平台推送到裝置。

使用 REST API 註冊 Azure

其實整段程式碼很簡單,但可以使用 REST API 執行的教學藏在 C# 範例裡,我也是先找到很多提供整合的老舊套件,才發現原來 Azure 本身就有提供註冊方法。

1. 取得推播識別碼

安裝 react-native-firebase/messaging,根據 文件中 messaging 提供的 getToken 方法 取得 FCMtoken

npm i @react-native-firebase/messaging

通常裝置每次取得的 FCMtoken 是相同的,但在以下情境時會改變:

import { useEffect } from 'react';
import messaging from '@react-native-firebase/messaging';

export default function HomeScreen() {
useEffect(() => {
const setupPush = async () => {
try {
const token = await messaging().getToken();
console.log(`FCM token: ${token}`);
} catch (err) {
console.log(`初始化推播錯誤 ${JSON.stringify(err)}`)
}
}
setupPush();
}, []);
return (...)
}

2. 準備註冊需要的參數

我們會使用 建立 Azure 註冊 create-registration 這支 API。還記得我們在上一篇文章中有設定 Azure 通知中樞 FCM(v1)金鑰嗎?這支 API 會將剛才產生的 FCM token 註冊到其中。成功註冊的裝置會得到 registerId 等資訊,這未來能用於修改和刪除,建議存到後端。

這是我們註冊需要準備的資料:

  • namespace:Notification Hub 所屬的命名空間(Namespace)
  • NotificationHub:實際 Notification Hub 名稱,是你註冊裝置與推播的實際目標
  • SAStoken:Shared Access Signature

namespace 和 NotificationHub 已經在上一篇文章建立通知中樞時設定好了,本文裡兩個 value 都用 AnnNotify

SAS token

SAStoken 將由以下參數組成,程式碼在 官方文件 有附。

  • targetUrihttps://${HUB_NAMESPACE}.servicebus.windows.net/${HUB_NAME}
  • sharedKey:’Access Policies 中 DefaultListenSharedAccessSignature 的金鑰值’。
  • ruleId:’DefaultListenSharedAccessSignature’。因為共用存取簽章安全性考量,建議 FullSharedAccess 只在後端使用,前端不要用呦。
  • expiresInMins:過期時間(產生後幾分鐘失效),SAStoken失效不影響已經成功的 Azure 註冊。其實建議設定短時間,並且由後端產生較安全,但前端還是可以自己先產出測試。
raw-image

我們可以新增一個 hook 專門用來放註冊程式碼,直接從 官方文件 中複製貼上吧!

// hooks/useAzureRegistration.tsx
import axios from 'axios'
import CryptoJS from 'crypto-js'

const HUB_NAME = '通知中樞名稱'
const HUB_NAMESPACE = '通知中樞命名空間'
const SHARED_ACCESS_KEY =
'Access Policies 中 DefaultListenSharedAccessSignature 的金鑰值'
const SHARED_ACCESS_KEY_NAME = 'DefaultListenSharedAccessSignature' // 切記前端不要使用 FullSharedAccess

const registerDeviceToAzure = async (fcmToken: string): Promise<void> => {
const baseUri = `https://${HUB_NAMESPACE}.servicebus.windows.net/${HUB_NAME}`
const apiVersion = '2015-01'
const targetUri = `${baseUri}`

// 生產 SAS token,設定 30 分鐘失效
const sasToken = getSelfSignedToken(
targetUri,
SHARED_ACCESS_KEY,
SHARED_ACCESS_KEY_NAME,
30
)
}

// SAS token 工具
const getSelfSignedToken = function (
targetUri: string,
sharedKey: string,
ruleId: string,
expiresInMins: number
) {
targetUri = encodeURIComponent(targetUri.toLowerCase()).toLowerCase()

// Set expiration in seconds
var expireOnDate = new Date()
expireOnDate.setMinutes(expireOnDate.getMinutes() + expiresInMins)
var expires =
Date.UTC(
expireOnDate.getUTCFullYear(),
expireOnDate.getUTCMonth(),
expireOnDate.getUTCDate(),
expireOnDate.getUTCHours(),
expireOnDate.getUTCMinutes(),
expireOnDate.getUTCSeconds()
) / 1000
var tosign = targetUri + '\n' + expires

// using CryptoJS
var signature = CryptoJS.HmacSHA256(tosign, sharedKey)
var base64signature = signature.toString(CryptoJS.enc.Base64)
var base64UriEncoded = encodeURIComponent(base64signature)

// construct autorization string
var token =
'SharedAccessSignature sr=' +
targetUri +
'&sig=' +
base64UriEncoded +
'&se=' +
expires +
'&skn=' +
ruleId
// console.log("signature:" + token);
return token
}

export default registerDeviceToAzure

3. 註冊 Azure 通知中樞

回到 建立 Azure 註冊 create-registration 這支 API,不同系統裝置有不同註冊範本。這篇文章以 Android 為主,使用 Firebase,所以我的註冊範本 xmlBody 使用 FcmV1TemplateRegistration 的範例,其他系統可以再替換。

另外可以選擇使用以下標籤:

  • Tags:推播時可針對標籤推播,如果要設定只推給 Android 用戶,可使用 <Tags>Android</Tags>。想推給某特定用戶,也可以自訂每個裝置有不同 Id,使用 Id 註冊。
  • ExpirationTime:註冊有效時間。Azure 通知中樞的付費方案與可註冊數量有關,尤其是在開發者測試期間會反覆重新安裝(本文第 1 個步驟有提到 FCMtoken 更新機制),如果不設定有效時間,會累積大量新註冊。雖然有 刪除註冊 API,但一次只能刪一個註冊。
// hooks/useAzureRegistration.tsx
const registerDeviceToAzure = async (fcmToken: string): Promise<void> => {
const baseUri = `https://${HUB_NAMESPACE}.servicebus.windows.net/${HUB_NAME}`;
const apiVersion = '2015-01';
const targetUri = `${baseUri}`;

// 生產 SAS token,設定 30 分鐘失效
const sasToken = getSelfSignedToken(targetUri, SHARED_ACCESS_KEY, SHARED_ACCESS_KEY_NAME, 30);

// Azure 註冊的過期時間設定為 30 天
const expirationDate = new Date();
expirationDate.setDate(expirationDate.getDate() + 30);
const isoString = expirationDate.toISOString().replace(/\.\d{3}Z$/, '+08:00');

// FcmV1TemplateRegistration 註冊範本
const xmlBody = `
<entry xmlns="http://www.w3.org/2005/Atom">
<content type="application/xml">
<FcmV1RegistrationDescription xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/netservices/2010/10/servicebus/connect">
<Tags>...</Tags>
<FcmV1RegistrationId>${fcmToken}</FcmV1RegistrationId>
<ExpirationTime>${isoString}</ExpirationTime>
</FcmV1RegistrationDescription>
</content>
</entry>
`;

try {
const response = await axios.post(`${baseUri}/registrations?api-version=${apiVersion}`, xmlBody, {
headers: {
'Authorization': sasToken,
'Content-Type': 'application/atom+xml'
}
});

// 解析 response 返回註冊頁面顯示
console.log('📡 Azure 註冊成功:', {
status: response.status,
registrationId: response.data?.match(/<title[^>]*>(.*?)<\/title>/)?.[1] ?? '不明',
});
} catch (error: any) {
console.error('❌ Azure 註冊失敗:', error);
return `註冊失敗:${error.message}`;
}
};

// SAS token 工具
const getSelfSignedToken = function (targetUri: string, sharedKey: string, ruleId: string,
expiresInMins: number) {
...
};

export default registerDeviceToAzure;


完工!🎉🎉接下來幾篇會介紹

  • 要求裝置開啟通知授權
  • 打包與 Android Studio 偵錯
  • 測試發送

相同文章發布於我的部落格

留言
avatar-img
留言分享你的想法!
avatar-img
Ann Chou的沙龍
17會員
29內容數
從藝術領域轉職到前端工程師,喜歡書寫學習歷程和技術文件,掌握經驗與隨時提取的感覺很好。
Ann Chou的沙龍的其他內容
2025/04/27
這篇文章說明如何在 Windows 電腦上設定 Android 推播通知,包含使用 Expo 串接 Firebase 和 Azure 的步驟。文章涵蓋 Firebase 和 Azure 的設定,以及 Android Studio 和 JDK 的配置。
2025/04/27
這篇文章說明如何在 Windows 電腦上設定 Android 推播通知,包含使用 Expo 串接 Firebase 和 Azure 的步驟。文章涵蓋 Firebase 和 Azure 的設定,以及 Android Studio 和 JDK 的配置。
2025/04/20
介紹在 React Native / Expo 中實作推播通知的方式,並比較使用 Expo Notifications 與整合 Firebase Cloud Messaging(FCM)或 Azure Notification Hubs 的差異。
2025/04/20
介紹在 React Native / Expo 中實作推播通知的方式,並比較使用 Expo Notifications 與整合 Firebase Cloud Messaging(FCM)或 Azure Notification Hubs 的差異。
2025/04/19
本篇主題是 React Native 小介紹。 因為先前在測試 Ionic + PWA 開發,對相機功能實在太失望,結果現在我開始用 React Native / Expo 了。 如果還不清楚 Ionic 和 Reac Native 能做不同種類的 App,可以先閱讀 App 種類概述 。
2025/04/19
本篇主題是 React Native 小介紹。 因為先前在測試 Ionic + PWA 開發,對相機功能實在太失望,結果現在我開始用 React Native / Expo 了。 如果還不清楚 Ionic 和 Reac Native 能做不同種類的 App,可以先閱讀 App 種類概述 。
看更多
你可能也想看
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
全球科技產業的焦點,AKA 全村的希望 NVIDIA,於五月底正式發布了他們在今年 2025 第一季的財報 (輝達內部財務年度為 2026 Q1,實際日曆期間為今年二到四月),交出了打敗了市場預期的成績單。然而,在銷售持續高速成長的同時,川普政府加大對於中國的晶片管制......
Thumbnail
全球科技產業的焦點,AKA 全村的希望 NVIDIA,於五月底正式發布了他們在今年 2025 第一季的財報 (輝達內部財務年度為 2026 Q1,實際日曆期間為今年二到四月),交出了打敗了市場預期的成績單。然而,在銷售持續高速成長的同時,川普政府加大對於中國的晶片管制......
Thumbnail
重點摘要: 6 月繼續維持基準利率不變,強調維持高利率主因為關稅 點陣圖表現略為鷹派,收斂 2026、2027 年降息預期 SEP 連續 2 季下修 GDP、上修通膨預測值 --- 1.繼續維持利率不變,強調需要維持高利率是因為關稅: 聯準會 (Fed) 召開 6 月利率會議
Thumbnail
重點摘要: 6 月繼續維持基準利率不變,強調維持高利率主因為關稅 點陣圖表現略為鷹派,收斂 2026、2027 年降息預期 SEP 連續 2 季下修 GDP、上修通膨預測值 --- 1.繼續維持利率不變,強調需要維持高利率是因為關稅: 聯準會 (Fed) 召開 6 月利率會議
Thumbnail
本篇文章將分享手機App設計教學,並往後介紹使用Flutter開發App的相關知識和技巧。透過這系列的分享,讀者將能夠學習如何利用設計和程式開發技能來製作一個App。文章中也提供了一些靈感來源和教學資源,幫助讀者進行設計和開發的思考和學習。
Thumbnail
本篇文章將分享手機App設計教學,並往後介紹使用Flutter開發App的相關知識和技巧。透過這系列的分享,讀者將能夠學習如何利用設計和程式開發技能來製作一個App。文章中也提供了一些靈感來源和教學資源,幫助讀者進行設計和開發的思考和學習。
Thumbnail
在本篇文章中,將會設定 Cloud Run,以便每當將程式修改並推送到 GitHub 時,它都會使用 Cloud Build 自動構建和部署應用程序的最新版本。
Thumbnail
在本篇文章中,將會設定 Cloud Run,以便每當將程式修改並推送到 GitHub 時,它都會使用 Cloud Build 自動構建和部署應用程序的最新版本。
Thumbnail
本文提供完成訂閱後的相關事項及安裝指引,包括填寫問卷、遠端開通Trading View帳號、指標安裝步驟等。另外也提供影片教學和紙本教學,以及解決安裝問題的方法。
Thumbnail
本文提供完成訂閱後的相關事項及安裝指引,包括填寫問卷、遠端開通Trading View帳號、指標安裝步驟等。另外也提供影片教學和紙本教學,以及解決安裝問題的方法。
Thumbnail
在這篇教學中,我們將學習如何使用 Google Apps Script 來連結 LINE Notify,以便於你的應用程式或自動化工作流程中發送通知。LINE Notify 是 LINE 提供的服務,可以讓你透過 LINE 帳號來發送自訂的通知訊息。
Thumbnail
在這篇教學中,我們將學習如何使用 Google Apps Script 來連結 LINE Notify,以便於你的應用程式或自動化工作流程中發送通知。LINE Notify 是 LINE 提供的服務,可以讓你透過 LINE 帳號來發送自訂的通知訊息。
Thumbnail
本文章將介紹如何在LINE Notify上設定及使用權杖(access token)來進行通知功能。透過此API,可以使用curl或JAVA CODE來讓結果顯示在Line上面,達到及時的通知效果。
Thumbnail
本文章將介紹如何在LINE Notify上設定及使用權杖(access token)來進行通知功能。透過此API,可以使用curl或JAVA CODE來讓結果顯示在Line上面,達到及時的通知效果。
Thumbnail
本課程學習如何使用 Intent 簡單跳頁,切換兩個 Activity。
Thumbnail
本課程學習如何使用 Intent 簡單跳頁,切換兩個 Activity。
Thumbnail
本課程學習如何在 Kotlin 程式碼檔案中,設定 ImageView 圖片元件,顯示本地端圖片。
Thumbnail
本課程學習如何在 Kotlin 程式碼檔案中,設定 ImageView 圖片元件,顯示本地端圖片。
Thumbnail
本課程學習如何使用 Android Studio 建立的第一個應用程式專案:Hello World。
Thumbnail
本課程學習如何使用 Android Studio 建立的第一個應用程式專案:Hello World。
Thumbnail
本篇文章將介紹開發 Android 手機應用程式所需的開發軟體,Google 官方的開發工具 Android Studio。這款軟體不僅免費,還提供完整的支援,適合所有 Android 開發者使用。
Thumbnail
本篇文章將介紹開發 Android 手機應用程式所需的開發軟體,Google 官方的開發工具 Android Studio。這款軟體不僅免費,還提供完整的支援,適合所有 Android 開發者使用。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News