九、創(chuàng)建不同樣式的通知
1扒接、創(chuàng)建基本樣式的通知
a.基本通知
最基本、最緊湊的形式(也稱為“折疊形式”)的通知會顯示一個圖標(biāo)威鹿、標(biāo)題和少量文本內(nèi)容。
設(shè)置通知的內(nèi)容
使用 NotificationCompat.Builder
對象設(shè)置通知的內(nèi)容和渠道忽你。
小圖標(biāo),通過
setSmallIcon()
設(shè)置臂容。這是所必需的唯一用戶可見內(nèi)容科雳。標(biāo)題根蟹,通過
setContentTitle()
設(shè)置。正文文本炸渡,通過
setContentText()
設(shè)置娜亿。通知優(yōu)先級,通過
setPriority()
設(shè)置蚌堵。優(yōu)先級決定了 Android 7.1 及更低版本上的通知的干擾程度。對于 Android 8.0 及更高版本沛婴,請改為設(shè)置渠道重要性吼畏,如下一部分所示。
var builder = 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)及更高版本兼容所必需的泻蚊,但被早期版本忽略。
創(chuàng)建渠道并設(shè)置重要性
需要先將 NotificationChannel
的實例傳遞給 createNotificationChannel()
丑婿,在系統(tǒng)中注冊應(yīng)用的通知渠道性雄,然后才能在 Android 8.0 及更高版本上發(fā)送通知。
private fun createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is not in the Support Library.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = getString(R.string.channel_name)
val descriptionText = getString(R.string.channel_description)
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
description = descriptionText
}
// Register the channel with the system.
val notificationManager: NotificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
必須先創(chuàng)建通知渠道羹奉,然后才能在 Android 8.0 及更高版本上發(fā)布任何通知秒旋,因此請在應(yīng)用啟動時立即執(zhí)行此代碼。您可以放心地重復(fù)調(diào)用此方法诀拭,因為創(chuàng)建現(xiàn)有通知渠道不會執(zhí)行任何操作迁筛。
NotificationChannel
構(gòu)造函數(shù)需要 importance
,它使用 NotificationManager
類中的一個常量耕挨。此參數(shù)確定對于屬于此渠道的任何通知细卧,如何干擾用戶。將優(yōu)先級設(shè)置為 setPriority()
以支持 Android 7.1 及更低版本筒占。
必須設(shè)置通知的重要性或優(yōu)先級贪庙,如以下示例所示,但系統(tǒng)不保證您會獲得提醒行為翰苫。在某些情況下止邮,系統(tǒng)可能會根據(jù)其他因素更改重要性級別,并且用戶可以隨時重新定義給定渠道的重要性級別革骨。
設(shè)置通知的點按操作
每個通知都必須響應(yīng)點按操作农尖,通常是為了打開應(yīng)用中與通知對應(yīng)的 activity。為此良哲,請指定使用 PendingIntent
對象定義的內(nèi)容 intent盛卡,并將其傳遞給 setContentIntent()
。
// Create an explicit intent for an Activity in your app.
val intent = Intent(this, AlertDetails::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)
val builder = NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
// Set the intent that fires when the user taps the notification.
.setContentIntent(pendingIntent)
.setAutoCancel(true)
此代碼會調(diào)用 setAutoCancel()
筑凫,它會在用戶點按通知時自動移除通知滑沧。
上例中顯示的 setFlags()
方法在用戶使用通知打開您的應(yīng)用后保留了預(yù)期的導(dǎo)航體驗并村。您可能需要根據(jù)要啟動的 activity 類型(可以是以下類型之一)來使用它:
專門用于響應(yīng)通知的 activity。用戶在正常使用應(yīng)用期間不會無緣無故地導(dǎo)航到此 activity滓技,因此該 activity 會啟動新任務(wù)哩牍,而不是添加到應(yīng)用的現(xiàn)有任務(wù)和返回堆棧。這是在上述示例中創(chuàng)建的 intent 類型令漂。
應(yīng)用的常規(guī)應(yīng)用流程中存在的 Activity膝昆。在這種情況下,啟動 activity 會創(chuàng)建一個返回堆棧叠必,以便保留用戶對返回和向上按鈕的預(yù)期荚孵。
從通知啟動 Activity
常規(guī) Activity
這類 Activity 是應(yīng)用的正常用戶體驗流程的一部分。當(dāng)用戶從通知轉(zhuǎn)到 activity 時纬朝,新任務(wù)必須包含完整的返回堆棧收叶,以便用戶點按返回按鈕在應(yīng)用層次結(jié)構(gòu)中向上導(dǎo)航。
特殊 Activity
只有當(dāng) Activity 從通知啟動時共苛,用戶才可以看到此類 Activity判没。從某種意義上講,此 activity 通過提供通知本身難以顯示的信息來擴展通知界面隅茎。此 activity 不需要返回堆棧澄峰。
設(shè)置常規(guī) Activity PendingIntent
如需從通知啟動常規(guī) activity,請使用 TaskStackBuilder
設(shè)置 PendingIntent
患膛,以便它可以創(chuàng)建新的返回堆棧摊阀,如下所示。
定義應(yīng)用的 Activity 層次結(jié)構(gòu)
通過向應(yīng)用清單文件中的每個 <activity>
元素添加 android:parentActivityName
屬性踪蹬,定義 activity 的自然層次結(jié)構(gòu)胞此。
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- MainActivity is the parent for ResultActivity. -->
<activity
android:name=".ResultActivity"
android:parentActivityName=".MainActivity" />
...
</activity>
構(gòu)建包含返回堆棧的 PendingIntent
如需啟動包含 activity 返回堆棧的 activity,請創(chuàng)建一個 TaskStackBuilder
實例并調(diào)用 addNextIntentWithParentStack()
跃捣,并向其傳遞您要啟動的 activity 的 Intent
漱牵。
只要您按照前文所述為每個 activity 定義父 activity肌割,就可以調(diào)用 getPendingIntent()
來接收包含整個返回堆棧的 PendingIntent
缩麸。
// Create an Intent for the activity you want to start.
val resultIntent = Intent(this, ResultActivity::class.java)
// Create the TaskStackBuilder.
val resultPendingIntent: PendingIntent? = TaskStackBuilder.create(this).run {
// Add the intent, which inflates the back stack.
addNextIntentWithParentStack(resultIntent)
// Get the PendingIntent containing the entire back stack.
getPendingIntent(0,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
}
可以通過調(diào)用 TaskStackBuilder.editIntentAt()
向堆棧中的 Intent
對象添加參數(shù)。有時必須這樣做全度,才能確保返回堆棧中的 activity 在用戶導(dǎo)航到該 activity 時顯示有意義的數(shù)據(jù)娶聘。
val builder = NotificationCompat.Builder(this, CHANNEL_ID).apply {
setContentIntent(resultPendingIntent)
...
}
with(NotificationManagerCompat.from(this)) {
notify(NOTIFICATION_ID, builder.build())
}
設(shè)置特殊 Activity PendingIntent
由于從通知啟動的特殊 activity 不需要返回堆棧闻镶,因此您可以通過調(diào)用 getActivity()
來創(chuàng)建 PendingIntent
。不過丸升,請在清單中定義相應(yīng)的任務(wù)選項铆农。
- 在清單中,將以下屬性添加到
<activity>
元素中狡耻。
android:taskAffinity= "" 與在代碼中使用的 [FLAG_ACTIVITY_NEW_TASK]
標(biāo)志結(jié)合使用墩剖,將此屬性設(shè)置為空白猴凹,以確保此 activity 不會進入應(yīng)用的默認(rèn)任務(wù)。具有應(yīng)用默認(rèn)親和性的任何現(xiàn)有任務(wù)都不會受到影響岭皂。
android:excludeFromRecents="true"`從“最近使用的應(yīng)用”屏幕中排除新任務(wù)郊霎,以免用戶意外返回該任務(wù)。
val notifyIntent = Intent(this, ResultActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val notifyPendingIntent = PendingIntent.getActivity(
this, 0, notifyIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val builder = NotificationCompat.Builder(this, CHANNEL_ID).apply {
setContentIntent(notifyPendingIntent)
...
}
with(NotificationManagerCompat.from(this)) {
notify(NOTIFICATION_ID, builder.build())
}
b.添加操作按鈕
通知最多可以提供三個操作按鈕爷绘,以便用戶快速響應(yīng)书劝,例如暫停提醒或回復(fù)短信。但這些操作按鈕不得重復(fù)用戶點按通知時執(zhí)行的操作揉阎。
添加操作按鈕庄撮,請將 PendingIntent
傳遞給 addAction()
方法。這就像是設(shè)置通知的默認(rèn)點按操作毙籽,除了啟動 activity 之外,您可以執(zhí)行其他操作毡庆,例如啟動在后臺執(zhí)行作業(yè)的 BroadcastReceiver
坑赡,這樣該操作就不會中斷已經(jīng)打開的應(yīng)用。
val ACTION_SNOOZE = "snooze"
val snoozeIntent = Intent(this, MyBroadcastReceiver::class.java).apply {
action = ACTION_SNOOZE
putExtra(EXTRA_NOTIFICATION_ID, 0)
}
val snoozePendingIntent: PendingIntent =
PendingIntent.getBroadcast(this, 0, snoozeIntent, 0)
val builder = 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)
如需詳細了解如何構(gòu)建 BroadcastReceiver
以運行后臺工作么抗,請參閱廣播概覽毅否。
如果您嘗試構(gòu)建包含媒體播放按鈕的通知(例如暫停和跳過曲目),請參閱如何創(chuàng)建包含媒體控件的通知蝇刀。
注意 :在 Android 10(API 級別 29)及更高版本中螟加,如果應(yīng)用不提供自己的通知操作按鈕,平臺會自動生成通知操作按鈕吞琐。如果您不希望應(yīng)用通知顯示任何建議的回復(fù)或操作捆探,可以使用
setAllowGeneratedReplies()
和setAllowSystemGeneratedContextualActions()
選擇停用系統(tǒng)生成的回復(fù)和操作。
c.添加直接回復(fù)操作
Android 7.0(API 級別 24)中引入的直接回復(fù)操作可讓用戶直接在通知中輸入文本站粟。然后黍图,文本會在不打開 activity 的情況下傳遞給您的應(yīng)用。例如奴烙,您可以使用直接回復(fù)操作助被,讓用戶能夠在通知中回復(fù)短信或更新任務(wù)列表。
直接回復(fù)操作在通知中顯示為用于打開文本輸入的附加按鈕切诀。用戶完成輸入后揩环,系統(tǒng)會將文本響應(yīng)附加到您為通知操作指定的 intent,并將該 intent 發(fā)送到您的應(yīng)用幅虑。
添加回復(fù)按鈕
1.創(chuàng)建可添加到通知操作的 RemoteInput.Builder 實例丰滑。此類的構(gòu)造函數(shù)接受系統(tǒng)用作文本輸入鍵的字符串。您的應(yīng)用稍后使用該鍵來檢索輸入的文本翘单。
// Key for the string that's delivered in the action's intent.
private val KEY_TEXT_REPLY = "key_text_reply"
var replyLabel: String = resources.getString(R.string.reply_label)
var remoteInput: RemoteInput = RemoteInput.Builder(KEY_TEXT_REPLY).run {
setLabel(replyLabel)
build()
}
2.為回復(fù)操作創(chuàng)建 PendingIntent吨枉。
// Build a PendingIntent for the reply action to trigger.
var replyPendingIntent: PendingIntent =
PendingIntent.getBroadcast(applicationContext,
conversation.getConversationId(),
getMessageReplyIntent(conversation.getConversationId()),
PendingIntent.FLAG_UPDATE_CURRENT)
注意:如果重復(fù)使用
PendingIntent
蹦渣,用戶回復(fù)的對話可能不是他們預(yù)期的對話。您必須為每個對話提供不同的請求代碼貌亭,或者提供一個當(dāng)您對任何其他對話的回復(fù) intent 調(diào)用 equals()時不會返回true
的 intent柬唯。對話 ID 會作為 intent 的 extra 捆綁包的一部分頻繁傳遞,但在您調(diào)用equals()
時會被忽略圃庭。
3.使用 addRemoteInput() 將 RemoteInput 對象附加到操作锄奢。
// Create the reply action and add the remote input.
var action: NotificationCompat.Action =
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.
val newMessageNotification = Notification.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_message)
.setContentTitle(getString(R.string.title))
.setContentText(getString(R.string.content))
.addAction(action)
.build()
// Issue the notification.
with(NotificationManagerCompat.from(this)) {
notificationManager.notify(notificationId, newMessageNotification)
}
從回復(fù)中檢索用戶輸入
如需從通知的回復(fù)界面接收用戶輸入剧腻,請調(diào)用 RemoteInput.getResultsFromIntent()
拘央,并向其傳遞 BroadcastReceiver
收到的 Intent
:
private fun getMessageText(intent: Intent): CharSequence? {
return RemoteInput.getResultsFromIntent(intent)?.getCharSequence(KEY_TEXT_REPLY)
}
處理文本后,通過調(diào)用 NotificationManagerCompat.notify() 并使用相同的 ID 和標(biāo)記(如果使用的話)更新通知书在。如需隱藏直接回復(fù)界面灰伟,并向用戶確認(rèn)他們的回復(fù)已正確接收和處理,您必須這樣做儒旬。
// Build a new notification, which informs the user that the system
// handled their interaction with the previous notification.
val repliedNotification = Notification.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_message)
.setContentText(getString(R.string.replied))
.build()
// Issue the new notification.
NotificationManagerCompat.from(this).apply {
notificationManager.notify(notificationId, repliedNotification)
}
在處理這個新通知時栏账,請使用傳遞給接收器的 onReceive()
方法的上下文。
通過調(diào)用 setRemoteInputHistory()
將回復(fù)附加到通知底部栈源。不過挡爵,如果您要構(gòu)建即時通訊應(yīng)用,請創(chuàng)建消息式通知甚垦,并將新消息附加到對話中茶鹃。
如需了解有關(guān)即時通訊應(yīng)用通知的更多建議,請參閱即時通訊應(yīng)用最佳實踐部分艰亮。
d.添加進度條
通知可以包含動畫形式的進度指示器闭翩,向用戶顯示正在進行的操作狀態(tài)。
如果您可以估算操作在任何時間的完成進度垃杖,請調(diào)用 setProgress(max, progress, false)
以使用指示符的“確定性”形式(如圖 5 所示)男杈。第一個參數(shù)是“complete”值,例如 100调俘。第二個因素是完成程度伶棒。最后一個表示這是一個確定性進度條。
隨著操作的繼續(xù)彩库,持續(xù)使用更新后的 progress
值調(diào)用 setProgress(max, progress, false)
并重新發(fā)出通知肤无,如以下示例所示。
注意 :由于進度條要求應(yīng)用持續(xù)更新通知骇钦,因此應(yīng)使此代碼在后臺服務(wù)中運行宛渐。
...
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID);
builder.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;
builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false);
notificationManager.notify(notificationId, builder.build());
// Do the job that tracks the progress here.
// Usually, this is in a worker thread.
// To show progress, update PROGRESS_CURRENT and update the notification with:
// builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false);
// notificationManager.notify(notificationId, builder.build());
// When done, update the notification once more to remove the progress bar.
builder.setContentText("Download complete")
.setProgress(0,0,false);
notificationManager.notify(notificationId, builder.build());
操作結(jié)束時,progress 必須等于 max。您可以離開進度條以顯示操作已完成窥翩,也可以將其移除业岁。無論是哪種情況,都請更新通知文本以顯示操作已完成寇蚊。如需移除進度條笔时,請調(diào)用 setProgress(0, 0, false)。
如需顯示不確定的進度條(不指示完成百分比的進度條)仗岸,請調(diào)用 setProgress(0, 0, true)允耿。結(jié)果是,指示器的樣式與前面的進度條相同扒怖,只不過它是一個不指示完成的連續(xù)動畫较锡。在您調(diào)用 setProgress(0, 0, false) 之前,進度動畫會一直運行盗痒,然后更新通知以移除 activity 指示器蚂蕴。
請記得更改通知文本,以表明操作已完成俯邓。
注意 :如果您需要下載文件掂墓,請考慮使用
DownloadManager
,它會提供專屬通知來跟蹤下載進度看成。
e.設(shè)置系統(tǒng)范圍的類別
Android 使用預(yù)定義的系統(tǒng)范圍類別來確定當(dāng)用戶啟用勿擾模式時,是否發(fā)出給定通知干擾用戶跨嘉。
如果您的通知屬于 NotificationCompat
中定義的通知類別之一(例如 CATEGORY_ALARM
川慌、CATEGORY_REMINDER
、CATEGORY_EVENT
或 CATEGORY_CALL
)祠乃,請通過將相應(yīng)類別傳遞給 setCategory()
進行聲明:
var builder = NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
系統(tǒng)會根據(jù)這些有關(guān)通知類別的信息來決定是否在設(shè)備處于“勿擾”模式時顯示通知梦重。但是,您無需設(shè)置系統(tǒng)范圍的類別亮瓷。只有當(dāng)您的通知與 NotificationCompat 中定義的某個類別匹配時琴拧,您才應(yīng)執(zhí)行此操作。
f.顯示緊急消息
您的應(yīng)用可能需要顯示緊急的時效性消息嘱支,例如來電或響鈴的鬧鐘蚓胸。在這些情況下,您可以將全屏 intent 與通知相關(guān)聯(lián)除师。
注意 :包含全屏 intent 的通知具有非常強的干擾性沛膳,因此請務(wù)必只將此類通知用于最緊急的時效性消息。
調(diào)用通知后汛聚,用戶會看到以下某種內(nèi)容锹安,具體取決于設(shè)備的鎖定狀態(tài):
- 如果用戶的設(shè)備處于鎖定狀態(tài),系統(tǒng)會顯示全屏 activity,并覆蓋鎖定屏幕叹哭。
- 如果用戶的設(shè)備處于解鎖狀態(tài)忍宋,通知會以展開形式顯示,其中包含用于處理或關(guān)閉通知的選項风罩。
注意 :如果您的應(yīng)用以 Android 10(API 級別 29)或更高版本為目標(biāo)平臺糠排,您必須在應(yīng)用的清單文件中請求
USE_FULL_SCREEN_INTENT
權(quán)限,系統(tǒng)才能啟動與時效性通知相關(guān)聯(lián)的全屏 activity泊交。
val fullScreenIntent = Intent(this, ImportantActivity::class.java)
val fullScreenPendingIntent = PendingIntent.getActivity(this, 0,
fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT)
var builder = NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setFullScreenIntent(fullScreenPendingIntent, true)
g.設(shè)置鎖定屏幕公開范圍
如需控制鎖定屏幕中通知的詳細可見信息乳讥,請調(diào)用 setVisibility()
并指定以下值之一:
取值 | 含義 |
---|---|
VISIBILITY_PUBLIC |
在鎖定屏幕上顯示通知的完整內(nèi)容 |
VISIBILITY_SECRET |
鎖定屏幕上不會顯示通知的任何部分 |
VISIBILITY_PRIVATE |
鎖定屏幕上僅顯示基本信息,如通知圖標(biāo)和內(nèi)容標(biāo)題廓俭。未顯示通知的完整內(nèi)容 |
設(shè)置 VISIBILITY_PRIVATE
時云石,您還可以提供隱藏某些詳細信息的備用版本通知內(nèi)容。例如研乒,短信應(yīng)用可能會顯示一條通知汹忠,指出“您有 3 條新短信”,但隱藏了短信內(nèi)容和發(fā)送者雹熬。如需提供此備用通知宽菜,請先照常使用 NotificationCompat.Builder
創(chuàng)建備用通知。然后竿报,使用 setPublicVersion()
將備用通知附加到普通通知中铅乡。
注意,用戶始終可以最終控制其通知是否顯示在鎖定屏幕上烈菌,并且可以根據(jù)應(yīng)用的通知渠道控制通知阵幸。
h.更新通知
如需在發(fā)出通知后對其進行更新,請再次調(diào)用 NotificationManagerCompat.notify()
芽世,并向其傳遞您之前使用的相同 ID挚赊。如果之前的通知已關(guān)閉,系統(tǒng)會改為創(chuàng)建新通知济瓢。
您可以選擇調(diào)用 setOnlyAlertOnce()
荠割,這樣您的通知只會在用戶首次出現(xiàn)時通過聲音、振動或視覺提示來打斷用戶旺矾,而不適用于后續(xù)更新蔑鹦。
注意:Android 會在更新通知時應(yīng)用速率限制。如果您過于頻繁地發(fā)布通知的更新(不到一秒內(nèi)發(fā)布多項更新)宠漩,系統(tǒng)可能會丟棄更新举反。
i.移除通知
除非發(fā)生以下情況之一,否則通知仍然可見:
- 用戶關(guān)閉通知扒吁。
- 如果您在創(chuàng)建通知時調(diào)用了
setAutoCancel()
火鼻,用戶便會點按該通知室囊。 - 您可以針對特定通知 ID 調(diào)用
cancel()
。此方法還會刪除持續(xù)性通知魁索。 - 您調(diào)用了
cancelAll()
方法融撞,該方法將移除之前發(fā)出的所有通知。 - 如果您在創(chuàng)建通知時使用
setTimeoutAfter()
設(shè)置了超時粗蔚,則會經(jīng)過指定的時長尝偎。如果需要,您可以在指定的超時時長過去之前取消通知鹏控。
j.有關(guān)即時通訊應(yīng)用的最佳做法
為即時通訊和聊天應(yīng)用創(chuàng)建通知時致扯,請考慮此處列出的最佳實踐。
使用 MessagingStyle
從 Android 7.0(API 級別 24)開始当辐,Android 提供了專用于消息內(nèi)容的通知樣式模板抖僵。使用 NotificationCompat.MessagingStyle
類,您可以更改在通知中顯示的多個標(biāo)簽缘揪,包括會話標(biāo)題耍群、其他消息和通知的內(nèi)容視圖。
val user = Person.Builder()
.setIcon(userIcon)
.setName(userName)
.build()
val notification = NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("2 new messages with $sender")
.setContentText(subject)
.setSmallIcon(R.drawable.new_message)
.setStyle(NotificationCompat.MessagingStyle(user)
.addMessage(messages[1].getText(), messages[1].getTime(), messages[1].getPerson())
.addMessage(messages[2].getText(), messages[2].getTime(), messages[2].getPerson())
)
.build()
從 Android 9.0(API 級別 28)開始找筝,還需要使用 Person
類才能優(yōu)化通知及其頭像的呈現(xiàn)方式蹈垢。
使用 NotificationCompat.MessagingStyle
時,請執(zhí)行以下操作:
- 調(diào)用
MessagingStyle.setConversationTitle()
袖裕,為超過兩個人的群聊設(shè)置標(biāo)題曹抬。一個好的會話標(biāo)題可以是群聊的名稱,如果沒有名稱急鳄,可以是會話的參與者列表沐祷。否則,消息可能會被誤認(rèn)為屬于與會話中最新消息的發(fā)送者的一對一對話攒岛。 - 使用
MessagingStyle.setData()
方法包含圖片等媒體消息。支持模式 image/* 的 MIME 類型胞锰。
使用直接回復(fù)
直接回復(fù)可讓用戶以內(nèi)嵌方式回復(fù)消息灾锯。
- 當(dāng)用戶使用內(nèi)嵌回復(fù)操作回復(fù)后,請使用
MessagingStyle.addMessage()
更新MessagingStyle
通知嗅榕,并且不要撤消或取消通知顺饮。不取消通知可讓用戶通過通知發(fā)送多次回復(fù)。 - 如需使內(nèi)嵌回復(fù)操作與 Wear OS 兼容凌那,請調(diào)用
Action.WearableExtender.setHintDisplayInlineAction(true)
兼雄。 - 通過向通知添加歷史消息,使用
addHistoricMessage()
方法為直接回復(fù)對話提供上下文帽蝶。
啟用智能回復(fù)
- 如需啟用智能回復(fù)赦肋,請對回復(fù)操作調(diào)用
setAllowGeneratedResponses(true)
。這樣,當(dāng)通知橋接到 Wear OS 設(shè)備時佃乘,用戶就可以使用智能回復(fù)響應(yīng)囱井。智能回復(fù)響應(yīng)由完全在手表上的機器學(xué)習(xí)模型使用NotificationCompat.MessagingStyle
通知提供的上下文生成,不會將數(shù)據(jù)上傳到互聯(lián)網(wǎng)來生成響應(yīng)趣避。
添加通知元數(shù)據(jù)
- 分配通知元數(shù)據(jù)庞呕,以告知系統(tǒng)當(dāng)設(shè)備處于
Do Not Disturb mode
狀態(tài)時如何處理應(yīng)用通知。例如程帕,使用addPerson()
或setCategory(Notification.CATEGORY_MESSAGE)
方法替換“勿擾”模式住练。
2、可展開樣式的通知
基本通知通常包括標(biāo)題愁拭、一行文本以及用戶可以作為響應(yīng)執(zhí)行的操作讲逛。如需提供更多信息,您可以按照本文檔中介紹的方式應(yīng)用多個通知模板之一敛苇,創(chuàng)建可展開的大型通知妆绞。
首先,使用創(chuàng)建通知中所述的所有基本內(nèi)容構(gòu)建通知枫攀。然后括饶,使用樣式對象調(diào)用 setStyle()
,并提供與每個模板相對應(yīng)的信息来涨,如以下示例所示图焰。
a.添加大圖片
如需在通知中添加圖片,請將 NotificationCompat.BigPictureStyle
的實例傳遞給 setStyle()
蹦掐。
val notification = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.new_post)
.setContentTitle(imageTitle)
.setContentText(imageDescription)
.setStyle(NotificationCompat.BigPictureStyle()
.bigPicture(myBitmap))
.build()
若要使圖片僅在通知收起時顯示為縮略圖(如下圖所示)技羔,請調(diào)用 setLargeIcon()
并向其傳遞圖片。然后卧抗,調(diào)用 BigPictureStyle.bigLargeIcon()
并向其傳遞 null
藤滥,這樣大圖標(biāo)就會在通知展開時消失:
b.添加一大段文本
應(yīng)用 NotificationCompat.BigTextStyle
以在通知的展開內(nèi)容區(qū)域顯示文本:
val notification = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.new_mail)
.setContentTitle(emailObject.getSenderName())
.setContentText(emailObject.getSubject())
.setLargeIcon(emailObject.getSenderAvatar())
//BigTextStyle .添加一大段文本
.setStyle(NotificationCompat.BigTextStyle()
.bigText(emailObject.getSubjectAndSnippet()))
.build()
提示: 如需為文本添加格式(例如粗體、斜體社裆、換行符等)拙绊,您可以使用 HTML 標(biāo)記添加樣式。
c.創(chuàng)建收件箱樣式的通知
如果您想添加多個簡短的摘要行(例如收到的電子郵件中的摘要)泳秀,請對通知應(yīng)用 NotificationCompat.InboxStyle
标沪。這樣,您就可以添加多段內(nèi)容文本嗜傅,并且每條文本都截斷為一行金句,而不是由 NotificationCompat.BigTextStyle
提供的一行連續(xù)文本。
如需添加新行吕嘀,最多可調(diào)用 addLine()
六次违寞,如以下示例所示贞瞒。如果添加的代碼行超過 6 行,則僅顯示前 6 行坞靶。
提示 :您可以使用 HTML 標(biāo)記添加樣式(例如加粗主題)憔狞,以區(qū)分每行中的消息主題和消息內(nèi)容。
val notification = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.baseline_email_24)
.setContentTitle("5 New mails from Frank")
.setContentText("Check them out")
.setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.logo))
.setStyle(
NotificationCompat.InboxStyle()
.addLine("Re: Planning")
.addLine("Delivery on its way")
.addLine("Follow-up")
)
.build()
創(chuàng)建一組通知
從 Android 7.0(API 級別 24)開始瘾敢,您可以在一個組中顯示相關(guān)通知。例如尿这,如果您的應(yīng)用針對收到的電子郵件顯示通知簇抵,請將有關(guān)新電子郵件的所有通知放入同一個群組中,以便它們收起來射众。
如需支持較低版本碟摆,請?zhí)砑诱ㄖ撜ㄖ獙为氾@示叨橱,以匯總所有單獨的通知典蜕。通常,最好使用收件箱樣式的通知來實現(xiàn)此目的罗洗。
注意 :通知組與通知渠道組不同愉舔。
滿足以下所有條件,請使用通知組:
子通知是完整通知伙菜,可以單獨顯示轩缤,而無需通知組摘要。
-
單獨顯示子級通知有一個好處贩绕。例如:
它們是可操作的火的,具體操作特定于每條通知。
每條通知中都包含更多信息供用戶查看淑倾。
如果您的通知不符合上述條件馏鹤,不妨考慮使用新信息更新現(xiàn)有通知,或創(chuàng)建消息樣式的通知娇哆,以便在同一對話中顯示多項更新假瞬。
注意 :如果您的應(yīng)用發(fā)出 4 條或更多條通知且未指定通知組,則系統(tǒng)會在 Android 7.0 及更高版本上將這些通知自動分組迂尝。
創(chuàng)建通知組并為其添加通知
如需創(chuàng)建通知組,請為該通知組定義一個唯一標(biāo)識符字符串剪芥。然后垄开,對于您想要添加到通知組中的每條通知,調(diào)用 setGroup()
并傳入通知組名稱税肪。例如:
val GROUP_KEY_WORK_EMAIL = "com.android.example.WORK_EMAIL"
val newMessageNotification = NotificationCompat.Builder(this@MainActivity, CHANNEL_ID)
.setSmallIcon(R.drawable.new_mail)
.setContentTitle(emailObject.getSenderName())
.setContentText(emailObject.getSubject())
.setLargeIcon(emailObject.getSenderAvatar())
.setGroup(GROUP_KEY_WORK_EMAIL)
.build()
默認(rèn)情況下溉躲,系統(tǒng)會根據(jù)通知的發(fā)布時間對其進行排序榜田,但您可以通過調(diào)用 setSortKey()
更改通知順序。
如果針對某個通知組的提醒必須由其他通知處理锻梳,請調(diào)用 setGroupAlertBehavior()
箭券。例如,如果您只希望通知組的摘要發(fā)出通知疑枯,則該通知組中的所有子級都必須具有通知組提醒行為 GROUP_ALERT_SUMMARY
辩块。其他選項包括 GROUP_ALERT_ALL
和 GROUP_ALERT_CHILDREN
。
設(shè)置通知組摘要
分組通知必須有一個額外的通知來充當(dāng)通知組摘要荆永。要啟用分組通知废亭,您必須設(shè)置通知組摘要。此通知組摘要必須包含通知組中其他通知的部分文本具钥,以幫助用戶了解通知組的內(nèi)容豆村。群組摘要的顯示方式取決于 Android 版本:
在低于 7.0(API 級別 24)的 Android 版本中,由于無法顯示嵌套通知組骂删,系統(tǒng)僅顯示您的通知組摘要通知掌动,而隱藏所有其他通知。用戶可以點按群組摘要通知以打開您的應(yīng)用宁玫。
在 Android 7.0 及更高版本中粗恢,系統(tǒng)會將通知組摘要通知顯示為一組嵌套通知,并用每個分組通知的文本摘要進行標(biāo)記撬统。不會顯示您在群組摘要通知中設(shè)置的文本适滓。用戶可以展開嵌套的通知組以查看該組中的各個通知,如上圖 所示恋追。
即使較新版本的 Android 未顯示您設(shè)計的通知組摘要文本凭迹,您也始終需要手動設(shè)置摘要才能啟用分組通知。設(shè)備組摘要的行為在某些設(shè)備類型(例如穿戴式設(shè)備)上可能會有所不同苦囱。在群組摘要中設(shè)置富媒體內(nèi)容有助于在所有設(shè)備和版本上提供最佳體驗嗅绸。
如需添加通知組摘要,請按以下步驟操作:
創(chuàng)建包含通知組說明的新通知 - 通常最好使用收件箱樣式的通知來完成撕彤。
通過調(diào)用
setGroup()
將摘要通知添加到通知組中鱼鸠。通過調(diào)用
setGroupSummary(true)
指定必須將其用作通知組摘要。
// Use constant ID for notifications used as group summary.
val SUMMARY_ID = 0
val GROUP_KEY_WORK_EMAIL = "com.android.example.WORK_EMAIL"
val newMessageNotification1 = NotificationCompat.Builder(this@MainActivity, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notify_email_status)
.setContentTitle(emailObject1.getSummary())
.setContentText("You will not believe...")
.setGroup(GROUP_KEY_WORK_EMAIL)
.build()
val newMessageNotification2 = NotificationCompat.Builder(this@MainActivity, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notify_email_status)
.setContentTitle(emailObject2.getSummary())
.setContentText("Please join us to celebrate the...")
.setGroup(GROUP_KEY_WORK_EMAIL)
.build()
val summaryNotification = NotificationCompat.Builder(this@MainActivity, CHANNEL_ID)
.setContentTitle(emailObject.getSummary())
// Set content text to support devices running API level < 24.
.setContentText("Two new messages")
.setSmallIcon(R.drawable.ic_notify_summary_status)
// Build summary info into InboxStyle template.
.setStyle(NotificationCompat.InboxStyle()
.addLine("Alex Faarborg Check this out")
.addLine("Jeff Chang Launch Party")
.setBigContentTitle("2 new messages")
.setSummaryText("janedoe@example.com"))
// Specify which group this notification belongs to.
.setGroup(GROUP_KEY_WORK_EMAIL)
// Set this notification as the summary for the group.
.setGroupSummary(true)
.build()
NotificationManagerCompat.from(this).apply {
notify(emailNotificationId1, newMessageNotification1)
notify(emailNotificationId2, newMessageNotification2)
notify(SUMMARY_ID, summaryNotification)
}
摘要通知 ID 必須保持不變羹铅,以便僅發(fā)布一次蚀狰,以便日后在摘要信息發(fā)生更改時進行更新。后續(xù)向該組添加內(nèi)容會導(dǎo)致更新現(xiàn)有摘要职员。
自動分組
在 Android 7.0(API 級別 24)及更高版本中麻蹋,如果您的應(yīng)用發(fā)送了 4 條或更多通知,并且未指定組鍵或組摘要焊切,系統(tǒng)可能會自動將這些通知分為一組扮授。系統(tǒng)會自動分組顯示通知芳室,并附帶通知組摘要通知,該摘要通知會標(biāo)有某些分組通知的文本片段刹勃。與手動分組的通知一樣堪侯,用戶可以展開此摘要通知以查看各個通知。
自動分組行為在某些設(shè)備類型上可能會有所不同荔仁。為了在所有設(shè)備和版本上提供最佳體驗伍宦,如果您知道通知必須分組,請指定組鍵和組摘要咕晋,以確保這些通知已分組雹拄。
d.在通知中顯示對話
應(yīng)用 NotificationCompat.MessagingStyle
可顯示任意數(shù)量的人之間的依序消息丽惭。這非常適合即時通訊應(yīng)用蔚携,因為它通過單獨處理發(fā)送者名稱和消息文本來為每條消息提供一致的布局捕传,并且每條消息可以多行果复。
如需添加新消息军俊,請調(diào)用 addMessage()
诲侮,并傳遞消息文本饶辙、接收時間和發(fā)送者姓名耳幢。您還可以將此信息作為 NotificationCompat.MessagingStyle.Message
對象傳遞
使用 NotificationCompat.MessagingStyle
時模暗,為 setContentTitle()
和 setContentText()
指定的任何值都會被忽略禁悠。
您可以調(diào)用 setConversationTitle()
來添加顯示在對話上方的標(biāo)題。這可以是用戶創(chuàng)建的群組名稱兑宇;如果沒有具體名稱碍侦,也可以是對話中的參與者列表。請勿為一對一聊天設(shè)置對話標(biāo)題隶糕,因為系統(tǒng)會利用此字段的存在來提示對話是一個群組瓷产。
此樣式僅適用于搭載 Android 7.0(API 級別 24)及更高版本的設(shè)備。如前所述枚驻,使用兼容性庫 (NotificationCompat
) 時濒旦,具有 MessagingStyle
的通知會自動回退為受支持的展開式通知樣式。
為聊天對話創(chuàng)建此類通知時再登,請添加直接回復(fù)操作尔邓。
e.使用媒體控件創(chuàng)建通知
注意 :使用 AndroidX Media3 時,系統(tǒng)會自動創(chuàng)建媒體通知锉矢。
應(yīng)用 MediaStyleNotificationHelper.MediaStyle
可顯示媒體播放控件和曲目信息梯嗽。
在構(gòu)造函數(shù)中指定關(guān)聯(lián)的 MediaSession
。這樣沽损,Android 就可以顯示有關(guān)您媒體的正確信息灯节。
調(diào)用 addAction()
最多五次,最多可以顯示五個圖標(biāo)按鈕。調(diào)用 setLargeIcon()
可設(shè)置專輯封面显晶。
與其他通知樣式不同,MediaStyle
還允許您通過指定三個操作按鈕(這些按鈕也會顯示在收起視圖中)來修改收起后尺寸的內(nèi)容視圖壹士。為此磷雇,請向 setShowActionsInCompactView()
提供操作按鈕索引。
val notification = NotificationCompat.Builder(context, CHANNEL_ID)
// Show controls on lock screen even when user hides sensitive content.
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setSmallIcon(R.drawable.ic_stat_player)
// Add media control buttons that invoke intents in your media service
.addAction(R.drawable.ic_prev, "Previous", prevPendingIntent) // #0
.addAction(R.drawable.ic_pause, "Pause", pausePendingIntent) // #1
.addAction(R.drawable.ic_next, "Next", nextPendingIntent) // #2
// Apply the media style template.
.setStyle(MediaStyleNotificationHelper.MediaStyle(mediaSession)
.setShowActionsInCompactView(1 /* #1: pause button \*/))
.setContentTitle("Wonderful music")
.setContentText("My Awesome Band")
.setLargeIcon(albumArtBitmap)
.build()
注意 :使用
MediaStyleNotificationHelper.MediaStyle
創(chuàng)建的通知的類別會設(shè)置為CATEGORY_TRANSPORT
唯笙,除非您使用setCategory()
設(shè)置其他類別。
f.其他資源
如需詳細了解 MediaStyle
和展開式通知盒使,請參閱以下參考文檔崩掘。
3、通話樣式的通知
在 Android 12.0(API 級別 31)及更高版本中少办,系統(tǒng)提供 CallStyle
通知模板苞慢,以將來電通知與其他類型的通知區(qū)分開來。使用此模板可以創(chuàng)建來電或正在進行的通話通知英妓。此模板支持大格式通知挽放,其中包含來電信息和所需的操作(如接聽或拒接來電)。
由于來電和正在進行的通話屬于高優(yōu)先級事件蔓纠,因此這些通知在通知欄中會獲得最高優(yōu)先級辑畦。此排名還使系統(tǒng)能夠?qū)⑦@些優(yōu)先級較高的通話轉(zhuǎn)接到其他設(shè)備。
CallStyle 通知模板包含以下必需操作:
- 接聽或拒接來電腿倚。
- 掛斷當(dāng)前通話纯出。
- 接聽或掛斷電話以過濾來電。
所需操作會以 intent 的形式傳遞敷燎,例如后面幾部分中的 hangupIntent
和 answerIntent
暂筝。其中每個字段都是對系統(tǒng)維護的令牌的引用。令牌是一個輕量級對象懈叹,可以在不同應(yīng)用和進程之間傳遞乖杠。系統(tǒng)負責(zé)管理令牌的生命周期,并確保即使創(chuàng)建 PendingIntent
的應(yīng)用不再運行澄成,它仍然可用胧洒。如果您為另一個應(yīng)用提供 PendingIntent
,即表示您授予該應(yīng)用執(zhí)行指定操作的權(quán)限墨状,如拒絕或接聽卫漫。即使創(chuàng)建該 intent 的應(yīng)用當(dāng)前未運行,也會授予此權(quán)限肾砂。如需了解詳情列赎,請參閱 PendingIntent
的參考文檔。
從 Android 14(API 級別 34)開始镐确,您可以將來電通知配置為不可關(guān)閉包吝。為此饼煞,請通過 Notification.Builder#setOngoing(true)
使用 Notification.FLAG_ONGOING_EVENT
的 CallStyle
通知。
// Create a new call, setting the user as the caller.
val incomingCaller = Person.Builder()
.setName("Jane Doe")
.setImportant(true)
.build()
來電
使用 forIncomingCall() 方法為來電創(chuàng)建通話樣式通知诗越。
// Create a call style notification for an incoming call.
val builder = Notification.Builder(context, CHANNEL_ID)
.setContentIntent(contentIntent)
.setSmallIcon(smallIcon)
.setStyle(
Notification.CallStyle.forIncomingCall(caller, declineIntent, answerIntent))
.addPerson(incomingCaller)
當(dāng)前通話
使用 forOngoingCall() 方法為正在進行的通話創(chuàng)建通話樣式通知砖瞧。
// Create a call style notification for an ongoing call.
val builder = Notification.Builder(context, CHANNEL_ID)
.setContentIntent(contentIntent)
.setSmallIcon(smallIcon)
.setStyle(
Notification.CallStyle.forOngoingCall(caller, hangupIntent))
.addPerson(second_caller)
過濾來電
使用 forScreeningCall() 方法可創(chuàng)建用于過濾來電的調(diào)用樣式通知。
// Create a call style notification for screening a call.
val builder = Notification.Builder(context, CHANNEL_ID)
.setContentIntent(contentIntent)
.setSmallIcon(smallIcon)
.setStyle(
Notification.CallStyle.forScreeningCall(caller, hangupIntent, answerIntent))
.addPerson(second_caller)
實現(xiàn)與更多 Android 版本的兼容性
將 API 版本 30 或更低版本的 CallStyle
通知與前臺服務(wù)相關(guān)聯(lián)嚷狞,以便為它們分配 API 級別 31 或更高級別中所指定的最高排名块促。此外,API 版本 30 或更低版本上的 CallStyle
通知可以使用 setColorized()
方法將通知標(biāo)記為彩色床未,從而達到類似排名竭翠。
將 Telecom API 與 CallStyle
通知搭配使用。如需了解詳情薇搁,請參閱 Telecom 框架概覽斋扰。
4、具有時效性的通知
在某些情況下只酥,您的應(yīng)用可能需要緊急吸引用戶的注意力褥实,例如鬧鐘正在響鈴或有來電時。在以搭載 Android 9(API 級別 28)或更低版本的設(shè)備為目標(biāo)平臺的應(yīng)用中裂允,您可以通過在應(yīng)用在后臺運行時啟動 activity 來處理此問題损离。本文檔介紹了如何在搭載 Android 10(API 級別 29)到 Android 13(API 級別 33)的設(shè)備上實現(xiàn)此行為。
添加 POST_NOTIFICATIONS 權(quán)限
從 Android 13 開始绝编,將以下行添加到 AndroidManifest.xml 文件中:
<manifest ...>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<application ...>
...
</application>
</manifest>
創(chuàng)建通知渠道
創(chuàng)建通知渠道以正確顯示通知僻澎,并讓用戶在應(yīng)用設(shè)置中管理通知。如需詳細了解通知渠道十饥,請參閱創(chuàng)建和管理通知渠道窟勃。
在 Application
類的 onCreate
方法中創(chuàng)建通知渠道:
class DACapp : Application() {
override fun onCreate() {
super.onCreate()
val channel = NotificationChannel(
CHANNEL_ID,
"High priority notifications",
NotificationManager.IMPORTANCE_HIGH
)
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
當(dāng)用戶首次運行您的應(yīng)用時,他們會在應(yīng)用的應(yīng)用信息系統(tǒng)屏幕中看到如圖 1 所示的內(nèi)容:
管理通知權(quán)限
從 Android 13 開始秉氧,請求通知權(quán)限后才能向用戶顯示通知。
val permissionLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.RequestPermission(),
onResult = { hasNotificationPermission = it }
)
...
Button(
onClick = {
if (!hasNotificationPermission) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
}
}
},
) {
Text(text = "Request permission")
}
創(chuàng)建高優(yōu)先級通知
創(chuàng)建通知時蜒秤,請?zhí)砑用枋鲂詷?biāo)題和消息汁咏。
private fun showNotification() {
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notificationBuilder =
NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.baseline_auto_awesome_24)
.setContentTitle("HIGH PRIORITY")
.setContentText("Check this dog puppy video NOW!")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_RECOMMENDATION)
notificationManager.notify(666, notificationBuilder.build())
}
向用戶顯示通知
Button(onClick = { showNotification() }) {
Text(text = "Show notification")
}
持續(xù)性通知
當(dāng)您向用戶顯示通知時,他們可以確認(rèn)或關(guān)閉應(yīng)用的提醒作媚。例如攘滩,用戶可以接聽或拒絕來電。
注意 :當(dāng)用戶使用設(shè)備時纸泡,系統(tǒng)界面可能會顯示浮動通知漂问,而不是啟動全屏 intent。
如果您的通知正在進行(例如來電),請將該通知與前臺服務(wù)相關(guān)聯(lián)蚤假。以下代碼段展示了如何顯示與前臺服務(wù)關(guān)聯(lián)的通知:
// Provide a unique integer for the "notificationId" of each notification.
startForeground(notificationId, notification)
5栏饮、自定義樣式通知
為了使通知在不同的 Android 版本上呈現(xiàn)最佳效果,請使用標(biāo)準(zhǔn)通知模板來構(gòu)建通知磷仰。如果您想在通知中提供更多內(nèi)容抡爹,不妨考慮使用某個可展開的通知模板。
不過芒划,如果系統(tǒng)模板無法滿足您的需求,您可以使用自己的通知布局欧穴。
注意 :使用自定義通知布局時民逼,請?zhí)貏e注意確保您的自定義布局適用于不同的設(shè)備屏幕方向和分辨率。雖然此建議適用于所有界面布局涮帘,但對于通知尤為重要拼苍,因為抽屜式通知欄中的空間有限。自定義通知布局的可用高度取決于 Android 版本调缨。在某些版本中疮鲫,收起視圖布局可低至 48 dp,浮動視圖布局可低至 88 dp弦叶,展開視圖布局可低至 252 dp俊犯。
為內(nèi)容區(qū)域創(chuàng)建自定義布局
如果您需要自定義布局,可以將 NotificationCompat.DecoratedCustomViewStyle
應(yīng)用于通知伤哺。借助此 API燕侠,您可以為通常由標(biāo)題和文本內(nèi)容占據(jù)的內(nèi)容區(qū)域提供自定義布局,同時仍對通知圖標(biāo)立莉、時間戳绢彤、子文本和操作按鈕使用系統(tǒng)裝飾。
此 API 的工作方式與可展開的通知模板類似蜓耻,都是基于基本通知布局構(gòu)建茫舶,如下所示:
- 使用
NotificationCompat.Builder
構(gòu)建基本通知。 - 調(diào)用
setStyle()
刹淌,并向其傳遞NotificationCompat.DecoratedCustomViewStyle
的實例饶氏。 - 將自定義布局膨脹為
RemoteViews
的實例。 - 調(diào)用
setCustomContentView()
以設(shè)置收起后通知的布局芦鳍。 - 您還可以選擇調(diào)用
setCustomBigContentView()
嚷往,為展開式通知設(shè)置不同的布局。
注意 :如果您要為媒體播放控件創(chuàng)建自定義通知柠衅,請遵循相同的建議皮仁,但請改用 NotificationCompat.DecoratedMediaCustomViewStyle 類。
準(zhǔn)備布局
需要使用 small 和 large 布局。在此示例中贷祈,small 布局可能如下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/notification_title"
style="@style/TextAppearance.Compat.Notification.Title"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:text="Small notification, showing only a title" />
</LinearLayout>
large 布局可能如下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="300dp"
android:orientation="vertical">
<TextView
android:id="@+id/notification_title"
style="@style/TextAppearance.Compat.Notification.Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Large notification, showing a title and a body." />
<TextView
android:id="@+id/notification_body"
style="@style/TextAppearance.Compat.Notification.Line2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="This is the body. The height is manually forced to 300dp." />
</LinearLayout>
構(gòu)建并顯示通知
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// Get the layouts to use in the custom notification.
val notificationLayout = RemoteViews(packageName, R.layout.notification_small)
val notificationLayoutExpanded = RemoteViews(packageName, R.layout.notification_large)
// Apply the layouts to the notification.
val customNotification = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setStyle(NotificationCompat.DecoratedCustomViewStyle())
.setCustomContentView(notificationLayout)
.setCustomBigContentView(notificationLayoutExpanded)
.build()
notificationManager.notify(666, customNotification)
注意趋急,通知的背景顏色可能因設(shè)備和版本而異。在自定義布局中势誊,對文本應(yīng)用 TextAppearance_Compat_Notification 樣式呜达,對標(biāo)題應(yīng)用 TextAppearance_Compat_Notification_Title 等支持庫樣式,如以下示例所示粟耻。這些樣式會根據(jù)顏色變化進行調(diào)整查近,因此您最終不會出現(xiàn)黑底白字或白底文字的情況。
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="@string/notification_title"
android:id="@+id/notification_title"
style="@style/TextAppearance.Compat.Notification.Title" />
避免在 RemoteViews 對象上設(shè)置背景圖片挤忙,否則文字可能會無法讀取霜威。
通知超時時間結(jié)束后戈泼,通知僅會顯示在系統(tǒng)欄中
創(chuàng)建完全自定義的通知布局
注意 :以 Android 12(API 級別 31)或更高版本為目標(biāo)平臺的應(yīng)用無法創(chuàng)建完全自定義的通知。相反赏僧,系統(tǒng)會應(yīng)用與
Notification.DecoratedCustomViewStyle
的行為幾乎完全相同的標(biāo)準(zhǔn)模板大猛。
如果您不想使用標(biāo)準(zhǔn)通知圖標(biāo)和標(biāo)題裝飾通知,請按照上述步驟操作淀零,但不要調(diào)用 setStyle()挽绩。
注意: 我們不建議使用未經(jīng)修飾的通知,因為這種通知與其他通知不匹配驾中,并且在對通知區(qū)域應(yīng)用了不同樣式的設(shè)備上可能導(dǎo)致嚴(yán)重的布局兼容性問題琼牧。