目录
- 创建通知渠道
- 初始化通知
- 显示通知
- 显示图片通知
- 通知点击
- PendingIntent.getBroadcast
- PendingIntent.getActivity
- Android12之PendingIntent特性
- 配合WorkManager发送延迟通知
- Android13 通知权限
在Android应用的开发中,必然会遇上通知的开发需求,本文主要讲一下Android中的通知 Notification的简单基本使用,主要包含创建通知渠道、初始化通知、显示通知、显示图片通知、通知点击、以及配合WorkManager发送延迟通知。
创建通知渠道
首先,创建几个常量和变量,其中渠道名是会显示在手机设置-通知里app对应展示的通知渠道名称,一般基于通知作用取名。
companion object {
//渠道Id
private const val CHANNEL_ID = "渠道Id"
//渠道名
private const val CHANNEL_NAME = "渠道名-简单通知"
//渠道重要级
private const val CHANNEL_IMPORTANCE = NotificationManager.IMPORTANCE_DEFAULT
}
private lateinit var context: Context
//Notification的ID
private var notifyId = 100
private lateinit var manager: NotificationManager
private lateinit var builder: NotificationCompat.Builder
然后获取系统通知服务,创建通知渠道,其中因为通知渠道是Android8.0才有的,所以增加一个版本判断:
//获取系统通知服务
manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
//创建通知渠道,Android8.0及以上需要
createChannel()
private fun createChannel() {
//创建通知渠道,Android8.0及以上需要
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
return
}
val notificationChannel = NotificationChannel(
CHANNEL_ID,
CHANNEL_NAME,
CHANNEL_IMPORTANCE
)
manager.createNotificationChannel(notificationChannel)
}
初始化通知
先生成NotificationCompat.Builder,然后初始化通知Builder的通用配置:
builder = NotificationCompat.Builder(context.applicationContext, CHANNEL_ID)
initNotificationBuilder()
/**
* 初始化通知Builder的通用配置
*/
private fun initNotificationBuilder() {
builder
.setAutoCancel(true) //设置这个标志当用户单击面板就可以让通知自动取消
.setSmallIcon(R.drawable.ic_reminder) //通知的图标
.setWhen(System.currentTimeMillis()) //通知产生的时间,会在通知信息里显示
.setDefaults(Notification.DEFAULT_ALL)
}
此外builder还有setVibrate、setSound、setStyle等方法,按需配置即可。
显示通知
给builder设置需要通知需要显示的title和content,然后通过builder.build()生成生成通知Notification,manager.notify()方法将通知发送出去。
fun configNotificationAndSend(title: String, content: String){
builder.setContentTitle(title)
.setContentText(content)
val notification = builder.build()
//发送通知
manager.notify(notifyId, notification)
//id自增
notifyId++
}
最简单的通知显示至此上面三步就完成了。
效果如下图:
显示图片通知
当通知内容过多一行展示不下时,可以通过设置
builder.setStyle(NotificationCompat.BigTextStyle().bigText(content)) //设置可以显示多行文本
这样通知就能收缩和展开,显示多行文本。
另外setStyle还可以设置图片形式的通知:
setStyle(NotificationCompat.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(resources,R.drawable.logo)))//设置图片样式
效果如下图:
通知点击
目前为止的通知还只是显示,因为设置了builder.setAutoCancel(true),点击通知之后通知会自动消失,除此之外还没有其他操作。
给builder设置setContentIntent(PendingIntent)就能有通知点击之后的其他操作了。PendingIntent可以看作是对Intent的一个封装,但它不是立刻执行某个行为,而是满足某些条件或触发某些事件后才执行指定的行为。PendingIntent获取有三种方式:Activity、Service和BroadcastReceiver获取。通过对应方法PendingIntent.getActivity、PendingIntent.getBroadcast、PendingIntent.getService就能获取。
这里就示例一下PendingIntent.getBroadcast和PendingIntent.getActivity
PendingIntent.getBroadcast
首先创建一个BroadcastReceiver:
class NotificationHandleReceiver : BroadcastReceiver() {
companion object {
const val NOTIFICATION_HANDLE_ACTION = "notification_handle_action"
const val NOTIFICATION_LINK = "notificationLink"
const val TAG = "NotificationReceiver"
}
override fun onReceive(context: Context, intent: Intent?) {
if (intent?.action == NOTIFICATION_HANDLE_ACTION) {
val link = intent.getStringExtra(NOTIFICATION_LINK)
}
}
}
别忘了在清单文件中还需要静态注册BroadcastReceiver:
<receiver
android:name=".NotificationHandleReceiver"
android:exported="false">
<intent-filter>
<action android:name="notification_handle_action" />
</intent-filter>
</receiver>
然后创建一个上面BroadcastReceiver的Intent,在intent.putExtra传入相应的点击通知之后需要识别的操作:
fun generateDefaultBroadcastPendingIntent(linkParams: (() -> String)?): PendingIntent {
val intent = Intent(NotificationHandleReceiver.NOTIFICATION_HANDLE_ACTION)
intent.setPackage(context.packageName)
linkParams?.let {
val params = it.invoke()
intent.putExtra(NotificationHandleReceiver.NOTIFICATION_LINK, params)
}
return PendingIntent.getBroadcast(
context,
notifyId,
intent,
PendingIntent.FLAG_IMMUTABLE
)
}
这样生成的PendingIntent再builder.setContentIntent(pendingIntent),在我们点击通知之后,NotificationHandleReceiver的onReceive里就会收到信息了,根据信息处理后续操作即可。
PendingIntent.getActivity
Activity的PendingIntent用于跳转到指定activity,创建一个跳转activity的Intent(同普通的页面跳转的Intent),也是同上面在intent.putExtra传入相应的点击通知之后需要识别的操作:
val intent = Intent(this, XXXX::class.java).apply {
putExtra("title", title).putExtra("content", content)
}
return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
也是这样生成的PendingIntent再builder.setContentIntent(pendingIntent),在我们点击通知之后,就会跳转到对应的activity页面,然后intent里就会收到信息了,根据信息处理后续操作即可。
Android12之PendingIntent特性
查看上面关于Android12的特性
在Android12平台上有关于PendingIntent的两点特性:
一是待处理 intent 可变性,必须为应用创建的每个PendingIntent
对象指定可变性,这也是上面创建PendingIntent时需要设置flag为PendingIntent.FLAG_IMMUTABLE。
二是通知 trampoline 限制,以 Android 12 或更高版本为目标平台的应用无法从用作通知 trampoline 的服务或广播接收器中启动 activity。换言之,当用户点按通知或通知中的操作按钮时,您的应用无法在服务或广播接收器内调用startActivity()
。所以当需要点击通知实现activity跳转时,需要使用PendingIntent. getActivity,而不是使用PendingIntent.getBroadcast,然后在BroadcastReceiver里实现activity跳转,后者方式在Android 12 或更高版本为目标平台的应用中将被限制。
配合WorkManager发送延迟通知
配合上WorkManager,就能实现发送延迟通知,主要是通过OneTimeWorkRequest的延迟特性。
创建一个延迟的OneTimeWorkRequest,加入WorkManager队列中:
fun sendWorkRequest(
context: Context,
reminderId: Int,
title: String,
content: String,
link: String,
triggerTime: Long
): OneTimeWorkRequest {
val duration = triggerTime - System.currentTimeMillis()
val data =
Data.Builder().putInt(REMINDER_WORKER_DATA_ID, reminderId).putString(REMINDER_WORKER_DATA_TITLE, title)
.putString(REMINDER_WORKER_DATA_CONTENT, content).putString(REMINDER_WORKER_DATA_LINK, link)
.build()
val uniqueWorkName =
"reminderData_${reminderId}"
val request = OneTimeWorkRequest.Builder(ReminderWorker::class.java)
.setInitialDelay(duration, TimeUnit.MILLISECONDS)
.setInputData(data)
.build()
WorkManager.getInstance(context)
.enqueueUniqueWork(uniqueWorkName, ExistingWorkPolicy.REPLACE, request)
return request
}
然后在doWork方法中拿到数据进行我们上面的通知发送显示即可。具体关于OneTimeWorkRequest的使用在本文中就不详细说明了。当需要发送延迟通知时,知道可以通过配合WorkManager实现。
Android13 通知权限
在目前最新的Android 13(API 级别 33)上对于通知增加了权限限制,具体可看官方描述: