移動應用消息推送及推送原理


轉載請注明出處 原文鏈接:移動應用消息推送及推送原理

消息推送

消息通知分本地通知和遠程推送通知。

本文是記錄React Native使用aws push notifications推送及相關配置及遇到的相關問題。在twilio和aws中選擇使用aws的Pinpoint服務。Pinpoint服務前一百萬條通知免費,之后每一百萬條通知收取 1.00 USD。SMS發送的每條消息都需要付費。每條消息支付的價格取決於接收人所在國家/地區。APNs使用keys來配置推送。

iOS推送原理

蘋果的推送服務通知由蘋果的推送服務器APNs(Apple Push Notification server)來完成的。APNs服務器收到我們發送的消息,然后將這條消息推送到指定的IOS設備上,然后再由IOS設備通過通知或者聲音的形式推到到我們的應用。
iOS要實現遠程推送需要安裝具有推送的應用,首次打開應用后詢問請求推送權限之后會向APNs服務器進行注冊。注冊成功之后APNs服務器會返回一個deviceToken, 拿到這個deviceToken 我們就可以發消息到這台iOS設備了。當注冊成功之后,我們的應用會和APNs服務器維持一個TCP鏈接。我們將deviceToken會傳到自己的服務器,通過具體的業務需求服務器發送消息到APNs服務器,APNs會將消息推送到iOS設備上。

iOS設備注冊APNs的過程

  • 設備連接APNs服務器並攜帶設備序列化(UUID)
  • 連接成功,APNs經過打包和處理后生成deviceToken並返回給注冊設備
  • 設備獲取的deviceToken通過自己的程序把它發送到自己的服務器
  • 設備在APNs服務器與自己的服務器進行注冊

iOS推送過程

  • 設備安裝了推送功能的應用,設備在有網下有連接APNs推送的服務器,連接過程中,APNs服務器會驗證deviceToken,成功后維持一個基於TCP的長連接
  • 服務器把要推送的消息(含有deviceToken)一起發送給APNs服務器
  • APNs服務器將接收到的信息推送給指定的deviceToken設備
  • 設備收到推送后通知到應用程序

1595486884533.png

根據發送過程的流程, 我們可以較快的排查消息推送的一些收不到消息問題。

Android推送原理

Android推送服務是采用GCM(Google Clond Message)來實現的(國內需要自備梯子),系統級別的消息推送服務。

詳細的過程原文

App從服務器獲取最新消息的基本方式有3種:Push、Pull 和 SMS

  • Push 是服務器主送發送到客戶端,客戶端被動接受

  • Pull 客戶端定期主動拉取服務端的消息,也叫做輪詢。 缺點是要消耗設備的CPU,電量,流量等。

  • SMS 通過發送信令的方式發給客戶端,客戶端收到后向服務器拉取消息。缺點就是收費問題。

推送方案

C2DM(Cloudto Device Messaging)

Google 操作系統有自身的消息推送功能(系統級別)

基於Push方式,C2DM服務負責處理諸如消息排隊等事務,並向運行於目標設備上的應用程序分發這些消息。

注冊設備、消息推送流程、出發流程同IOS。

這種C2DM方式是Google官方提供的。國內使用Google需要FQ,國內的手機需要安裝Google。

輪詢

基於Pull的方式。客戶端定期主動拉取服務端的消息。 成本是要消耗設備的CPU,電量,流量等。

SMS

短信發送,基於Push方式。原理是通過攔截SMS消息並且解析消息內容來了解服務器的意圖,並獲取其顯示內容進行處理。成本就是通過運營商繳納短信費用。

MQTT協議

國內很多企業都廣泛使用MQTT作為Android手機客戶端與服務器端推送消息的協議。
MQTT(消息隊列遙測傳輸)是ISO 標准(ISO/IEC PRF 20922)下基於發布/訂閱范式的消息協議。工作在 TCP/IP協議族上。基於Push的方式輕量級的消息發布/訂閱協議。

XMPP協議

