Android通知——Notification

创建通道

在显示通知之前必须先设置通道,这是必须前提。
可以在此对此通道的通知进行基本的设置,例如是否显示呼吸灯、是否震动、优先级等。

代码大概长这样:

/*** 创建通知渠道(8.0后新增,必须)* 应该再应用启动时就自己支持创建渠道,否则收不到通知,可以重复创建*/
private fun createNotificationChannel() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {val name = "测试通知"val descriptionText = "测试通知的渠道"val importance = NotificationManager.IMPORTANCE_DEFAULTval channel =NotificationChannel(CHANNEL_ID_NOTIFICATION_BASIC, name, importance).apply {description = descriptionTextenableLights(false)enableVibration(false)vibrationPattern = LongArray(0)setSound(null, null)}notificationManager.createNotificationChannel(channel)}
}

此操作需要在显示通知前完成,可以重复调用。
创建完通道后可以再设置中看到。

CHANNEL_ID_NOTIFICATION_BASIC 是我们自定义的 CHANNEL_ID 后面显示通知的时候会用到

private const val CHANNEL_ID_NOTIFICATION_BASIC = "CHANNEL_ID_NOTIFICATION_BASIC"

在显示通知之前,我们先创建一个NotificationManager

private lateinit var notificationManager: NotificationManagernotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

基本样式通知

/*** 显示基本通知*/
private fun showBasicNotification2() {val build = NotificationCompat.Builder(this, CHANNEL_ID_NOTIFICATION_BASIC).setSmallIcon(R.mipmap.ic_launcher).setContentTitle("基本通知").setContentText("我是基本通知内容").setPriority(NotificationCompat.PRIORITY_DEFAULT).build()notificationManager.notify(id++, build)
}

可以展开大图的通知

private fun showBigPictureNotification() {val bitmap = BitmapFactory.decodeStream(resources.assets.open("picture.jpg"))val build = NotificationCompat.Builder(this, CHANNEL_ID_NOTIFICATION_BASIC).setSmallIcon(R.mipmap.ic_launcher).setContentTitle("可展开大图").setContentText("我是可展开大图的通知").setStyle(NotificationCompat.BigPictureStyle().bigPicture(bitmap)).build()notificationManager.notify(id++, build)
}

可以展开大段文字的通知

private fun showBigTextNotification() {val bitmap = BitmapFactory.decodeStream(resources.assets.open("picture.jpg"))val build = NotificationCompat.Builder(this, CHANNEL_ID_NOTIFICATION_BASIC).setSmallIcon(R.mipmap.ic_launcher).setContentTitle("可展开大段文字").setContentText("我是可展开大段文字的通知").setLargeIcon(bitmap).setStyle(NotificationCompat.BigTextStyle().setBigContentTitle("大段文字").bigText("大段文字大段文字大段文字大段文字大段文字大段文字大段文字大段文字大段文字大段文字大段文字大段文字大段文字大段文字大段文字大段文字大段文字大段文字大段文字")).build()notificationManager.notify(id++, build)
}

列表样式的通知

private fun showMessageSnippetNotification() {val bitmap = BitmapFactory.decodeStream(resources.assets.open("picture.jpg"))val build = NotificationCompat.Builder(this, CHANNEL_ID_NOTIFICATION_BASIC).setSmallIcon(R.mipmap.ic_launcher).setContentTitle("列表样式的通知").setContentText("我是列表样式的通知").setLargeIcon(bitmap).setStyle(NotificationCompat.InboxStyle().addLine("1111111").addLine("2222222").addLine("3").addLine("444").addLine("555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555").addLine("6666666666666666")).build()notificationManager.notify(id++, build)
}

列表中最多显示6行(addLine 6次),多余6行的内容将无法显示。

对话样式的通知

