Android は通知通知バー機能のカプセル化を使用します

Androidアプリの開発では通知バーの機能をよく利用しますが、Android の通知バーには基本的なタイプ、プログレスバー付きタイプ、大きなアイコンタイプ、大きな文字タイプなど、さまざまなスタイルがあります。通知バーを使用した (API レベル 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())
 

以下は通知を使用するためのシンプルなパッケージを作成し、特定の機能ロジックを拡張できます。

まずは具体的な使い方を見てみましょう。

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

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