創(chuàng)建一個基本的通知
以最基本和緊湊形式(也稱為折疊形式)的通知顯示圖標,標題和少量內(nèi)容文本。在本節(jié)中,您將學(xué)習如何創(chuàng)建用戶可以點擊的通知來在應(yīng)用中啟動活動。

有關(guān)通知各部分的更多詳細信息,請閱讀有關(guān) 通知解剖的內(nèi)容
設(shè)置通知內(nèi)容
要開始使用,您需要使用[NotificationCompat.Builder]對象設(shè)置通知的內(nèi)容和頻道 。以下示例顯示如何使用以下命令創(chuàng)建通知:
- 一個小圖標,
[setSmallIcon()]。這是唯一需要的用戶可見內(nèi)容。 - 標題,
[setContentTitle()] - 正文,
[setContentText()] - 通知優(yōu)先級,由...設(shè)定[setPriority()]。優(yōu)先級決定了Android 7.1及更低版本的通知應(yīng)具有多大的侵入性。(對于Android 8.0及更高版本,您必須設(shè)置頻道重要性 - 如下一節(jié)所示。)
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID) .setSmallIcon(R.drawable.notification_icon)
.setContentTitle(textTitle)
.setContentText(textContent)
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
注意[NotificationCompat.Builder]構(gòu)造函數(shù)要求你提供一個通道ID。這是與Android 8.0(API級別26)及更高版本兼容所必需的,但舊版本會忽略它。
默認情況下,通知的文本內(nèi)容被截斷以適合一行。如果您希望通知時間更長,可以通過添加樣式模板來啟用可擴展通知[setStyle()]。例如,下面的代碼創(chuàng)建一個更大的文本區(qū)域:
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Much longer text that cannot fit one line...")
.setStyle(new NotificationCompat.BigTextStyle()
.bigText("Much longer text that cannot fit one line..."))
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
有關(guān)其他大型通知樣式的更多信息,包括如何添加圖像和媒體播放控件,請參閱使用展開式詳細信息創(chuàng)建通知
創(chuàng)建一個頻道并設(shè)置重要性
在Android 8.0及更高版本上發(fā)布通知之前,您必須向系統(tǒng)注冊您的應(yīng)用程序的 [通知渠道],方法是[NotificationChannel]向其 傳遞實例[createNotificationChannel()]。因此,以下代碼被[SDK_INT]版本中的條件阻止 :
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
CharSequence name = getString(R.string.channel_name);
String description = getString(R.string.channel_description);
int importance = NotificationManagerCompat.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
channel.setDescription(description);
// Register the channel with the system
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.createNotificationChannel(channel);
}
注意[NotificationChannel]構(gòu)造函數(shù)需要importance使用類中的一個常量[NotificationManagerCompat]。此參數(shù)確定如何中斷用戶對屬于此的任何通知信道,雖然必須同時設(shè)置的優(yōu)先級與[setPriority()]支持Android 7.1和下(如上所示)。
盡管您必須如此處所示設(shè)置通知重要性/優(yōu)先級,但系統(tǒng)并不保證您會收到警報行為。在某些情況下,系統(tǒng)可能會根據(jù)其他因素改變重要性級別,用戶可以隨時重新定義給定頻道的重要性級別。
有關(guān)不同級別的含義的更多信息,請閱讀有關(guān)通知重要性級別
。
設(shè)置通知的點按操作
每個通知都應(yīng)該對點擊進行響應(yīng),通常會在您的應(yīng)用中打開與通知相對應(yīng)的活動。為此,您必須指定一個用[PendingIntent]對象定義的內(nèi)容意圖并將其傳遞給[setContentIntent()]。
以下片段顯示了如何在用戶點擊通知時創(chuàng)建打開活動的基本意圖:
// Create an explicit intent for an Activity in your app
Intent intent = new Intent(this, AlertDetails.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
// Set the intent that will fire when the user taps the notification
.setContentIntent(pendingIntent)
.setAutoCancel(true);
注意這個代碼調(diào)用[setAutoCancel()], 當用戶點擊它時[會]自動[刪除通知]。
[setFlags()]上面顯示的方法有助于在通過通知打開您的應(yīng)用程序后保留用戶的預(yù)期導(dǎo)航體驗。但是,您是否想要使用這取決于您開始的活動類型,可能是以下某種活動:
· 專門用于響應(yīng)通知的活動。在正常的應(yīng)用程序使用過程中,用戶無需導(dǎo)航到此活動,因此該活動將啟動一項新任務(wù),而不是添加到您的應(yīng)用程序的現(xiàn)有 [任務(wù)和后退堆棧中]。這是上面示例中創(chuàng)建的意圖類型。
· 存在于您應(yīng)用的常規(guī)應(yīng)用流中的活動。在這種情況下,啟動該活動應(yīng)創(chuàng)建一個后退堆棧,以便保留用戶對Back和Up按鈕的期望。
有關(guān)配置通知意圖的不同方法的更多信息,請參閱從通知開始活動
。
顯示通知
要顯示通知,請調(diào)用[NotificationManagerCompat.notify()]并為其傳遞一個唯一的通知ID和結(jié)果[NotificationCompat.Builder.build()]。例如:
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
// notificationId is a unique int for each notification that you must define
notificationManager.notify(notificationId, mBuilder.build());
請記住保存您傳遞給的通知ID,[NotificationManagerCompat.notify()]因為如果您想[更新]或[刪除通知],以后需要它 。
注意:從Android 8.1(API級別27)開始,應(yīng)用程序無法每秒發(fā)出一次以上的通知聲音。如果您的應(yīng)用在一秒內(nèi)發(fā)布多個通知,它們?nèi)及搭A(yù)期顯示,但每秒只有第一個通知發(fā)出聲音。
添加操作按鈕
通知最多可以提供三個操作按鈕,以便用戶快速響應(yīng),例如暫停提醒或甚至回復(fù)短信。但是這些操作按鈕不應(yīng)復(fù)制用戶[點擊通知]時執(zhí)行的操作 。

