Android使用Notification通知栏功能的封装

在Android应用开发中我们经常会使用到通知栏的功能,安卓的通知栏有多种类型样式,包括基本类型、带进度条的类型、大图标类型、大段文本类型等,在Android 8.0 (API level 26) 中使用通知栏的代码示例:

        // 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())
 

以下会对notification的使用做一个简单的封装,具体的功能逻辑还可以再扩展

先看一下具体的使用:

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)
    }
}

DefaultNotifyBuilder中有一些参数会有默认值:

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会对基本的参数进行组装:

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采用单例模式

从 Android 8.0(API 级别 26)开始,必须为所有通知分配渠道,否则通知将不会显示。通过将通知归类为不同的渠道,用户可以停用您应用的特定通知渠道(而非停用您的所有通知),还可以控制每个渠道的视觉和听觉选项,所有这些操作都在 Android 系统设置中完成。用户还可以长按通知以更改所关联渠道的行为。

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)
            }
        }
    }
}

其它样式builder的处理逻辑,如 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()
    }
}

猜你喜欢

转载自blog.csdn.net/qq_36162336/article/details/128683839