Notification Direct Reply Inline Reply

實作Android Notification的快速回覆

莊以楷 2020/05/26 10:24:21
286

實作Android Notification的快速回覆

 

作者YiKai Chuang

 

前言

 

若是常使用傳訊軟體或Gmail之類應用程式的人應該不會對藉由點擊手機狀態列的Notification來開啟特定應用程式、或直接在Notification上回覆訊息、郵件...等操作感到陌生。從 Android 7.0 (API 等級 24) 開始,程式開發者可以新增動作讓使用者回覆訊息,或是直接在Notification中輸入其他文字...等,本文即是對Inline Reply(或Direct Reply)功能的實作,做一個概括性的介紹

 

開始在Android專案實作

 

  1. 首先建立一個名稱為MyFirebaseMessagingService的FirebaseMessagingService(可自行改成任意名稱),以本專案為例,我是在onMessageReceived收到remoteMessage之後,將remoteMessage的title和body作為參數,丟進sendNotification()

 

  1. 其次,sendNotification()做發送Notification到手機的處理

(1).由於每一個Notification都必須對使用者的點擊做出回應,為了達到此要求,所以需要建立PendingIntent

 

(2).建立Reply(回覆)的RemoteInput:將此RemoteInput命名為remoteInput (RemoteInput原先是在Android Wearable的API中使用,譬如透過Notification.Builder的setRemoteInput方法,可以讓使用者在Android穿戴式裝置進行語音回覆,現在也支援文字輸入),remoteInput之後會用於接收使用者的文字輸入,以及在使用者輸入前顯示提示文字

 

(3).建立Reply(回覆)的Action:將此Action命名為replyAction,接著調用addRemoteInput(),把之前建好的remoteInput塞進參數。此外,也可以視情況考慮使用setAllowGeneratedReplies(true) ,允許Android Wear 2.0生成Smart Reply,讓使用者可以更快速、方便地回應。

 

(4).建立Dismiss(關閉Notification)PendingIntent:將此PendingIntent命名為dismissIntent,由於Disimiss功能只是想關閉Notification做測試,所以建立Intent時,setFlags()的參數不是像處理Reply功能時寫成(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP),而是改寫成(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)

 

(5).建立Dismiss(關閉Notification)的Action:將此Action命名為dismissAction,接著把之前建立的dismissIntent塞入參數

 

(6).建立Notification.Builder:將此Builder命名為notificationBuilder,把所有Action都透過addAction()加到notificationBuilder之後,就可以準備發布

 

(7).若是Android 8以上需要建立NotificationChannel,另外,在Firebase Console發送完訊息之後,為了讓使用者的手機上可以成功跳出Notification,需要呼叫NotificationManager的notify(),並且傳入Notification的id(數字必須唯一,不能重複)和Notification.Builder這兩個參數

 

  1. 在主畫面(MainActivity.java)處理使用者的動作

(1).由於在MyFirebaseMessagingService設定Reply功能相關的intent時,setFlags()裡頭所塞的參數是(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP),若從Firebase Console成功發送訊息到使用者手機,當使用者實際點擊Notification,便會執行MainActivity的onNewIntent()

 

(2).在onNewIntent()的處理:若使用者點擊Notification的Reply功能選項,並且有輸入回覆文字,Android程式會透過RemoteInput.getResultsFromIntent()來接收,以本專案為例,執行完String res = (String) remoteInput.getCharSequence(KEY_TEXT_REPLY)這行程式之後,res變數便會得到使用者所回覆的內容

 

(2).本專案利用RemoteViews做出客製化的介面,但由於RemoteViews不是本篇所要探討的重點,所以不詳細說明

 

(3).接著更新Notification.Builder

 

(4).最後,為了在同一個Notification顯示使用者所回覆的內容,需要呼叫NotificationManagerCompat.notify(),最重要的地方在於:若之前在MyFirebaseMessagingService建立Notification時有設定的id或tag的話,主程式的Notification的id或tag,也必須使用同樣的值才可以

 

App的執行結果:

 

  1. 從Firebase Console發送訊息後,手機上很快就收到Notification

 

  1. 點擊【回覆】功能選項後,提示使用者輸入文字

 

  1. 輸入【我知道了】做測試,然後送出

 

  1. 可在同一個Notification看到剛才輸入的文字

 

最後總結:

 

除了上述介紹內容,若有需要也可以透過setRemoteInputHistory(),在同一個Notification顯示所有的回覆的歷史紀錄。只要願意花點時間研究,相信任何人都可以做到豐富、生動的推播通知。

 

參考來源:

 

  1. https://android-developers.googleblog.com/2016/06/notifications-in-android-n.html#directreply

  2. https://developer.android.com/guide/topics/ui/notifiers/notifications

  3. https://www.journaldev.com/15571/android-notification-direct-reply

莊以楷