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