private fun showMessagingNotification() {val bitmap = BitmapFactory.decodeStream(resources.assets.open("picture.jpg"))val createWithBitmap = IconCompat.createWithBitmap(bitmap)val message1 = NotificationCompat.MessagingStyle.Message("你好啊", System.currentTimeMillis(), Person.Builder().setName("张三").setIcon(createWithBitmap).build())val message2 = NotificationCompat.MessagingStyle.Message("谢谢", System.currentTimeMillis(), Person.Builder().setName("李四").setBot(true).build())val message3 = NotificationCompat.MessagingStyle.Message("Hello!", System.currentTimeMillis(), Person.Builder().setName("王五").setImportant(true).build())val message4 = NotificationCompat.MessagingStyle.Message("Android", System.currentTimeMillis(), Person.Builder().setName("赵六").setIcon(createWithBitmap).build())val message5 = NotificationCompat.MessagingStyle.Message("Notification", System.currentTimeMillis(), Person.Builder().setName("小七").build())val message6 = NotificationCompat.MessagingStyle.Message("biubiubiu~", System.currentTimeMillis(), Person.Builder().setName("老八").build())val build = NotificationCompat.Builder(this, CHANNEL_ID_NOTIFICATION_BASIC).setSmallIcon(R.mipmap.ic_launcher).setLargeIcon(bitmap).setStyle(NotificationCompat.MessagingStyle(Person.Builder().setName("kongqw").build()).addMessage(message1).addMessage(message2).addMessage(message3).addMessage(message4).addMessage(message5).addMessage(message6)).build()notificationManager.notify(id++, build)
}

列表中最多显示5条,后添加的消息会挤掉前面的消息。

媒体控件样式的通知

需要先添加一个依赖

