第一步, 我們需要創建一個RemoteInput
第二步, 創建一個PendingIntent, 這個PendingIntent指當我們點擊”發送”的時候調用什么
第三步, 創建一個直接回復的Action
第四步, 創建notification
第五步, 發送通知
一共5個步驟我們就可以創建一個帶有”直接回復”功能的通知了, 而且這5步里2,4,5應該是我們熟悉的代碼, 下面我們就來一步步的完成代碼.
首先, 創建RemoteInput
RemoteInput remoteInput =newRemoteInput.Builder(RESULT_KEY)? ? ? ? .setLabel("回復這條消息")? ? ? ? .build();
1
2
3
1
2
3
很簡單的一個builder, 首先Builder的構造我們需要一個String類型的key, 這個key是干嘛用的? 其實就是我們方便在處理回復的時候拿內容的. 其次一個setLabel方法, 可以對照著上面的圖來看看這是哪一部分的內容, 說白了, 這其實就是一個EditText的Hint值.
接下來繼續第二步, 創建一個PendingIntent, 這個PendingIntent在這里的作用是啟動一個service,所以代碼是這樣的:
Intent intent =newIntent(this, SendMsgService.class);PendingIntent pi = PendingIntent.getService(this,1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
1
2
1
2
都是大家熟悉的代碼, 我們接著來看第三步, 創建一個直接回復的Action
NotificationCompat.Action act =newNotificationCompat.Action.Builder(R.mipmap.ic_launcher,"回復", pi)? ? ? ? .addRemoteInput(remoteInput).build();
1
2
1
2
又是一個Builder, 這個Builder的構造中有三個參數, 第一個參數是一個logo, 搞過通知的朋友肯定對通知的logo都很熟悉了, 第二個參數是這個Action的標簽, 對應上面demo中我們要點擊的那個按鈕, 第三個參數是當我們點擊”回復”的時候要干嘛. 接下來一個addRemoteInput方法將上面我們創建的RemoteInput傳遞進來.
第四步, 創建一個notification, 這個過程中大家都知道也是一個builder, 不過這個builder中肯定有我們不熟悉的方法, 要們上面的Action怎么設置呢?
NotificationCompat.Builder builder =newNotificationCompat.Builder(this)? ? ? ? .setSmallIcon(R.mipmap.ic_launcher)? ? ? ? .setContentTitle("請問是否需要信用卡?")? ? ? ? .setContentText("您好,我是XX銀行的XX經理, 請問你需要辦理信用卡嗎?")? ? ? ? .setColor(Color.CYAN)? ? ? ? .addAction(act)? ? ? ? .setCategory(Notification.CATEGORY_MESSAGE);
1
2
3
4
5
6
7
1
2
3
4
5
6
7
從上往下一個個的來, 略…略…略…,setColor方法的作用是設置一個accent顏色, 對應上面的demo就是那個”回復”和點擊”回復”后輸入框的背景顏色.addAction方法就是將我們上面創建的Action設置進來,setCategory是指定通知的類型, 這里我們指定為消息類型.
最后一步, 發送通知
NotificationManager nm = getSystemService(NotificationManager.class);
nm.notify(NOTIFICATION_ID, builder.build());
1
2
1
2
沒撒好說的, 就這樣簡單的幾步, 一個具有”直接回復”功能的通知就發出來了, 不過還沒完, 雖然通知出來了, 但是用戶回復的內容我們還沒處理. 這些邏輯的處理我們放到上面提到的那個service里執行.
那這個處理流程是怎樣的呢? 還是先來羅列下流程.
拿到用戶輸入的內容
模擬發送的延遲
模擬發送成功, 取消通知
再次一步步的跟代碼, 首先我們要拿到用戶輸入的內容, 我們可以通過RemoteInput的一個靜態方法getResultsFromIntent直接拿到一個Bundle, 然后我們就可以根據上面構建RemoteInput的時候使用的key來拿到內容了.
Bundle replyBundle = RemoteInput.getResultsFromIntent(intent);if(replyBundle !=null) {// 根據key拿到回復的內容String reply = replyBundle.getString(MainActivity.RESULT_KEY);? ? reply(reply);}
1
2
3
4
5
6
1
2
3
4
5
6
拿到內容后, 我們就來模擬回復了, 這個操作是在reply方法中完成的.
privatevoidreply(finalString reply) {? ? mHandler.postDelayed(newRunnable() {@Overridepublicvoidrun() {? ? ? ? ? ? Log.d("reply","reply: "+ reply);? ? ? ? ? ? onReply();? ? ? ? }? ? },1000);}}
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
這里我們延遲1000ms后表示回復成功, 然后調用onReply方法.
privatevoidonReply() {finalNotificationManager nm = getSystemService(NotificationManager.class);? ? mHandler.post(newRunnable() {@Overridepublicvoidrun() {// 更新通知為“回復成功”Notification notification =newNotificationCompat.Builder(SendMsgService.this)? ? ? ? ? ? ? ? ? ? .setSmallIcon(R.mipmap.ic_launcher)? ? ? ? ? ? ? ? ? ? .setContentText("回復成功")? ? ? ? ? ? ? ? ? ? .build();? ? ? ? ? ? nm.notify(MainActivity.NOTIFICATION_ID, notification);? ? ? ? }? ? });// 最后將通知取消mHandler.postDelayed(newRunnable() {@Overridepublicvoidrun() {? ? ? ? ? ? nm.cancel(MainActivity.NOTIFICATION_ID);? ? ? ? }? ? },2000);}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
在onReply里我們就來干剩下的事了, 包括發送一個”發送成功”的消息,然后延遲取消通知.
代碼很簡單, 主要的是創建直接回復的通知和如何拿到用戶輸入的內容, 如果大家的APP中有這樣的需求, 可以考慮在適配Android7的時候加入直接回復的功能.