新的通知框架

This commit is contained in:
renhaoting 2025-12-29 16:56:08 +08:00
parent b59b858352
commit 6018362656
7 changed files with 198 additions and 52 deletions

View File

@ -0,0 +1,14 @@
package com.remax.notification.newUtil
import android.content.Intent
class NotificationConfig(val notificationId: Int = System.currentTimeMillis().toInt(),
val channelId: String,
val channelName: String,
val title: String,
val content: String,
val smallIcon: Int,
val intent: Intent? = null,
val useFullScreenIntent: Boolean = false,
) {
}

View File

@ -0,0 +1,59 @@
package com.remax.notification.newUtil
import android.app.PendingIntent
import android.content.Intent
import com.ama.core.architecture.util.ResUtil
import com.remax.notification.R
import java.util.concurrent.ConcurrentHashMap
object NotificationDatas {
// notifi type
const val NOTI_TYPE_BG_WITHDRAW = "NOTI_TYPE_BG_WITHDRAW"
const val NOTI_TYPE_BG_RANDOM = "NOTI_TYPE_BG_RANDOM"
const val NOTI_TYPE_RESIDENT = "NOTI_TYPE_RESIDENT"
const val NOTI_TYPE_UNLOCK = "NOTI_TYPE_UNLOCK"
// notifi id
const val NOTI_ID_TYPE_BG_WITHDRAW = 666
const val NOTI_ID_TYPE_BG_RANDOM = 667
const val NOTI_ID_TYPE_RESIDENT = 668
const val NOTI_ID_TYPE_UNLOCK = 669
// channelId type
const val CHANNEL_TYPE_BG_WITHDRAW = "CHANNEL_TYPE_BG_WITHDRAW"
const val CHANNEL_TYPE_BG_RANDOM = "CHANNEL_TYPE_BG_RANDOM"
const val CHANNEL_TYPE_RESIDENT = "CHANNEL_TYPE_RESIDENT"
const val CHANNEL_TYPE_UNLOCK = "CHANNEL_TYPE_UNLOCK"
// channelId name
const val CHANNEL_TYPE_BG_WITHDRAW_NAME = "CHANNEL_TYPE_BG_WITHDRAW_NAME"
const val CHANNEL_TYPE_BG_RANDOM_NAME = "CHANNEL_TYPE_BG_RANDOM_NAME"
const val CHANNEL_TYPE_RESIDENT_NAME = "CHANNEL_TYPE_RESIDENT_NAME"
const val CHANNEL_TYPE_UNLOCK_NAME = "CHANNEL_TYPE_UNLOCK_NAME"
private val mConfigList: ConcurrentHashMap<String, NotificationConfig> = ConcurrentHashMap()
init {
mConfigList.put(NOTI_TYPE_BG_WITHDRAW, NotificationConfig(
NOTI_ID_TYPE_BG_WITHDRAW,
CHANNEL_TYPE_BG_WITHDRAW,
CHANNEL_TYPE_BG_WITHDRAW_NAME,
ResUtil.getString(R.string.title_bg_withdraw),
String.format(ResUtil.getString(R.string.content_bg_withdraw), 50),
R.mipmap.icon_bg_withdraw,
null,
true,
))
}
fun getConfigForType(notifiType: String): NotificationConfig? {
return mConfigList[notifiType]
}
}

View File