implementation "androidx.media:media:1.1.0"
private fun showMediaNotification() {val bitmap = BitmapFactory.decodeStream(resources.assets.open("picture.jpg"))val pendingIntentPrevious: PendingIntent = PendingIntent.getBroadcast(this, 0, Intent("com.kongqw.notification.media.previous"), 0)val pendingIntentPause: PendingIntent = PendingIntent.getBroadcast(this, 0, Intent("com.kongqw.notification.media.pause"), 0)val pendingIntentNext: PendingIntent = PendingIntent.getBroadcast(this, 0, Intent("com.kongqw.notification.media.next"), 0)val pendingIntentPlay: PendingIntent = PendingIntent.getBroadcast(this, 0, Intent("com.kongqw.notification.media.play"), 0)val build = NotificationCompat.Builder(this, CHANNEL_ID_NOTIFICATION_BASIC).setVisibility(NotificationCompat.VISIBILITY_PUBLIC).setSmallIcon(R.mipmap.ic_launcher).setContentTitle("媒体控件样式通知").setContentText("我是媒体控件样式通知").addAction(android.R.drawable.ic_media_previous, "Previous", pendingIntentPrevious).addAction(android.R.drawable.ic_media_pause, "Pause", pendingIntentPause).addAction(android.R.drawable.ic_media_next, "Next", pendingIntentNext).addAction(android.R.drawable.ic_media_play, "Play", pendingIntentPlay).setLargeIcon(bitmap).setStyle(androidx.media.app.NotificationCompat.MediaStyle().setShowActionsInCompactView(0, 1, 2) // .setMediaSession()).build()notificationManager.notify(id++, build)
}

上述代码中addAction添加了4个控制按钮,setShowActionsInCompactView设置了通知在收起状态下,显示第012个按钮。

点击通知跳转Activity

基本样式通知的基础上举例,只需要setContentIntent即可

private fun showBasicNotification3() {// 创建一个跳转的Intentval intent = Intent(this, MainActivity::class.java).apply { // ... 其他一些设置信息}// 创建 PendingIntentval jumpIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, 0)val build = NotificationCompat.Builder(this, CHANNEL_ID_NOTIFICATION_BASIC).setSmallIcon(R.mipmap.ic_launcher).setContentTitle("基本通知").setContentText("我是基本通知内容,点击可以跳转Activity.").setPriority(NotificationCompat.PRIORITY_DEFAULT)// 设置跳转,点击打开MainActivity.setContentIntent(jumpIntent).build()notificationManager.notify(id++, build)
}

添加Action

同样在基本样式通知的基础上举例,Action可以添加点击跳转行为,也可以添加点击发送广播的行为。

private fun showBasicNotification4() {// 创建一个跳转的Intentval intent = Intent(this, MainActivity::class.java).apply {// ... 其他一些设置信息}// 创建 PendingIntentval jumpIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, 0)// 创建发送广播的Intentval sendBroadcastIntent: PendingIntent = PendingIntent.getBroadcast(this, 0, Intent("com.kongqw.notificationsimple.action"), 0)val build = NotificationCompat.Builder(this, CHANNEL_ID_NOTIFICATION_BASIC).setSmallIcon(R.mipmap.ic_launcher).setContentTitle("基本通知").setContentText("我是带有Action的基本通知内容").setPriority(NotificationCompat.PRIORITY_DEFAULT)// 设置点击跳转的Action.addAction(R.mipmap.ic_launcher, "点我打开MainActivity", jumpIntent)// 设置点击发送广播的Action.addAction(R.mipmap.ic_launcher, "点我发送一条广播", sendBroadcastIntent).build()notificationManager.notify(id++, build)
}
  • jumpIntent 设置了点击跳转到MainActivity
  • sendBroadcastIntent 设置了发送广播的内容,动态注册一个广播后自行验证即可。

在通知中直接回复

private fun showReplayNotification() {// 设置回复后的广播val replyPendingIntent: PendingIntent = PendingIntent.getBroadcast(applicationContext, 0, Intent("com.kongqw.notificationsimple.reply"), PendingIntent.FLAG_UPDATE_CURRENT)// 设置回复输入框val remoteInput: RemoteInput = RemoteInput.Builder("KEY_TEXT_REPLY").setLabel("请输入").build()// 设置回复按钮val replyAction = NotificationCompat.Action.Builder(R.drawable.ic_launcher_background, "回复", replyPendingIntent).addRemoteInput(remoteInput).build()// 模拟收到的消息val bitmap = BitmapFactory.decodeStream(resources.assets.open("picture.jpg"))val message = NotificationCompat.MessagingStyle.Message("你好啊", System.currentTimeMillis(), Person.Builder().setName("张三").setIcon(IconCompat.createWithBitmap(bitmap)).build())val build = NotificationCompat.Builder(this, CHANNEL_ID_NOTIFICATION_BASIC).setSmallIcon(R.mipmap.ic_launcher).setPriority(NotificationCompat.PRIORITY_DEFAULT).setStyle(NotificationCompat.MessagingStyle(Person.Builder().setName("kongqw").build()).addMessage(message))// 回复.addAction(replyAction).build()notificationManager.notify(id++, build)
}
  • KEY_TEXT_REPLY 用来标记回复的文字内容,在广播接收者中使用该字段来获取回复的文字

广播接收(代码仅供参考,注册广播请自行处理)

inner class MyBroadcastReceiver : BroadcastReceiver() {override fun onReceive(context: Context?, intent: Intent?) {when (intent?.action) {"com.kongqw.notificationsimple.action" -> Toast.makeText(applicationContext, "收到广播", Toast.LENGTH_SHORT).show()"com.kongqw.notificationsimple.reply" -> {val charSequence = RemoteInput.getResultsFromIntent(intent)?.getCharSequence("KEY_TEXT_REPLY")Toast.makeText(applicationContext, "回复:$charSequence", Toast.LENGTH_SHORT).show()}}}
}

自定义样式的通知

最后部分,我们来模拟网易云音乐,实现一个自定义的通知样式(仅实现基础样式、不包含功能),先看图(上:网易云音乐,下:自定义)

因为网易云音乐的通知有一些设置,例如:不能滑动删除、静音、没有震动等,所以我们重新创建一个通道,专门来显示我们的自定义通知。

private fun createNotificationChannel2() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {val name = "播放器"val descriptionText = "模仿网易云音乐的通知"val importance = NotificationManager.IMPORTANCE_DEFAULTval channel =NotificationChannel(CHANNEL_ID_NOTIFICATION_CUSTOM_MEDIA, name, importance).apply {description = descriptionText// 禁用呼吸灯enableLights(false)// 禁止震动enableVibration(false)vibrationPattern = LongArray(0)// 静音setSound(null, null)}notificationManager.createNotificationChannel(channel)}
}

直接上代码部分

private fun showCustomNotification() {// 自定义的通知页面val remoteViewsMedia = RemoteViews(packageName, R.layout.custom_notification_media)// 设置通知页面上按钮的点击广播remoteViewsMedia.setOnClickPendingIntent(R.id.ib_close, PendingIntent.getBroadcast(applicationContext, 0, Intent("com.kongqw.notification.custom.media.close"), 0))remoteViewsMedia.setOnClickPendingIntent(R.id.ib_1, PendingIntent.getBroadcast(applicationContext, 0, Intent("com.kongqw.notification.custom.media.btn1"), 0))remoteViewsMedia.setOnClickPendingIntent(R.id.ib_2, PendingIntent.getBroadcast(applicationContext, 0, Intent("com.kongqw.notification.custom.media.btn2"), 0))remoteViewsMedia.setOnClickPendingIntent(R.id.ib_3, PendingIntent.getBroadcast(applicationContext, 0, Intent("com.kongqw.notification.custom.media.btn3"), 0))remoteViewsMedia.setOnClickPendingIntent(R.id.ib_4, PendingIntent.getBroadcast(applicationContext, 0, Intent("com.kongqw.notification.custom.media.btn4"), 0))remoteViewsMedia.setOnClickPendingIntent(R.id.ib_5, PendingIntent.getBroadcast(applicationContext, 0, Intent("com.kongqw.notification.custom.media.btn5"), 0))// 设置封面remoteViewsMedia.setImageViewBitmap(R.id.iv_cover, BitmapFactory.decodeStream(resources.assets.open("picture.jpg")))build = NotificationCompat.Builder(this, CHANNEL_ID_NOTIFICATION_CUSTOM_MEDIA).setSmallIcon(R.mipmap.ic_launcher)// .setStyle(NotificationCompat.DecoratedCustomViewStyle()).setCustomContentView(remoteViewsMedia).setAutoCancel(false)// 禁止滑动删除.setOngoing(true)build?.priority = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {NotificationManager.IMPORTANCE_MAX} else {NotificationCompat.PRIORITY_MAX}notificationManager.notify(66, build?.build())
}

自定义通知,最核心的的部分就在setCustomContentView,添加了一个自定义的View,这里是一个RemoteViews,因此想到之前的Widget开发,通知的自定义布局和Widget的自定义布局一样,能且仅能使用部分布局和组件,详见Widget。

这里在复述一遍,
可使用的布局包括:

  • FrameLayout
  • LinearLayout
  • RelativeLayout
  • GridLayout

可使用的控件包括:

  • AnalogClock
  • Button
  • Chronometer
  • ImageButton
  • ImageView
  • ProgressBar
  • TextView
  • ViewFlipper
  • ListView
  • GridView
  • StackView
  • AdapterViewFlipper

注:如果使用除此之外的布局或控件,通知将无法显示。

布局文件 custom_notification_media.xml 提供一下仅供参考

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="113dp"android:orientation="horizontal"><ImageViewandroid:id="@+id/iv_cover"android:layout_width="113dp"android:layout_height="113dp"android:background="@drawable/ic_launcher_background"android:scaleType="centerCrop" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:weightSum="10"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="60dp"><ImageButtonandroid:id="@+id/ib_close"android:layout_width="30dp"android:layout_height="30dp"android:layout_alignParentEnd="true"android:layout_alignParentRight="true"android:background="@android:color/transparent"android:src="@android:drawable/ic_menu_close_clear_cancel" /><TextViewandroid:id="@+id/tv_title"android:layout_width="match_parent"android:layout_height="35dp"android:layout_toStartOf="@id/ib_close"android:layout_toLeftOf="@id/ib_close"android:gravity="center_vertical"android:paddingStart="10dp"android:paddingEnd="10dp"android:text="我是歌名"android:textColor="#555555"android:textSize="15sp" /><TextViewandroid:id="@+id/tv_des"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_below="@id/tv_title"android:layout_toStartOf="@id/ib_close"android:layout_toLeftOf="@id/ib_close"android:gravity="center_vertical"android:paddingStart="10dp"android:paddingEnd="10dp"android:text="我是歌手名"android:textColor="#AAAAAA"android:textSize="13sp" /></RelativeLayout><TextViewandroid:layout_width="match_parent"android:layout_height="1dp"android:background="#EEEEEE" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"android:weightSum="5"><ImageButtonandroid:id="@+id/ib_1"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@android:color/transparent"android:src="@android:drawable/star_off" /><ImageButtonandroid:id="@+id/ib_2"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@android:color/transparent"android:src="@android:drawable/ic_media_previous" /><ImageButtonandroid:id="@+id/ib_3"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@android:color/transparent"android:src="@android:drawable/ic_media_play" /><ImageButtonandroid:id="@+id/ib_4"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@android:color/transparent"android:src="@android:drawable/ic_media_next" /><ImageButtonandroid:id="@+id/ib_5"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@android:color/transparent"android:src="@android:drawable/ic_lock_power_off" /></LinearLayout></LinearLayout>
</LinearLayout>

广播的注册

private val mMyBroadcastReceiver = MyBroadcastReceiver()
private val mIntentFilter = IntentFilter().apply {addAction("com.kongqw.notification.custom.media.close")addAction("com.kongqw.notification.custom.media.btn1")addAction("com.kongqw.notification.custom.media.btn2")addAction("com.kongqw.notification.custom.media.btn3")addAction("com.kongqw.notification.custom.media.btn4")addAction("com.kongqw.notification.custom.media.btn5")
}
registerReceiver(mMyBroadcastReceiver, mIntentFilter)

反注册

unregisterReceiver(mMyBroadcastReceiver)

广播接收者

inner class MyBroadcastReceiver : BroadcastReceiver() {override fun onReceive(context: Context?, intent: Intent?) {when (intent?.action) {"com.kongqw.notification.custom.media.close" -> {Toast.makeText(applicationContext, "关闭", Toast.LENGTH_SHORT).show()notificationManager.cancel(66)}"com.kongqw.notification.custom.media.btn1" -> Toast.makeText(applicationContext, "按钮1", Toast.LENGTH_SHORT).show()"com.kongqw.notification.custom.media.btn2" -> Toast.makeText(applicationContext, "按钮2", Toast.LENGTH_SHORT).show()"com.kongqw.notification.custom.media.btn3" -> {Toast.makeText(applicationContext, "按钮3", Toast.LENGTH_SHORT).show()val remoteViewsMedia = RemoteViews(packageName, R.layout.custom_notification_media)if (isPlaying) {isPlaying = falseremoteViewsMedia.setImageViewResource(R.id.ib_3, android.R.drawable.ic_media_play)} else {isPlaying = trueremoteViewsMedia.setImageViewResource(R.id.ib_3, android.R.drawable.ic_media_pause)}build?.setCustomContentView(remoteViewsMedia)// 更新通知notificationManager.notify(66, build?.build())}"com.kongqw.notification.custom.media.btn4" -> Toast.makeText(applicationContext, "按钮4", Toast.LENGTH_SHORT).show()"com.kongqw.notification.custom.media.btn5" -> Toast.makeText(applicationContext, "按钮5", Toast.LENGTH_SHORT).show()}}
}

Android通知——Notification相关推荐

  1. android activity 被notification启动,Android通知Notification全面剖析

    原标题:Android通知Notification全面剖析 通知 通知是您可以在应用的常规 UI 外部向用户显示的消息.当您告知系统发出通知时,它将先以图标的形式显示在通知区域中.用户可以打开抽屉式通 ...

  2. Android通知Notification使用全解析,看这篇就够了

    1.效果 2.简介 通知是 Android 在您的应用 UI 之外显示的消息,用于向用户提供提醒.来自其他人的通信或来自您的应用的其他及时信息.用户可以点击通知打开您的应用或直接从通知中执行操作. 2 ...

  3. Android - 通知Notification

    简介 指 Android 在应用的界面之外显示的消息,旨在向用户提供提醒.来自他人的通信信息或应用中的其他实时信息.用户可以点击通知来打开应用,也可以直接在通知中执行某项操作,比如点击按钮可以切歌,甚 ...

  4. android之Notification通知

    我们在用手机的时候,如果来了短信,而我们没有点击查看的话,是不是在手机的最上边的状态栏里有一个短信的小图标提示啊?你是不是也想实现这种功能呢?今天的Notification就是解决这个问题的. pac ...

  5. xamarin android 通知,在 Xamarin.Android 中使用 Notification.Builder 构建通知

    0 背景 在 Android 4.0 以后,系统支持一种更先进的 Notification.Builder 类来发送通知.但 Xamarin 文档含糊其辞,多方搜索无果,遂决定自己摸索. 之前的代码: ...

  6. android 通知传值,Android消息通知(notification)和PendingIntent传值

    Android支持Toast和NotificationManager两种通知方式,前者相当于一个定时关闭的对话框,后者是在状态栏上显示一条消息.Toast和Notification都可以随时取消. T ...

  7. Android的notification通知

    概括: Android使用notification实现消息提醒,提供通知栏和通知抽屉查看通知和通知详情,Android的notification机制应用非常广泛,是指在应用程序之外显示的消息,布局由系 ...

  8. Android篇 --Notification(消息通知)

    Android篇 --Notification(消息通知) 消息通知(Notification)是Android系统中比较有特色的一个功能,当某个应用程序希望用户发出一些提示信息,而该应用又不在前台运 ...

  9. 利用android的通知Notification来实现msn的登录状态

    Notification,状态栏.看得出来就是和我们PC机一样,在某一区域有个标志,需要请求它就去点这个标志就可以打开这个程序了. 先来介绍下需要用到的一些属于android下的类:Intent.No ...

最新文章

  1. 360金融携手上海交大共建AI实验室,开启人才战略新布局
  2. boost::mp11::mp_split相关用法的测试程序
  3. SQL Server安全(11/11):审核(Auditing)
  4. VLC详细的使用说明以及配置说明综合示范实例精通VLC开发
  5. postman新手使用教程
  6. mysql cluster安装配置_mysqlcluster安装与配置_MySQL
  7. Maven系列一pom.xml 配置详解
  8. jq多选按钮值_关于jquery的多选框获取值和状态回显
  9. Spring的JdbcTemplate实现分页
  10. HPGL(PLT文件格式)文件解析及VS2017工程源码
  11. 对联广告html,Js对联广告代码示例(入门)
  12. 爬取搜狗微信文章笔记2
  13. python不是5的倍数_python – 低于1000的3或5的所有倍数的总和
  14. AI人工智能基础自学(一)
  15. win2008 r2 hyper-v虚拟机的安装使用图文教程
  16. 基于RPA的自动化测试研究
  17. 带宽,速率,吞吐量区别
  18. linux samba yum,CentOS7下yum安装SAMBA全命令过程
  19. 微信支付 商户号该产品权限未开通,请前往商户平台
  20. linux系统怎么设置为中午_Linux修改系统时间与时区

热门文章

  1. ❤️数据可视化❤️:基于Echarts + GeoJson实现的地图视觉映射散点(气泡)组件【4】 - 广东省
  2. FFMpeg 实现视频编码、解码
  3. 用NetTerm连接虚拟机的telnet服务,打造轻松自如的虚拟机实验环境
  4. openldap 匿名访问
  5. 单点登录涉及的技术点
  6. 谷歌SEO排名受哪些因素的影响?(二)
  7. 【单片机原理及其应用】第五章定时器的介绍和习题分析
  8. 《神经网络与深度学习》nndl读书笔记
  9. java提取pdf题目_java读取doc,pdf问题。
  10. 超实数与单子(Monad)