一.前言
在如今五花八门的 app
中,从手机上方弹出的通知消息可谓随处可见,因此在 android
开发中掌握 Notification
知识点是很有必要的。
二.Notification基本介绍
在这里借用官方文档中的一张图
由此可见,构成一个通知的基本要素有6点:
1.小图标,通常和应用图标一样
2.应用名称(系统提供)
3.时间戳,用来显示通知发出的时刻
4.大图标
5.通知标题
6.通知文本内容
这是比较常见的样式,后面还会提到其他通知样式。
那我们先来试试上边这种最简单的通知吧。
三.简单Notification的创建并显示
首先来创建一条通知,将其中的基本元素给搭建好
val builder = NotificationCompat.Builder(this, channelId).apply {
//设置通知标题
setContentTitle("通知")
//设置文本内容
setContentText("这是一条悬浮通知")
//设置小图标
setSmallIcon(R.drawable.ic_baseline_accessibility_new_24)
//true 表示户点按通知后自动移除通知
setAutoCancel(true)
//设置优先级
priority = NotificationCompat.PRIORITY_HIGH
}
其中的 setPriority()
是用于确定通知在 Android 7.1
和 更低版本
上的干扰程度。换句话说,就是显示通知的优先级。
优先级分为:
PRIORITY_MIN
,PRIORITY_LOW
,PRIORITY_DEFAULT
,PRIORITY_HIGH
,PRIORITY_MAX
。
Google
建议只有非常重要的通知或者需要用户回复的通知才使用PRIORITY_HIGH
和PRIORITY_MAX
。但国内的很多应用不管什么通知,都要弹出来烦你一下,用户体验真的很差,所以请大家考虑自己的通知是否真的重要。
而在 Android 8.0
以后,都是需要设置 通知渠道
的,否则通知不会生效。
首先通过向 createNotificationChannel()
传递 NotificationChannel
的实例在系统中注册应用的通知渠道。
//创建 NotificationChannel 实例
val channel = NotificationChannel(channelId, "name", NotificationManager.IMPORTANCE_HIGH)
val notificationManager =
this.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
//在系统中注册通知渠道
notificationManager.createNotificationChannel(channel)
IMPORTANCE_HIGH
相当于高版本后代替了 PRIORITY_HIGH
。
这时,我们就在系统中成功注册了通知渠道,完成了关键性的一步,我们可以看到应用设置中多了我们刚刚建立的名为 name
的通知渠道。
最后就可以显示出一条最简单的通知了,但是 notificationId
一定要记住, 因为后期取消和更新通知,都要用到此id。
notificationManager.notify(notificationId, builder.build())
注:如果按照上述操作依然无法弹出通知,请在应用详情中将 横幅
选项选中。
此外,如果想让您的应用在点击后发生响应,如跳转到指定页面,请在创建 builder
的时候使用 setContentIntent()
。
//创建 intent 实现跳转
val intent = Intent(this, MainActivity::class.java)
//0 是 requestCode(请求码)
//如果要想在 intent 中传递数据并及时更新,一定要保证每次请求码都需要不同!!
//并且标明 FLAG 为 FLAG_IMMUTABLE
val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)
val builder = NotificationCompat.Builder(this, channelId).apply {
....
setContentIntent(pendingIntent)
}
PendingIntent
是 Intent
的封装,它自带一个 Context
对象,通常用来完成未来发生的意图,而 Intent
是即时启动,随 activity
的消失而消失。它主要与 intent
配合使用, 用来启动一些组件,从 PendingIntent
的三种创建方法就能看出:
PendingIntent.getActivity()
,PendingIntent.getService()
,PendingIntent.getBroadcast()
。
如果我们想在后台定时发起通知,通常选择 PendingIntent.getBroadcast()
,下面的回复通知中,我们将会用到。而在这里我们说要实现界面跳转,当然就选择 PendingIntent.getActivity()
。
三.其他样式的Notification
其实大多时候上面那一种通知已经够用了,下面再提提其它样式的通知吧。
1.展开式通知
val builder = NotificationCompat.Builder(this, channelId).apply {
....
.setStyle(NotificationCompat.BigTextStyle()
.bigText(getText)
}
在展开前和一般的 Notification
一样:
但是右上方有一个箭头可以展开,我们看到这里有更多的文字内容。
2.带有输入框的通知
这种通知,只需要在最开始的那种通知上,加入一个输入框即可
// KEY -- 在回复操作中 intent 存储文本内容的键
val remoteInput = RemoteInput.Builder(KEY).run {
setLabel("回复")
build()
}
//设置回复图标并将创建好的 RemoteInput 设置上去
val action = NotificationCompat
.Action.Builder(R.drawable.ic_baseline_4k_24, "回复", replyPendingIntent)
.addRemoteInput(remoteInput).build()
}
上述的 replyPendingIntent
创建方式和之前的 PendingIntent
一样,只不过我们回复的消息文本用 put()
储存到里面,而上面说到的 KEY
就是这个文本值的键。
val builder = NotificationCompat.Builder(this, channelId).apply {
....
setAction()
这样一来就可以看效果了:
这样一来,我们不需要打开应用也能即时回对方消息了。但是对方怎么收到我们发出去的通知呢?
还记得上面说到的 replyPendingIntent
吗?我们通过它向广播传递过去了附带文本信息的intent
,这时候我们就可以在广播中的 onReceive()
中收到这个 intent
了,然后就可以用 getResultFromIntent()
拿到文本内容了。
private fun getMessageText(intent: Intent): CharSequence? {
return RemoteInput.getResultsFromIntent(intent)?.getCharSequence(KEY)
}