添加動作按鈕,傳遞[PendingIntent]給 [addAction()]方法。這就像設(shè)置通知的默認點按操作一樣,除了啟動活動之外,您還可以執(zhí)行其他各種操作,例如啟動[BroadcastReceiver]在后臺執(zhí)行作業(yè)的操作,以便操作不會中斷已打開的應(yīng)用程序。
例如,以下代碼顯示如何將廣播發(fā)送到特定接收者:
Intent snoozeIntent = new Intent(this, MyBroadcastReceiver.class);
snoozeIntent.setAction(ACTION_SNOOZE);
snoozeIntent.putExtra(EXTRA_NOTIFICATION_ID, 0);
PendingIntent snoozePendingIntent =
PendingIntent.getBroadcast(this, 0, snoozeIntent, 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.addAction(R.drawable.ic_snooze, getString(R.string.snooze),
snoozePendingIntent);
有關(guān)構(gòu)建[BroadcastReceiver](https://developer.android.com/reference/android/content/BroadcastReceiver.html) 要運行后臺工作的更多信息,請參閱 廣播指南。
如果您嘗試使用媒體播放按鈕(例如暫停和跳過曲目)來構(gòu)建通知,請參閱如何使用媒體控件創(chuàng)建通知。
添加直接回復(fù)操作
Android 7.0(API級別24)中引入的直接回復(fù)操作允許用戶直接在通知中輸入文本,通知會在不打開任何活動的情況下發(fā)送到您的應(yīng)用。例如,您可以使用直接回復(fù)操作來讓用戶回復(fù)通知中的短信或更新任務(wù)列表。

直接回復(fù)操作在打開文本輸入的通知中顯示為附加按鈕。當用戶完成輸入時,系統(tǒng)將文本響應(yīng)附加到您為通知操作指定的意圖,并將意圖發(fā)送到您的應(yīng)用程序。
添加回復(fù)按鈕
創(chuàng)建支持直接回復(fù)的通知操作:
- 創(chuàng)建一個
[RemoteInput.Builder]可以添加到通知操作的實例。此類的構(gòu)造函數(shù)接受系統(tǒng)用作文本輸入的關(guān)鍵字的字符串。稍后,掌上電腦應(yīng)用程序會使用該鍵來檢索輸入的文本。
// Key for the string that's delivered in the action's intent.
private static final String KEY_TEXT_REPLY = "key_text_reply";
String replyLabel = getResources().getString(R.string.reply_label);
RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY)
.setLabel(replyLabel)
.build();
2. 創(chuàng)建一個[PendingIntent]回復(fù)操作。
// Build a PendingIntent for the reply action to trigger.
PendingIntent replyPendingIntent =
PendingIntent.getBroadcast(getApplicationContext(),
conversation.getConversationId(),
getMessageReplyIntent(conversation.getConversationId()),
PendingIntent.FLAG_UPDATE_CURRENT);
警告:如果您重新使用[PendingIntent],用戶可能會回復(fù)與他們認為不同的對話。您必須為每個對話提供一個不同的請求代碼,或者提供一個true在您調(diào)用[equals()] 任何其他對話的回復(fù)意圖時不會返回的意圖。對話ID經(jīng)常作為意圖的額外套餐的一部分傳遞,但在您致電時會被忽略[equals()]。
3 將該RemoteInput 對象附加到使用的操作 [addRemoteInput()]// Create the reply action and add the remote input.
NotificationCompat.Action action =
new NotificationCompat.Action.Builder(R.drawable.ic_reply_icon,
getString(R.string.label), replyPendingIntent)
.addRemoteInput(remoteInput)
.build();
4. 將操作應(yīng)用于通知并發(fā)出通知。
// Build the notification and add the action.
Notification newMessageNotification = new Notification.Builder(mContext, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_message)
.setContentTitle(getString(R.string.title))
.setContentText(getString(R.string.content))
.addAction(action)
.build();
// Issue the notification.
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(notificationId, newMessageNotification);
系統(tǒng)提示用戶在觸發(fā)通知操作時輸入響應(yīng),如圖3所示。
從回復(fù)中檢索用戶輸入
從通知的答復(fù)UI,呼叫接收用戶輸入 [RemoteInput.getResultsFromIntent()],它傳遞[Intent]您收到的[BroadcastReceiver]:
private CharSequence getMessageText(Intent intent) {
Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
if (remoteInput != null) {
return remoteInput.getCharSequence(KEY_TEXT_REPLY);
}
return null;
}
處理完文本后,您必須[NotificationManagerCompat.notify()](https://developer.android.com/reference/java/lang/Object.html#notify())使用相同的ID和標簽(如果使用)更新通知 。這對于隱藏直接回復(fù)UI并向用戶確認他們的回復(fù)已被正確接收和處理是必要的。
// Build a new notification, which informs the user that the system
// handled their interaction with the previous notification.
Notification repliedNotification = new Notification.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_message)
.setContentText(getString(R.string.replied))
.build();
// Issue the new notification.
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(notificationId, repliedNotification);
使用這個新通知時,請使用傳遞給接收方[onReceive()]方法的上下文。
您還應(yīng)該通過呼叫將答復(fù)追加到通知底部 [setRemoteInputHistory()]。但是,如果您正在構(gòu)建消息傳遞應(yīng)用程序,則應(yīng)該創(chuàng)建[消息傳遞式通知] 并將新消息附加到對話中。
有關(guān)消息應(yīng)用程序通知的更多建議,請參閱消息傳遞應(yīng)用程序的[最佳實踐]
添加一個進度條
通知可以包含一個動畫進度指示器,向用戶顯示正在進行的操作的狀態(tài)

如果您可以隨時估計完成的操作有多少,請使用指示器的“確定”形式(如圖4所示) [setProgress(max, progress, false)]。第一個參數(shù)是“完整”值(例如100); 第二個是當前完成的數(shù)量,最后一個表示這是確定的進度條。
隨著您的操作進行,持續(xù)呼叫[setProgress(max, progress, false)]更新后的值 progress并重新發(fā)出通知。
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID);
mBuilder.setContentTitle("Picture Download")
.setContentText("Download in progress")
.setSmallIcon(R.drawable.ic_notification)
.setPriority(NotificationCompat.PRIORITY_LOW);
// Issue the initial notification with zero progress
int PROGRESS_MAX = 100;
int PROGRESS_CURRENT = 0;
mBuilder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false);
notificationManager.notify(notificationId, mBuilder.build());
// Do the job here that tracks the progress.
// Usually, this should be in a worker thread
// To show progress, update PROGRESS_CURRENT and update the notification with:
// mBuilder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false);
// notificationManager.notify(notificationId, mBuilder.build());
// When done, update the notification one more time to remove the progress bar
mBuilder.setContentText("Download complete")
.setProgress(0,0,false);
notificationManager.notify(notificationId, mBuilder.build());
在手術(shù)結(jié)束時,progress應(yīng)該相等 max。您可以讓進度條顯示操作完成時間,或?qū)⑵鋭h除。無論哪種情況,請記住更新通知文本以顯示操作已完成。要刪除進度條,請致電[setProgress(0, 0, false)]。
注意:由于進度條要求您的應(yīng)用程序不斷更新通知,因此此代碼通常應(yīng)在后臺服務(wù)中運行。
要顯示不確定的進度條(不指示完成百分比的欄),請調(diào)用 [setProgress(0, 0, true)]。結(jié)果是一個與上面的進度條具有相同樣式的指示符,除了進度條是一個不表示完成的連續(xù)動畫。進度動畫會一直運行,直到您致電 [setProgress(0, 0, false)] ,然后更新通知以刪除活動指示符。
請記住更改通知文本以表明操作已完成。
注意:如果您確實需要下載文件,您應(yīng)該考慮使用 [DownloadManager],它提供了自己的通知來跟蹤您的下載進度。
設(shè)置一個系統(tǒng)范圍的類別
Android使用某些預(yù)定義的系統(tǒng)范圍類別來確定當用戶啟用["請勿打擾”模式]時是否使用給定通知[打擾]用戶 。
如果您的通知屬于中定義的預(yù)先定義的通知類別之一[NotificationCompat]-如[CATEGORY_ALARM], [CATEGORY_REMINDER], [CATEGORY_EVENT],或[CATEGORY_CALL]-你應(yīng)該通過合適的類別聲明它是這樣[setCategory()]。
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setCategory(NotificationCompat.CATEGORY_MESSAGE);
當設(shè)備處于免打擾模式時,系統(tǒng)將使用有關(guān)您的通知類別的這些信息來做出關(guān)于顯示通知的決定。
但是,您無需設(shè)置系統(tǒng)范圍的類別,只有在您的通知與由in定義的某個類別匹配時才應(yīng)該這樣做 [NotificationCompat](https://developer.android.com/reference/android/support/v4/app/NotificationCompat.html)。
設(shè)置鎖定屏幕可見性
要通過鎖定屏幕控制通知中可見的詳細程度,請調(diào)用[setVisibility()]并指定以下值之一:
· [VISIBILITY_PUBLIC] 顯示通知的完整內(nèi)容。
· [VISIBILITY_SECRET] 在鎖定屏幕上不顯示此通知的任何部分。
· [VISIBILITY_PRIVATE] 顯示基本信息,例如通知圖標和內(nèi)容標題,但隱藏通知的完整內(nèi)容。
何時[VISIBILITY_PRIVATE]設(shè)置,您還可以提供隱藏某些詳細信息的通知內(nèi)容的備用版本。例如,短信應(yīng)用可能會顯示一條通知,顯示您有3條新短信,但隱藏了短信內(nèi)容和發(fā)件人。要提供此替代通知,請首先[NotificationCompat.Builder]像往常一樣創(chuàng)建替代通知。然后用另外的通知附加替代通知[setPublicVersion()]。
但是,用戶始終可以最終控制他們的通知是否在鎖定屏幕上可見,甚至可以根據(jù)您的應(yīng)用程序的通知渠道來控制這些通知。
更新通知
要在發(fā)布通知后更新此通知,請[NotificationManagerCompat.notify()]再次撥打電話,并將與您先前使用的ID相同的通知傳遞給它。如果先前的通知已被解除,則會創(chuàng)建新的通知。
您可以選擇打電話, [setOnlyAlertOnce()]以便只在通知出現(xiàn)時通知才會中斷用戶(包括聲音,振動或視覺線索),而不是在以后進行更新。
警告:Android在更新通知時應(yīng)用速率限制。如果您過于頻繁地發(fā)布更新(通常少于一秒),系統(tǒng)可能會放棄一些更新。
刪除通知
通知保持可見,直到發(fā)生以下情況之一:
· 用戶關(guān)閉通知。
· 用戶單擊通知,并[setAutoCancel()]在創(chuàng)建通知時調(diào)用 。
· 你需要[cancel()]一個特定的通知ID。此方法還會刪除正在進行的通知。
· 你打電話[cancelAll()],這將刪除您先前發(fā)出的所有通知。
· 如果您在創(chuàng)建通知時設(shè)置超時 [setTimeoutAfter()],系統(tǒng)會在指定的持續(xù)時間過后取消通知。如果需要,您可以在超過指定的超時時間之前取消通知。
消息傳遞應(yīng)用的最佳實踐
使用此處列出的最佳做法作為創(chuàng)建消息傳遞和聊天應(yīng)用通知時要記住的內(nèi)容的快速參考。
使用MessagingStyle
從Android 7.0(API級別24)開始,Android為消息內(nèi)容專門提供通知樣式模板。使用該 [NotificationCompat.MessagingStyle] 課程,您可以更改通知中顯示的多個標簽,包括會話標題,其他消息和通知的內(nèi)容視圖。
以下代碼片段演示了如何使用MessagingStyle該類自定義通知的樣式。
Notification notification = new Notification.Builder(this, CHANNEL_ID)
.setStyle(new NotificationCompat.MessagingStyle("Me")
.setConversationTitle("Team lunch")
.addMessage("Hi", timestamp1, null) // Pass in null for user.
.addMessage("What's up?", timestamp2, "Coworker")
.addMessage("Not much", timestamp3, null)
.addMessage("How about lunch?", timestamp4, "Coworker"))
.build();
從Android 8.0(API級別26)開始,使用[NotificationCompat.MessagingStyle]該類的通知 將以折疊形式顯示更多內(nèi)容。您還可以使用該[addHistoricMessage()]方法通過向與消息傳遞相關(guān)的通知添加歷史消息來為對話提供上下文。
使用時[NotificationCompat.MessagingStyle]:
· 呼叫[MessagingStyle.setConversationTitle()]為兩人以上的群組聊天設(shè)置標題。一個好的對話標題可能是群組聊天的名稱,或者如果它沒有特定的名稱,則可能是對話中的參與者列表。如果沒有這個,該消息可能被誤認為屬于與對話中最近消息的發(fā)送者的一對一對話。
· 使用該[MessagingStyle.setData()] 方法來包含媒體消息,如圖像。目前支持模式圖像/ *的MIME類型。
使用直接回復(fù)
直接回復(fù)允許用戶回復(fù)內(nèi)部消息。
· 用戶回復(fù)內(nèi)嵌回復(fù)操作后,用于 [MessagingStyle.addMessage()]更新 MessagingStyle通知,并且不收回或取消通知。不取消通知允許用戶從通知中發(fā)送多個回復(fù)。
· 要使內(nèi)聯(lián)回復(fù)操作與Android Wear兼容,請致電。[ Action.WearableExtender.setHintDisplayInlineAction(true)]
· 通過向通知添加歷史消息,使用該方法為直接回復(fù)對話提供上下文。[ addHistoricMessage()]
啟用智能回復(fù)
· 要啟用智能回復(fù),請調(diào)用回復(fù)操作。這會使通知橋接到Android Wear設(shè)備時,用戶可以使用智能回復(fù)響應(yīng)。智能回復(fù)響應(yīng)由完全在機器學(xué)習模型生成,使用 通知提供的上下文,并且沒有數(shù)據(jù)上傳到互聯(lián)網(wǎng)以生成響應(yīng)。[ setAllowGeneratedResponses(true)][NotificationCompat.MessagingStyle]
添加通知元數(shù)據(jù)
· 當設(shè)備處于免打擾模式時,分配通知元數(shù)據(jù)以告知系統(tǒng)如何處理您的應(yīng)用通知。例如,使用 or 方法覆蓋免打擾模式。 addPerson() setCategory(Notification.CATEGORY_MESSAGE)
本文源自 * 發(fā)展* 指南* 用戶界面和導(dǎo)航* 通知
2018/3/9