文章默认大家会创建消息通知
消息通知在Android 8.0以上(targetSdkVersion大于等于26)的设备中,
- 添加了NotificationChannel(通知渠道)的概念,每个消息通知必须依附于通知渠道
过期了NotificationCompat.Builder(Context context) 方法,统一使用NotificationCompat.Builder(Context context, String channelId) 方法获取创建Notification的Bulider:- 修改了设置通知信息优先级和多媒体的方式
NotificationChannel(String id, CharSequence name, int importance)
8.0创建消息通知的正确姿势:
创建通知
val pushDataBean = 你的数据源
val mNotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
//创建通知
val mBuilder = NotificationCompat.Builder(context, AppConfig.NOTIFICATION_CHANNEL)
.setSmallIcon(R.drawable.ic_logo)
.setContentTitle(pushDataBean.text)
.setContentText(pushDataBean.title)
.setStyle(
NotificationCompat
.BigTextStyle()
.setBigContentTitle(pushDataBean.title)
.bigText(pushDataBean.text)
)
.setOngoing(false)
.setAutoCancel(true)
创建通知channel和配置通知消息
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(AppConfig.NOTIFICATION_CHANNEL, AppConfig.NOTIFICATION_CHANNEL,
//设置优先级
NotificationManager.IMPORTANCE_HIGH)
//设置在渠道信息
channel.name = AKApplication.instance.applicationContext.getString(R.string.notify_channel_name)
channel.description = AKApplication.instance.applicationContext.getString(R.string.notify_channel_description)
//绕过请勿打扰
channel.setBypassDnd(true)
//设置在锁屏界面上显示这条通知
channel.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
channel.setShowBadge(true)
//设置呼吸灯
channel.enableLights(true)
channel.lightColor = Color.GREEN
//设置震动
if (pushDataBean.is_vibrate) {
channel.enableVibration(true)
channel.vibrationPattern = longArrayOf(100, 400, 100)
}
//设置铃声
if (pushDataBean.is_ring) {
//默认有铃声
channel.setSound(null, null)
}
mNotificationManager.createNotificationChannel(channel)
} else {
//设置优先级
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//8.0以下 && 7.0及以上 设置优先级
mBuilder.priority = NotificationManager.IMPORTANCE_HIGH
} else {
mBuilder.priority = NotificationCompat.PRIORITY_HIGH
}
//设置多媒体
if (pushDataBean.is_vibrate && pushDataBean.is_ring) {
mBuilder.setDefaults(Notification.DEFAULT_ALL)
} else if (pushDataBean.is_vibrate) {
//设置震动
mBuilder.setDefaults(Notification.DEFAULT_VIBRATE)
} else if (pushDataBean.is_ring) {
//设置铃声
mBuilder.setDefaults(Notification.DEFAULT_SOUND)
}
}
这里需要注意的是
- channel配置需要在createNotificationChannel(channel)之前配置完成,一旦create就无法改变
- channel的name和description会在设置页面显示
被创建过的channel无法进行改变,包括声音震动配置- 国产手机多媒体设置不一定会生效,需要在设置页面进行多媒体的相关配置
设置点击事件并发送通知
//设置pendingIntent
val intent = Intent(context, NotificationClickReceiver::class.java)
intent.putExtra(KeySet.I_NOTIFICATION_EXTRA, dataString)
val pendingIntent = PendingIntent.getBroadcast(context, DateUtils.instance.getNowSeconds().toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT)
mBuilder.setContentIntent(pendingIntent)
//发送通知
mNotificationManager.notify(DateUtils.instance.getNowSeconds().toInt(), mBuilder.build())
NotificationClickReceiver接收广播类
class NotificationClickReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val data = intent?.getStringExtra(KeySet.I_NOTIFICATION_EXTRA)
//处理点击消息
}
}
不要忘记在清单文件中注册广播消息
<receiver android:name=".receiver.NotificationClickReceiver" />
要点
获取PendingIntent的方法:
- getActivity()
- getActivities()
- getBroadcast()
- getService()
- getForegroundService()
这些获取方法分别对应了Activity、Broadcast、Service,根据自己的具体情况选择;参数都是四个:
- Context
- requestCode:请求码
- Intent:请求意图用以指明启动类及数据传递
- flags:标志位
flags与我们传递数据息息相关:
- FLAG_CANCEL_CURRENT:如果已经获取到一个相同的PendingIntent对象,会先将获取的PendingIntent取消,然后重新生成一个PendingIntent对象。
- FLAG_NO_CREATE:如果当前系统中不存在相同的PendingIntent对象,系统将不会创建该PendingIntent对象而是直接返回null,如果之前设置过,这次就能获取到。
- FLAG_ONE_SHOT:该PendingIntent只作用一次。在该PendingIntent对象通过send()方法触发过后,PendingIntent将自动调用cancel()进行销毁,那么如果你再调用send()方法的话,系统将会返回一个SendIntentException。
- FLAG_UPDATE_CURRENT:如果系统中有一个和你描述的PendingIntent相等的PendingInent,将复用该PendingIntent对象,但是会使用新的Intent来更新之前PendingIntent中的Intent对象数据,例如更新Intent中的Extras
两个PendingIntent相等是指它们的operation一样, 且其它们的Intent的action, data, categories, components和flags都一样。但是它们的Intent的Extra可以不一样。
一般来说我们会使用FLAG_UPDATE_CURRENT更新消息通知中的数据Extras
这里分两种情况,如果我们用相同的PendingIntent,更新数据的Extras会在原有的通知消息里进行更新,而不会新建一个消息通知展示消息;如果需要多条消息并列展示,则需要不同的PendingIntent(设置不同的requestCode即可)