You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android最高优先级本地通知开发问题:需支持免打扰及锁屏显示

问题解决方案

一、修复通知锁屏显示、声音及震动问题

你的代码存在几个关键问题导致通知无锁屏显示、无声音震动:

  1. 通知渠道优先级不足
    Android 8.0+ 中,通知的优先级由NotificationChannel的importance决定,而非NotificationCompat.Builder的priority。你当前设置的IMPORTANCE_DEFAULT优先级不够,无法触发锁屏显示、声音和震动。需要将其改为IMPORTANCE_HIGH或IMPORTANCE_MAX(后者为紧急通知,会弹出全屏提示)。

  2. 未配置震动属性
    当前代码仅设置了声音,未开启震动功能,需要为渠道添加震动配置。

  3. 渠道创建后无法修改优先级
    注意:通知渠道一旦创建,importance等核心属性无法通过代码修改,若之前已安装过应用,需卸载重装或清除应用数据才能生效。

修改后的createNotificationChannelWithSound方法:

@RequiresApi(api = Build.VERSION_CODES.O)
public static String createNotificationChannelWithSound(Context context, String channelId, String channelName, Uri rawPathUri) {
    // 使用IMPORTANCE_HIGH确保高优先级
    NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH);
    channel.setLightColor(Color.BLUE);
    // 设置锁屏可见性,PRIVATE表示隐藏敏感内容,PUBLIC显示全部内容
    channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
    
    // 配置声音属性
    AudioAttributes att = new AudioAttributes.Builder()
            .setUsage(AudioAttributes.USAGE_NOTIFICATION)
            .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
            .build();
    channel.setSound(rawPathUri, att);
    
    // 添加震动配置
    channel.enableVibration(true);
    channel.setVibrationPattern(new long[]{0, 1000, 500, 1000}); // 震动节奏:立即震动1秒,停0.5秒,再震动1秒
    
    channel.setShowBadge(false);
    NotificationManager service = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    service.createNotificationChannel(channel);
    return channelId;
}

同时,在sendNotification方法中,补充设置通知可见性(与渠道配置对应):

with(builder) {
    // ... 原有代码
    priority = NotificationCompat.PRIORITY_MAX // 兼容8.0以下版本
    setVisibility(NotificationCompat.VISIBILITY_PRIVATE) // 对应渠道的锁屏可见性
    setContentIntent(intent)
}

二、实现静音/免打扰模式下接收通知

要让通知在静音、免打扰模式下正常接收,需完成两步:

  1. 申请绕过免打扰权限
    在AndroidManifest.xml中添加权限:
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
  1. 检查并请求权限
    在发送通知前,检查是否已获得权限,若未获得,跳转至系统设置页面让用户开启:
private fun canBypassDnd(): Boolean {
    val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        notificationManager.isNotificationPolicyAccessGranted
    } else {
        true // 6.0以下无需权限
    }
}

private fun requestBypassDndPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        val intent = Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS)
        startActivity(intent)
    }
}

发送通知前调用:

if (!canBypassDnd()) {
    requestBypassDndPermission()
    return
}
// 继续发送通知逻辑

三、实现每日至多显示1次通知

使用SharedPreferences记录上次发送通知的日期,每次发送前判断是否当天已发送:

private fun shouldSendToday(): Boolean {
    val sp = getSharedPreferences("NotificationPrefs", Context.MODE_PRIVATE)
    val lastSendDate = sp.getLong("LastSendDate", 0)
    val today = Calendar.getInstance().apply {
        set(Calendar.HOUR_OF_DAY, 0)
        set(Calendar.MINUTE, 0)
        set(Calendar.SECOND, 0)
        set(Calendar.MILLISECOND, 0)
    }.timeInMillis
    
    return lastSendDate < today
}

private fun markNotificationSentToday() {
    val sp = getSharedPreferences("NotificationPrefs", Context.MODE_PRIVATE)
    val today = Calendar.getInstance().apply {
        set(Calendar.HOUR_OF_DAY, 0)
        set(Calendar.MINUTE, 0)
        set(Calendar.SECOND, 0)
        set(Calendar.MILLISECOND, 0)
    }.timeInMillis
    sp.edit().putLong("LastSendDate", today).apply()
}

在sendNotification方法开头添加判断:

private fun sendNotification(
    notificationId: Int,
    title: String,
    message: String,
    intent: PendingIntent? = null
) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return
    // 检查是否今日已发送
    if (!shouldSendToday()) {
        Timber.d("今日已发送过通知,跳过")
        return
    }
    // 检查免打扰权限
    if (!canBypassDnd()) {
        requestBypassDndPermission()
        return
    }
    Timber.d("sendNotification")
    
    // ... 原有创建通知逻辑
    
    // 发送后标记今日已发送
    markNotificationSentToday()
    notificationManager.notify(notificationId, builder.build())
}

内容的提问来源于stack exchange,提问作者Sunbey13

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 13:18:19