En el desarrollo de aplicaciones de Android, a menudo usamos la función de la barra de notificaciones. Hay muchos tipos de estilos para la barra de notificaciones de Android, incluidos tipos básicos, tipos con barras de progreso, tipos de iconos grandes y tipos de texto grande. En Android 8.0 (Nivel de API 26) ejemplo de código usando la barra de notificación:
// Create an explicit intent for an Activity in your app
val intent = Intent(this, AlertDetails::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val pendingIntent = PendingIntent.getActivity(this, 0, intent, 0)
val builder: NotificationCompat.Builder = NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!")
.setPriority(NotificationCompat.PRIORITY_DEFAULT) // Set the intent that will fire when the user taps the notification
.setContentIntent(pendingIntent)
.setAutoCancel(true)
val notificationManager = NotificationManagerCompat.from(this)
// notificationId is a unique int for each notification that you must define
notificationManager.notify(notificationId, builder.build())
Lo siguiente hará un paquete simple para el uso de la notificación, y la lógica funcional específica se puede expandir
Primero mira el uso específico:
package com.let.myapplication
import android.app.PendingIntent
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity(), View.OnClickListener {
private val TAG = MainActivity::class.java.simpleName
var tvImMsg: TextView? = null
var tvSysMsg: TextView? = null
private val userArray = arrayOf("Cyra", "Morgen", "Iris", "Mia")
private val messageArray = arrayOf("我发表了新的美食文章", "我更新了我的相册", "我在FaceBook申请了账号", "我做了一个好看的小视频")
private val sysMessageArray = arrayOf("有新的系统版本可以升级", "收到新的资讯内容", "为你推荐周边美食、娱乐活动", "最新最火爆的游戏")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
tvImMsg = findViewById(R.id.textview_im_msg)
tvSysMsg = findViewById(R.id.textview_sys_msg)
tvImMsg!!.setOnClickListener(this)
tvSysMsg!!.setOnClickListener(this)
}
override fun onClick(v: View) {
when (v.id) {
R.id.textview_im_msg -> notifyImMessage()
R.id.textview_sys_msg -> notifySysMessage()
else -> {}
}
}
private fun notifyImMessage() {
val uIndex = (Math.random() * userArray.size).toInt()
val mIndex = (Math.random() * messageArray.size).toInt()
val userName = userArray[uIndex]
val content = messageArray[mIndex]
val key = "ImMessage#$userName"
val requestCode = NotifyManager.getInstance(this@MainActivity).initNotifyId(key)
Log.d(TAG, "method:notifyReceivedMessage#key=$key, requestCode=$requestCode")
val intent = Intent(this@MainActivity, NotificationMsgActivity::class.java)
intent.putExtra("msgContent", "$userName:\n\n$content")
val pendingIntent = PendingIntent.getActivity(this@MainActivity, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT)
val defaultNotifyBuilder = DefaultNotifyBuilder(userName, content)
.setChannelId(resources.getString(R.string.channel_001))
.setContentIntent(pendingIntent)
NotifyManager.getInstance(this@MainActivity).showDefaultNotification(key, defaultNotifyBuilder)
}
private fun notifySysMessage() {
val key = "SysMessage#系统消息"
val mIndex = (Math.random() * sysMessageArray.size).toInt()
val content = sysMessageArray[mIndex]
val requestCode = NotifyManager.getInstance(this@MainActivity).initNotifyId(key)
Log.d(TAG, "method:notifyReceivedMessage#key=$key, requestCode=$requestCode")
val intent = Intent(this@MainActivity, NotificationMsgActivity::class.java)
intent.putExtra("msgContent", "系统消息:\n\n$content")
val pendingIntent = PendingIntent.getActivity(this@MainActivity, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT)
val defaultNotifyBuilder = DefaultNotifyBuilder("系统消息", content)
.setChannelId(resources.getString(R.string.channel_002))
.setContentIntent(pendingIntent)
NotifyManager.getInstance(this@MainActivity).showDefaultNotification(key, defaultNotifyBuilder)
}
}
Algunos parámetros en DefaultNotifyBuilder tendrán valores predeterminados:
package com.let.myapplication
import android.app.PendingIntent
import androidx.core.app.NotificationCompat
/**
* @author let
*/
class DefaultNotifyBuilder {
@JvmField
var channelId: String? = null
@JvmField
var smallIcon = R.drawable.ic_launcher_foreground
@JvmField
var contentTitle: CharSequence = "小蜗牛Tech"
@JvmField
var contentText: CharSequence
@JvmField
var ticker: CharSequence? = null
var flag = NotificationCompat.FLAG_AUTO_CANCEL
@JvmField
var priority = NotificationCompat.PRIORITY_HIGH
@JvmField
var `when` = System.currentTimeMillis()
@JvmField
var contentIntent: PendingIntent? = null
@JvmField
var autoCancel = true
@JvmField
var sound = false
@JvmField
var vibrate = false
@JvmField
var lights = false
constructor(contentText: CharSequence) {
this.contentText = contentText
}
constructor(contentTitle: CharSequence, contentText: CharSequence) {
this.contentTitle = contentTitle
this.contentText = contentText
}
constructor(smallIcon: Int, contentTitle: CharSequence, contentText: CharSequence) {
this.smallIcon = smallIcon
this.contentTitle = contentTitle
this.contentText = contentText
}
fun setChannelId(channelId: String?): DefaultNotifyBuilder {
this.channelId = channelId
return this
}
fun setTicker(ticker: CharSequence?): DefaultNotifyBuilder {
this.ticker = ticker
return this
}
fun setFlag(flag: Int): DefaultNotifyBuilder {
this.flag = flag
return this
}
fun setPriority(priority: Int): DefaultNotifyBuilder {
this.priority = priority
return this
}
fun setWhen(`when`: Long): DefaultNotifyBuilder {
this.`when` = `when`
return this
}
fun setContentIntent(contentIntent: PendingIntent?): DefaultNotifyBuilder {
this.contentIntent = contentIntent
return this
}
fun setAutoCancel(autoCancel: Boolean): DefaultNotifyBuilder {
this.autoCancel = autoCancel
return this
}
fun setSound(sound: Boolean): DefaultNotifyBuilder {
this.sound = sound
return this
}
fun setVibrate(vibrate: Boolean): DefaultNotifyBuilder {
this.vibrate = vibrate
return this
}
fun setLights(lights: Boolean): DefaultNotifyBuilder {
this.lights = lights
return this
}
}
BaseNotifyBuilder ensamblará los parámetros básicos:
package com.let.myapplication
import android.app.Notification
import android.content.Context
import android.os.Build
import android.text.TextUtils
import android.util.Log
import androidx.core.app.NotificationCompat
import com.let.myapplication.BaseNotifyBuilder
/**
* @author let
*/
open class BaseNotifyBuilder(protected var defaultBuilder: DefaultNotifyBuilder) {
@JvmField
protected var notifyBuilder: NotificationCompat.Builder? = null
open fun build(context: Context?): Notification? {
notifyBuilder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationCompat.Builder(context!!, defaultBuilder.channelId!!)
} else {
NotificationCompat.Builder(context!!)
}
Log.d(TAG, "method:build#defaultBuilder=$defaultBuilder")
// 设置顶部状态栏的小图标
notifyBuilder!!.setSmallIcon(defaultBuilder.smallIcon)
// 设置通知中心的标题
notifyBuilder!!.setContentTitle(defaultBuilder.contentTitle)
// 设置通知中心中的内容
val contentText = defaultBuilder.contentText
if (!TextUtils.isEmpty(contentText)) {
notifyBuilder!!.setContentText(defaultBuilder.contentText)
}
val contentIntent = defaultBuilder.contentIntent
if (contentIntent != null) {
notifyBuilder!!.setContentIntent(contentIntent)
}
var defaults = 0
val sound = defaultBuilder.sound
val vibrate = defaultBuilder.vibrate
val lights = defaultBuilder.lights
if (sound) {
defaults = defaults or Notification.DEFAULT_SOUND
}
if (vibrate) {
defaults = defaults or Notification.DEFAULT_VIBRATE
}
if (lights) {
defaults = defaults or Notification.DEFAULT_LIGHTS
}
if (defaults != 0) {
notifyBuilder!!.setDefaults(defaults)
}
val ticker = defaultBuilder.ticker
if (!TextUtils.isEmpty(ticker)) {
notifyBuilder!!.setTicker(defaultBuilder.ticker)
}
notifyBuilder!!.setAutoCancel(defaultBuilder.autoCancel)
notifyBuilder!!.setWhen(defaultBuilder.`when`)
notifyBuilder!!.priority = defaultBuilder.priority
return notifyBuilder!!.build()
}
companion object {
private val TAG = BaseNotifyBuilder::class.java.simpleName
}
}
MyNotificationManager usa un patrón singleton
A partir de Android 8.0 (API nivel 26), todas las notificaciones deben tener asignado un canal, de lo contrario, la notificación no se mostrará. Al agrupar las notificaciones en diferentes canales, los usuarios pueden deshabilitar canales de notificación específicos para su aplicación (en lugar de deshabilitar todas sus notificaciones), así como también controlar las opciones visuales y audibles para cada canal, todo dentro del sistema Android. La configuración está completa. Los usuarios también pueden mantener presionada una notificación para cambiar el comportamiento del canal asociado.
package com.let.myapplication
import android.app.NotificationChannel
import android.app.NotificationChannelGroup
import android.app.NotificationManager
import android.content.Context
import android.os.Build
import android.util.Log
import com.let.myapplication.NotifyManager
import java.util.concurrent.atomic.AtomicInteger
/**
* @author let
*
*
* 封装通知栏实现,对于某些相关属性的处理逻辑,可根据具体的需求调整完善
*/
class NotifyManager private constructor() {
/**
* 通知栏的消息对象的自增Id
*/
private val mInitialNotifyId: AtomicInteger? = AtomicInteger(0)
/**
* 全局通知栏的Id,不同消息对象,对应自身唯一的全局Id
*/
@Volatile
private var mGlobalNotifyIdMap: MutableMap<Any, Int>? = null
val initialNotifyId: Int
get() = mInitialNotifyId?.toInt() ?: 0
val globalNotifyIdMap: Map<Any, Int>?
get() = mGlobalNotifyIdMap
/**
* IM消息的key的形式:key = "ImMessage"
*
* @param key
* @return 返回对应的id
*/
fun initNotifyId(key: Any): Int {
Log.d(TAG, "method:initNotifyId#key=$key")
if (mGlobalNotifyIdMap == null) {
mGlobalNotifyIdMap = HashMap()
}
val notifyId = mGlobalNotifyIdMap!![key]
Log.d(TAG, "method:initNotifyId#mGlobalNotifyIdMap=$mGlobalNotifyIdMap")
Log.d(TAG, "method:initNotifyId#notifyId=$notifyId")
return notifyId ?: putNotifyId(key)
}
/**
* 保证每次往集合[.mGlobalNotifyIdMap]中put新值时,ID都是自增的
*
*
* IM消息的key的形式:key = "ImMessage"
*
* @param key
* @return
*/
private fun putNotifyId(key: Any): Int {
Log.d(TAG, "method:putNotifyId#key=$key")
if (mGlobalNotifyIdMap != null) {
val value = mInitialNotifyId!!.incrementAndGet()
Log.d(TAG, "method:putNotifyId#mInitialNotifyId.incrementAndGet#value=$value")
mGlobalNotifyIdMap!![key] = value
Log.d(TAG, "method:putNotifyId#mGlobalNotifyIdMap=$mGlobalNotifyIdMap")
return value
}
return 0
}
private fun notify(key: Any, builder: BaseNotifyBuilder) {
val notifyId = initNotifyId(key)
notificationManager!!.notify(notifyId, builder.build(mContext))
}
val channelGroupList: List<NotificationChannelGroup>?
get() = mChannelGroupList
fun showDefaultNotification(key: Any, defaultBuilder: DefaultNotifyBuilder?) {
val builder = BaseNotifyBuilder(defaultBuilder!!)
notify(key, builder)
}
fun showProgressNotification(key: Any, progress: Int, max: Int, interminate: Boolean, defaultBuilder: DefaultNotifyBuilder?) {
val builder = ProgressNotifyBuilder(defaultBuilder)
notify(key, builder)
}
fun showLargeIconNotification(key: Any, largeIconId: Int, defaultBuilder: DefaultNotifyBuilder?) {
val builder: LargeIconNotifyBuilder = LargeIconNotifyBuilder(defaultBuilder).setLargeIcon(largeIconId)
notify(key, builder)
}
fun showBigTextNotification(key: Any, bigText: String?, defaultBuilder: DefaultNotifyBuilder?) {
val builder = BigTextNotifyBuilder(defaultBuilder).setBigText(bigText)
notify(key, builder)
} // ……………… 根据需要完善其它通知栏样式 ………………
companion object {
private val TAG = NotifyManager::class.java.simpleName
private var sInstance: NotifyManager? = null
var notificationManager: NotificationManager? = null
get() = Companion.field
private set
private var mChannelGroupList: MutableList<NotificationChannelGroup>? = null
private var mContext: Context? = null
fun getInstance(context: Context): NotifyManager? {
if (sInstance == null) {
synchronized(NotifyManager::class.java) {
if (sInstance == null) {
sInstance = NotifyManager()
mContext = context.applicationContext
if (notificationManager == null) {
notificationManager = mContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
initNotifyChannel()
}
}
}
}
return sInstance
}
private fun initNotifyChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (mChannelGroupList == null) {
mChannelGroupList = ArrayList()
}
mChannelGroupList!!.add(NotificationChannelGroup(mContext!!.resources.getString(R.string.groupId_001), "系统消息"))
mChannelGroupList!!.add(NotificationChannelGroup(mContext!!.resources.getString(R.string.groupId_002), "IM消息"))
notificationManager!!.createNotificationChannelGroups(mChannelGroupList!!)
val channel1 = NotificationChannel(mContext!!.resources.getString(R.string.channel_001), "系统消息", NotificationManager.IMPORTANCE_HIGH)
val channel2 = NotificationChannel(mContext!!.resources.getString(R.string.channel_002), "IM消息", NotificationManager.IMPORTANCE_HIGH)
channel1.group = mContext!!.resources.getString(R.string.groupId_001)
channel2.group = mContext!!.resources.getString(R.string.groupId_002)
notificationManager!!.createNotificationChannel(channel1)
notificationManager!!.createNotificationChannel(channel2)
}
}
}
}
Lógica de procesamiento de otros constructores de estilo, como BigTextNotifyBuilder:
package com.let.myapplication
import android.app.Notification
import android.content.Context
import androidx.core.app.NotificationCompat
/**
* @author let
*/
class BigTextNotifyBuilder(defaultBuilder: DefaultNotifyBuilder?) : BaseNotifyBuilder(defaultBuilder!!) {
var mBigText: String? = null
var mBigTextStyle: NotificationCompat.BigTextStyle? = null
fun setBigText(bigText: String?): BigTextNotifyBuilder {
mBigText = bigText
mBigTextStyle = NotificationCompat.BigTextStyle()
.bigText(bigText)
return this
}
override fun build(context: Context?): Notification? {
super.build(context)
notifyBuilder!!.setStyle(mBigTextStyle)
return notifyBuilder!!.build()
}
}