Extensible Messaging And Presence protocol,可擴展通訊和表示協議,是基於可擴展標記語言(XML)的協議。

基本的網絡架構:

XMPP中定義了三個角色,客戶端,服務器,網關。通信能夠在這三者的任意兩個之間雙向發生。服務器同時承擔了客戶端信息記錄,連接管理和信息的路由功能。網關承擔着與異構即時通信系統的互聯互通,異構系統可以包括SMS(短信),MSN,ICQ等。基本的網絡形式是單客戶端通過TCP/IP連接到單服務器,然后在之上傳輸XML。

XMPP系統特點:

  • 客戶機/服務器通信模式;
  • 分布式網絡;
  • 簡單的客戶端;
  • 標准通用標記語言的子集XML的數據格式。

通俗解釋:其實XMPP 是一種很類似於http協議的一種數據傳輸協議,它的過程就如同“解包裝--〉包裝”的過程,用戶只需要明白它接受的類型,並理解它返回的類型,就可以很好的利用xmpp來進行數據通訊。

XMPP推送的優點:簡單、開源、拓展性強。缺點:消息被推送出去,不管消息是否成功到達客戶端。Android XMPP源碼實例

其他的第三方推送平台

友盟、極光等。

使用aws配置推送

環境配置

先安裝Amplify CLI,用來創建AWS雲服務。

npm install -g @aws-amplify/cli

設置amplify,進行配置Amplify

amplify configure

在命令框執行之后會跳轉網頁來登錄aws網站, 登錄后會創建一個IMA賬號。會需要設置AWS Region和user name。登錄的賬號需擁有創建IMA的權限。否則在創建過程中會提示403 無權操作。

接下來需要初始化app端的配置,進入項目根目錄執行

amplify init

根據提示完成項目相應配置如平台、語言、編輯器、環境等。最后選擇剛剛創建好的IMA角色,會在項目下生成amplify-config文件夾及export—was.js。

1595468402653.png

IOS平台配置

此時我們可以添加需要的aws服務了。添加Push Notifications服務,可以先從IOS平台開始配置:

amplify add notifications

選擇APNs

1595469166533.png

會提示需要創建的Pinpoint資源的相關配置,如資源名、蘋果推送證書或者key ID、、bundle identifier、Team identifier、Authenrication key(p8文件 下面介紹如何創建key)。該階段的操作會在aws控制台自動創建好這個服務。(后端開發人員一般就不需要在去拿生成的keys、.p8)。推介使用keys來創建推送服務。

基於keys的身份驗證提供了與APN通信的無狀態方式。無狀態通信比基於證書的通信快,因為它不需要APNs來查找與您的提供程序服務器有關的證書或其他信息。使用基於令牌的身份驗證還有其他優點:

  • 可以在同個keys下分發沙河環境和發布狀態的推送(Sandbox Production)
  • 可以從多個提供程序服務器中使用相同的令牌
  • 可以使用一個令牌來分發公司所有應用程序的通知

aws控制台

1595469469543.png

這樣APNs服務就在aws Pinpoint服務中配置好了。

創建IOS key步驟

有一個付費的apple賬號之后登陸蘋果開發者中心,進入account

1595471512228.png

keys 創建key

1595471596185.png

創建完成

1595471682354.png

可以下載這個key也就是p8文件(* 只能下載一次,蘋果服務器並且不會對它進行保存,所以需要保存好)

Android平台配置

amplify add notifications

1595472838827.png

在配置中需要輸入在firebase申請的該App的api秘鑰。配置完成之后,在aws控制台中:

Android的推送需要Google的服務,需要訪問Firebase控制台,然后點擊“ 項目概述”旁邊的Gear圖標,然后點擊“ 項目設置”。

1595472985870.png

下載google-server.json放到項目adnroid/app/目錄下

具體操配置作鏈接

在配置推送時遇到的問題

Android 遇到的問題

