From b59b8583529fa57c1b46ba64d88416d2e2256407 Mon Sep 17 00:00:00 2001 From: renhaoting <370797079@qq.com> Date: Mon, 29 Dec 2025 15:29:11 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20handsUp=E9=80=9A=E7=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/newUtil/NotificationUtil.kt | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/notification/src/main/java/com/remax/notification/newUtil/NotificationUtil.kt b/notification/src/main/java/com/remax/notification/newUtil/NotificationUtil.kt index cbfaf75..1c17cd5 100644 --- a/notification/src/main/java/com/remax/notification/newUtil/NotificationUtil.kt +++ b/notification/src/main/java/com/remax/notification/newUtil/NotificationUtil.kt @@ -8,6 +8,7 @@ import android.graphics.BitmapFactory import android.graphics.Color import android.os.Build import android.widget.RemoteViews +import androidx.annotation.RequiresApi import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import com.ama.core.architecture.util.permission.PermissionUtil @@ -278,6 +279,126 @@ class NotificationUtil private constructor() { showNotification(notificationId, notification) } + + + + /** + * 显示应用在后台时的顶部悬浮通知(Heads-up Notification) + * 此方法会自动处理Android版本的兼容性 + * + * @param channelId 通知渠道ID(Android 8.0+必须) + * @param channelName 通知渠道名称(Android 8.0+必须) + * @param title 通知标题 + * @param content 通知内容 + * @param smallIcon 小图标资源ID + * @param intent 点击通知后要执行的Intent(可选) + * @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") + } + + val builder = NotificationCompat.Builder(context, channelId) + + // 2. 设置通知基本内容 + builder.setContentTitle(title) + .setContentText(content) + .setSmallIcon(smallIcon) + .setAutoCancel(true) + .setWhen(System.currentTimeMillis()) + + // 3. 处理点击意图 + val pendingIntent = intent?.let { + PendingIntent.getActivity(context, 0, it, PendingIntent.FLAG_IMMUTABLE) + } + pendingIntent?.let { builder.setContentIntent(it) } + + // 4. 版本兼容性配置 - 这是触发Heads-up的关键 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + // Android 8.0+ 使用通知渠道 + createHeadsUpNotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH) + // 设置高重要性(会触发顶部悬浮) + builder.setPriority(NotificationCompat.PRIORITY_MAX) + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + // Android 5.0-7.1 使用优先级设置 + builder.setPriority(NotificationCompat.PRIORITY_MAX) + // 添加声音和振动确保触发顶部悬浮 + builder.setDefaults(NotificationCompat.DEFAULT_ALL) + } else { + // Android 5.0以下版本不支持Heads-up,使用普通高优先级通知 + builder.setPriority(NotificationCompat.PRIORITY_HIGH) + builder.setDefaults(NotificationCompat.DEFAULT_ALL) + } + + // 5. 可选:全屏意图(用于最高优先级场景) + if (useFullScreenIntent && pendingIntent != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + builder.setFullScreenIntent(pendingIntent, true) + } + + // 6. 发送通知 + showNotification(notificationId, builder.build()) + } + + /** + * 创建用于顶部悬浮的高重要性通知渠道(Android 8.0+) + */ + @RequiresApi(Build.VERSION_CODES.O) + private fun createHeadsUpNotificationChannel(channelId: String, channelName: String, importance: Int) { + // 检查是否已存在相同ID的渠道,避免重复创建 + if (notificationManager.getNotificationChannel(channelId) != null) { + return + } + + val channel = NotificationChannel( + channelId, + channelName, + importance + ).apply { + description = "应用在后台时的重要通知,会以悬浮形式显示" + enableLights(true) + lightColor = Color.RED + enableVibration(true) + vibrationPattern = longArrayOf(0, 250, 250, 250) + lockscreenVisibility = Notification.VISIBILITY_PUBLIC + // 设置锁定屏幕上的可见性 + } + + notificationManager.createNotificationChannel(channel) + } + + + + + + + + + + + + + + + + + + + + + + private fun showNotification(notificationId: Int = System.currentTimeMillis().toInt(), notification: Notification) {