@ -9,8 +9,10 @@ import android.graphics.Color
import android.os.Build
import android.widget.RemoteViews
import androidx.annotation.RequiresApi
import androidx.annotation.RequiresPermission
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.ama.core.architecture.BaseApp
import com.ama.core.architecture.util.permission.PermissionUtil
class NotificationUtil private constructor() {
@ -25,15 +27,14 @@ class NotificationUtil private constructor() {
}
}
private lateinit var context: Context
private lateinit var notificationManager: NotificationManager
private val context = BaseApp.appContext()
private var notificationManager: NotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
/**
* 初始化工具类
*/
fun init(context: Context) {
this.context = context.applicationContext
notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
}
/**
@ -75,7 +76,7 @@ class NotificationUtil private constructor() {
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.build()
showNotification(notificationId, notification)
showNotification(notificationId, notification, "name")
}
/**
@ -108,7 +109,7 @@ class NotificationUtil private constructor() {
.setAutoCancel(true)
.build()
showNotification(notificationId, notification)
showNotification(notificationId, notification, "name")
}
/**
@ -142,7 +143,7 @@ class NotificationUtil private constructor() {
.setAutoCancel(true)
.build()
showNotification(notificationId, notification)
showNotification(notificationId, notification, "name")
}
/**
@ -167,7 +168,7 @@ class NotificationUtil private constructor() {
.setAutoCancel(true)
.build()
showNotification(notificationId, notification)
showNotification(notificationId, notification, "name")
}
/**
@ -204,7 +205,7 @@ class NotificationUtil private constructor() {
builder.addAction(action.smallIcon, action.title, actionPendingIntent)
}
showNotification(notificationId, builder.build())
showNotification(notificationId, builder.build(), "name")
}
/**
@ -240,7 +241,7 @@ class NotificationUtil private constructor() {
.setNumber(lines.size) // 显示消息数量
.build()
showNotification(notificationId, notification)
showNotification(notificationId, notification, "name")
}
/**
@ -277,7 +278,7 @@ class NotificationUtil private constructor() {
.setCustomContentView(remoteViews) // 设置自定义视图
.build()
showNotification(notificationId, notification)
showNotification(notificationId, notification, "name")
}
@ -295,21 +296,19 @@ class NotificationUtil private constructor() {
* @param useFullScreenIntent 是否使用全屏意图来电等高优先级场景
* @param notificationId 通知ID
*/
fun showHeadsUpNotification(
channelId: String,
channelName: String,
title: String,
content: String,
smallIcon: Int,
intent: Intent? = null,
useFullScreenIntent: Boolean = false,
notificationId: Int = System.currentTimeMillis().toInt()
) {
// 1. 确保初始化
if (!this::context.isInitialized) {
throw IllegalStateException("NotificationUtil must be initialized first")
}
fun showHeadsUpNotification(notifiConfig: NotificationConfig) {
val notificationId = notifiConfig.notificationId
val channelId = notifiConfig.channelId
val channelName = notifiConfig.channelName
val title = notifiConfig.title
val content = notifiConfig.content
val smallIcon = notifiConfig.smallIcon
val intent = notifiConfig.intent
val useFullScreenIntent = notifiConfig.useFullScreenIntent
// 1. 确保初始化
val builder = NotificationCompat.Builder(context, channelId)
// 2. 设置通知基本内容
@ -348,7 +347,7 @@ class NotificationUtil private constructor() {
}
// 6. 发送通知
showNotification(notificationId, builder.build())
showNotification(notificationId, builder.build(), "name")
}
/**
@ -400,12 +399,13 @@ class NotificationUtil private constructor() {
private fun showNotification(notificationId: Int = System.currentTimeMillis().toInt(), notification: Notification) {
private fun showNotification(notificationId: Int = System.currentTimeMillis().toInt(),
notification: Notification,
channelName: String) {
if (!isNotificationsEnabled()) {
PermissionUtil.checkPermission(Manifest.permission.POST_NOTIFICATIONS, object : PermissionUtil.ICallback() {
override fun onAllGranted() {
NotificationManagerCompat.from(context).notify(notificationId, notification)
doShowNotification(notificationId, notification, channelName)
}
override fun onPartialGranted() {
@ -415,10 +415,18 @@ class NotificationUtil private constructor() {
}
})
} else {
NotificationManagerCompat.from(context).notify(notificationId, notification)
doShowNotification(notificationId, notification, channelName)
}
}
@RequiresPermission(Manifest.permission.POST_NOTIFICATIONS)
private fun doShowNotification(notificationId: Int = System.currentTimeMillis().toInt(), notification: Notification, channelName: String) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannel(notification.channelId, channelName, NotificationCompat.PRIORITY_HIGH)
}
NotificationManagerCompat.from(context).notify(notificationId, notification)
}
/**
* 检查通知权限

View File

@ -21,6 +21,9 @@ import com.remax.base.report.DataReportManager
import com.remax.notification.config.NotificationConfigController
import com.remax.notification.controller.NotificationTriggerController
import com.remax.notification.check.NotificationCheckController
import com.remax.notification.newUtil.NotificationDatas
import com.remax.notification.newUtil.NotificationDatas.NOTI_TYPE_BG_WITHDRAW
import com.remax.notification.newUtil.NotificationUtil
import com.remax.notification.utils.NotiLogger
import com.remax.notification.utils.FCMTopicManager
import com.remax.notification.service.FCMService
@ -245,40 +248,6 @@ class NotificationTimingController private constructor() : LifecycleObserver {
triggerNotificationIfAllowed(NotificationCheckController.NotificationType.UNLOCK)
}
/**
* 通用通知触发方法
* @param type 通知类型
*/
fun triggerNotificationIfAllowed(type: NotificationCheckController.NotificationType) {
val description = when (type) {
NotificationCheckController.NotificationType.UNLOCK -> "解锁通知"
NotificationCheckController.NotificationType.BACKGROUND -> "后台通知"
NotificationCheckController.NotificationType.KEEPALIVE -> "保活通知"
NotificationCheckController.NotificationType.FCM -> "FCM推送通知"
NotificationCheckController.NotificationType.RESIDENT -> ""
}
DataReportManager.reportData("Notific_Pull", mapOf("topic" to "localPush"))
// 检查是否可以触发通知,并获取具体的拦截原因
val checkResult = NotificationCheckController.getInstance().canTriggerNotificationWithReason(type)
if (/*!checkResult.first*/false) {
val blockReason = checkResult.second
val reasonString = blockReason?.reason ?: "unknown"
val reasonDescription = blockReason?.description ?: "未知原因"
NotiLogger.d("${description}检查未通过,跳过触发 - 原因: ${reasonDescription}")
DataReportManager.reportData("Notific_Show_Fail", mapOf(
"reason" to "app_inner_${type.string}_${reasonString}",
))
return
}
NotiLogger.d("触发${description}")
NotificationTriggerController.triggerGeneralNotification(type){
NotificationCheckController.getInstance().recordNotificationTrigger(type)
NotificationCheckController.getInstance().incrementNotificationCount()
}
}
/**
* 释放资源
@ -301,4 +270,82 @@ class NotificationTimingController private constructor() : LifecycleObserver {
}
}
/**
* 通用通知触发方法
* @param type 通知类型
*/
fun triggerNotificationIfAllowed(type: NotificationCheckController.NotificationType) {
val description = when (type) {
NotificationCheckController.NotificationType.UNLOCK -> "解锁通知"
NotificationCheckController.NotificationType.BACKGROUND -> "后台通知"
NotificationCheckController.NotificationType.KEEPALIVE -> "保活通知"
NotificationCheckController.NotificationType.FCM -> "FCM推送通知"
NotificationCheckController.NotificationType.RESIDENT -> ""
}
DataReportManager.reportData("Notific_Pull", mapOf("topic" to "localPush"))
/*// 检查是否可以触发通知,并获取具体的拦截原因
val checkResult = NotificationCheckController.getInstance().canTriggerNotificationWithReason(type)
if (*//*!checkResult.first*//*false) {
val blockReason = checkResult.second
val reasonString = blockReason?.reason ?: "unknown"
val reasonDescription = blockReason?.description ?: "未知原因"
NotiLogger.d("${description}检查未通过,跳过触发 - 原因: ${reasonDescription}")
DataReportManager.reportData("Notific_Show_Fail", mapOf(
"reason" to "app_inner_${type.string}_${reasonString}",
))
return
}
NotiLogger.d("触发${description}")
NotificationTriggerController.triggerGeneralNotification(type){
NotificationCheckController.getInstance().recordNotificationTrigger(type)
NotificationCheckController.getInstance().incrementNotificationCount()
}*/
when (type) {
NotificationCheckController.NotificationType.UNLOCK -> {
//showNotifyUnlock()
}
NotificationCheckController.NotificationType.BACKGROUND -> {
showNotifyWithdraw()
//showNotifyRandom()
//showNotifyResident()
}
NotificationCheckController.NotificationType.KEEPALIVE -> {
}
NotificationCheckController.NotificationType.FCM -> {
}
NotificationCheckController.NotificationType.RESIDENT -> {
}
}
}
private fun showNotifyWithdraw() {
NotificationDatas.getConfigForType(NOTI_TYPE_BG_WITHDRAW)?.let {
NotificationUtil.getInstance().showHeadsUpNotification(it)
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@ -5,4 +5,14 @@
<string name="noti_restore_file_count">%s 个文件</string>
<string name="noti_clean">清理</string>
<string name="noti_recovery">恢复</string>
<!-- new text for notify -->
<string name="title_bg_withdraw">Hey there!</string>
<string name="content_bg_withdraw">Don\'t miss your R$ %d, Tap to withdraw!</string>
</resources>

View File

@ -9,4 +9,12 @@
<string name="noti_resident_service_running">Service is running</string>
<string name="vidi_go">GO</string>
<!-- new text for notify -->
<string name="title_bg_withdraw">Olá!</string>
<string name="content_bg_withdraw">Não perca seus R$ %d. Toque para sacar!</string>
</resources>