在項目中一開始使用的是yarn安裝的依賴,在安卓項目中會出現。同時也是這個不經意的問題,導致在配置Android時花費了不少的功夫。google和百度提出的解決方案是把項目生成androidX,

1595990076537.png

1595990123706.png

但是在gradle.properties里面的useAndroidX已經是true。按照網上在一頓排錯之后還是沒有解決這個問題, 最后就把整個node_nodules刪除之后清除node_modules緩存,重新npm install就沒有再繼續提示這個錯誤。

import android.support.v4.app.NotificationCompat

配置好,當應用啟動時 android 不會調用PushNotification.onRegister這個方法。因為調用這個方法的目的是獲取設備的deviceToken,所以需要從NativeModules.RNPushNotification模塊中獲取相應的方法來獲取deviceToken

在ReactNative中配置

注意: 在配置ios推送時需要申請推送權限請求。

IOS 配置

// Required to register for notifications
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
 [RNCPushNotificationIOS didRegisterUserNotificationSettings:notificationSettings];
}
// Required for the register event.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
 [RNCPushNotificationIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
// Required for the notification event. You must call the completion handler after handling the remote notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
  [RNCPushNotificationIOS didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
// Required for the registrationError event.
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
 [RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error];
}
// IOS 10+ Required for localNotification event
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
         withCompletionHandler:(void (^)(void))completionHandler
{
  [RNCPushNotificationIOS didReceiveNotificationResponse:response];
  completionHandler();
}
// IOS 4-10 Required for the localNotification event.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
 [RNCPushNotificationIOS didReceiveLocalNotification:notification];
}

Android

打開android / app / src / main / AndroidManifest.xml文件,並將以下配置添加到applicationelement中。

<application ... >

     <!--[START Push notification config -->
         <!-- [START firebase_service] -->
         <service
             android:name="com.amazonaws.amplify.pushnotification.RNPushNotificationMessagingService">
             <intent-filter>
                 <action android:name="com.google.firebase.MESSAGING_EVENT"/>
             </intent-filter>
         </service>
         <!-- [END firebase_service] -->
         <!-- [START firebase_iid_service] -->
         <service
             android:name="com.amazonaws.amplify.pushnotification.RNPushNotificationDeviceIDService">
             <intent-filter>
                 <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
             </intent-filter>
         </service>
         <receiver
             android:name="com.amazonaws.amplify.pushnotification.modules.RNPushNotificationBroadcastReceiver"
             android:exported="false" >
             <intent-filter>
                 <action android:name="com.amazonaws.amplify.pushnotification.NOTIFICATION_OPENED"/>
             </intent-filter>
         </receiver>
     <!-- [END Push notification config -->

 </application>

App

1595475707110

//...
constructor(props) {
    super(props);
    if (isAndroid) {
	//Android 不會調用 PushNotification.onRegister,需要從NativeModules中調用RNPushNotification.getToken來回去deviceToken
	NativeModules.RNPushNotification.getToken(this.handleRegisterDeviceToken);
    } else {
      PushNotification.onRegister(this.handleRegisterDeviceToken);
    }
    // 設置收到notification的回調 處理收到的消息
    PushNotification.onNotification(notification => {
      this.handleReceiveNotification(notification);
      if (isIos) {
        notification.finish(PushNotificationIOS.FetchResult.NoData);
      }
    });
    // 點擊消息后的回調
    PushNotification.onNotificationOpened(this.handleOpenNotification);
  }
//...

到此 我們的客戶端配置好了aws的推送接受服務。

當拿到deviceToken我們需要將它發給我們的服務器,具體的業務邏輯交給后端(接入aws-pinpoint服務)去觸發消息推送。

總結

在iOS推送過程中,deviceToken是會變化的問題, 所以在程序中要做好更新deviceToken的動作,避免因設備升級或者應用重裝而導致收不到消息。

參考鏈接:

ios推送使用keys與推送證書區別

MQTT協議

XMPP協議

Android推送原理

轉載注明出處:原文鏈接:移動應用消息推送及推送原理


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM