```
/**
- 显示基本通知
*/
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)
}
[]( )可以展开大图的通知
-------------------------------------------------------------------
![](https://img-blog.csdnimg.cn/20200804182808498.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3E0ODc4ODAy,size_16,color_FFFFFF,t_70) ![](https://img-blog.csdnimg.cn/20200804182922900.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3E0ODc4ODAy,size_16,color_FFFFFF,t_70)```
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)
}
[]( )列表样式的通知
-----------------------------------------------------------------
![](https://img-blog.csdnimg.cn/20200804183128181.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3E0ODc4ODAy,size_16,color_FFFFFF,t_70) ![](https://img-blog.csdnimg.cn/20200804183151701.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3E0ODc4ODAy,size_16,color_FFFFFF,t_70)```
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条,后添加的消息会挤掉前面的消息。
[]( )媒体控件样式的通知
-------------------------------------------------------------------
![](https://img-blog.csdnimg.cn/20200804183317792.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3E0ODc4ODAy,size_16,color_FFFFFF,t_70) ![](https://img-blog.csdnimg.cn/20200804183340455.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3E0ODc4ODAy,size_16,color_FFFFFF,t_70)
需要先添加一个依赖
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`设置了通知在收起状态下,显示第`0`、`1`、`2`个按钮。
[]( )点击通知跳转Activity
------------------------------------------------------------------------
在`基本样式通知`的基础上举例,只需要`setContentIntent`即可
private fun showBasicNotification3() {
// 创建一个跳转的Intent
val intent = Intent(this, MainActivity::class.java).apply {
// ... 其他一些设置信息
}
// 创建 PendingIntent
val 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
------------------------------------------------------------------
![](https://img-blog.csdnimg.cn/20200804183419567.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3E0ODc4ODAy,size_16,color_FFFFFF,t_70)
同样在`基本样式通知`的基础上举例,Action可以添加点击跳转行为,也可以添加点击发送广播的行为。
private fun showBasicNotification4() {
// 创建一个跳转的Intent
val intent = Intent(this, MainActivity::class.java).apply {
// ... 其他一些设置信息
}
// 创建 PendingIntent
val jumpIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, 0)
// 创建发送广播的Intent
val 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 设置了发送广播的内容,动态注册一个广播后自行验证即可。
[]( )在通知中直接回复
------------------------------------------------------------------
![](https://img-blog.csdnimg.cn/20200804183446736.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3E0ODc4ODAy,size_16,color_FFFFFF,t_70) ![](https://img-blog.csdnimg.cn/20200804183509655.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3E0ODc4ODAy,size_16,color_FFFFFF,t_70) ![](https://img-blog.csdnimg.cn/20200804183528972.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3E0ODc4ODAy,size_16,color_FFFFFF,t_70) ![](https://img-blog.csdnimg.cn/2020080418355190.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3E0ODc4ODAy,size_16,color_FFFFFF,t_70) ![](https://img-blog.csdnimg.cn/20200804183616617.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3E0ODc4ODAy,size_16,color_FFFFFF,t_70) ![](https://img-blog.csdnimg.cn/20200804183636345.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3E0ODc4ODAy,size_16,color_FFFFFF,t_70)```
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_DEFAULT
val 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
最后
答应大伙的备战金三银四,大厂面试真题来啦!
这份资料我从春招开始,就会将各博客、论坛。网站上等优质的Android开发中高级面试题收集起来,然后全网寻找最优的解答方案。每一道面试题都是百分百的大厂面经真题+最优解答。包知识脉络 + 诸多细节。
节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
《960全网最全Android开发笔记》
《379页Android开发面试宝典》
包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。
如何使用它?
1.可以通过目录索引直接翻看需要的知识点,查漏补缺。
2.五角星数表示面试问到的频率,代表重要推荐指数
《507页Android开发相关源码解析》
只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。
真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。
腾讯、字节跳动、阿里、百度等BAT大厂 2020-2021面试真题解析
资料收集不易,如果大家喜欢这篇文章,或者对你有帮助不妨多多点赞转发关注哦。文章会持续更新的。绝对干货!!!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。
如何使用它?
1.可以通过目录索引直接翻看需要的知识点,查漏补缺。
2.五角星数表示面试问到的频率,代表重要推荐指数
[外链图片转存中…(img-5m0jL7xy-1714463140897)]
《507页Android开发相关源码解析》
只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。
真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。
[外链图片转存中…(img-tJfUZBc4-1714463140898)]
腾讯、字节跳动、阿里、百度等BAT大厂 2020-2021面试真题解析
[外链图片转存中…(img-Y5UPnm4R-1714463140898)]
资料收集不易,如果大家喜欢这篇文章,或者对你有帮助不妨多多点赞转发关注哦。文章会持续更新的。绝对干货!!!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!