You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android按通知内容设置不同提示音异常问题求助

问题分析与解决方案

你的问题核心在于Android 8.0(API 26+)中NotificationChannel的优先级高于NotificationCompat.Builder的声音设置,且Channel一旦创建后,其核心属性(如声音)无法动态修改——这就是为什么标题含"acknowledge"时仍播放警报音的原因:如果之前已经用同一个Channel ID创建过使用警报音的Channel,后续修改Channel的声音设置会被系统忽略。

另外你代码里重复调用setDefaults()也可能引发冲突,比如setDefaults(Notification.DEFAULT_SOUND)会重置声音为系统默认,但之后调用setSound()虽然能覆盖这个设置,但在O+版本下还是Channel的设置说了算。

修复步骤

1. 拆分不同声音场景为独立的NotificationChannel

因为不同的通知声音需要不同的Channel(Channel的声音属性无法动态修改),所以我们定义两个Channel ID:一个用于警报音场景,一个用于默认音场景。

2. 按需创建对应Channel

在构建通知前,根据标题判断需要使用哪个Channel,并确保该Channel已正确创建(注意:创建Channel时要先判断是否已存在,避免重复操作)。

3. 清理冗余的setDefaults()调用

合并或移除重复的setDefaults(),避免设置冲突。

修复后的完整代码

Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Uri alarmSound = Uri.parse("android.resource://" + getApplicationContext().getPackageName() + "/" + R.raw.siren);

// 定义两个不同的Channel ID,区分警报音和默认音场景
String ALERT_CHANNEL_ID = "com.example.bantay.bantay.alert";
String DEFAULT_CHANNEL_ID = "com.example.bantay.bantay.default";

NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
String targetChannelId = DEFAULT_CHANNEL_ID; // 默认用默认音Channel
PendingIntent targetPendingIntent = pendingIntent3; // 默认对应acknowledge的PendingIntent

// 根据标题判断使用的Channel和PendingIntent
if (title.toLowerCase().contains("1")) {
    targetChannelId = ALERT_CHANNEL_ID;
    targetPendingIntent = pendingIntent;
} else if (title.toLowerCase().contains("2")) {
    targetChannelId = ALERT_CHANNEL_ID;
    targetPendingIntent = pendingIntent1;
} else if (title.toLowerCase().contains("3")) {
    targetChannelId = ALERT_CHANNEL_ID;
    targetPendingIntent = pendingIntent2;
} else if (title.toLowerCase().contains("acknowledge")) {
    targetChannelId = DEFAULT_CHANNEL_ID;
    targetPendingIntent = pendingIntent3;
}

// 创建对应的NotificationChannel(仅在API 26+时需要)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    // 先检查Channel是否已存在,避免重复创建
    if (notificationManager.getNotificationChannel(targetChannelId) == null) {
        NotificationChannel channel;
        AudioAttributes audioAttributes = new AudioAttributes.Builder()
                .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                .setUsage(AudioAttributes.USAGE_NOTIFICATION)
                .build();

        if (targetChannelId.equals(ALERT_CHANNEL_ID)) {
            // 警报音Channel
            channel = new NotificationChannel(ALERT_CHANNEL_ID, "Alert Notifications", NotificationManager.IMPORTANCE_HIGH);
            channel.setSound(alarmSound, audioAttributes);
        } else {
            // 默认音Channel
            channel = new NotificationChannel(DEFAULT_CHANNEL_ID, "Default Notifications", NotificationManager.IMPORTANCE_DEFAULT);
            channel.setSound(defaultSound, audioAttributes);
        }

        channel.enableLights(true);
        channel.setLightColor(Color.RED);
        channel.enableVibration(true);
        channel.setVibrationPattern(new long[]{500, 1000, 500, 1000, 500, 1000});
        notificationManager.createNotificationChannel(channel);
    }
}

// 构建通知
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, targetChannelId);
notificationBuilder.setAutoCancel(true);
notificationBuilder.setPriority(Notification.PRIORITY_MAX);
notificationBuilder.setDefaults(Notification.DEFAULT_VIBRATE); // 只保留震动默认,声音由Channel控制
notificationBuilder.setWhen(System.currentTimeMillis());
notificationBuilder.setSmallIcon(R.drawable.marikinalogo);
notificationBuilder.setContentTitle(title);
notificationBuilder.setContentText(body);
notificationBuilder.setVibrate(new long[]{500, 1000, 500, 1000, 500, 1000});
notificationBuilder.setContentIntent(targetPendingIntent);

// 对于API 26以下的版本,直接设置声音
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
    if (targetChannelId.equals(ALERT_CHANNEL_ID)) {
        notificationBuilder.setSound(alarmSound);
    } else {
        notificationBuilder.setSound(defaultSound);
    }
}

// 发送通知
notificationManager.notify((int) System.currentTimeMillis(), notificationBuilder.build());

关键说明

  • Channel ID的独立性:不同声音必须用不同的Channel ID,因为Channel创建后无法修改声音属性,除非删除旧Channel(不推荐,会影响用户已设置的Channel偏好)。
  • API版本兼容:API 26以下的版本不需要Channel,直接用setSound()即可;API 26+完全依赖Channel的声音设置。
  • 避免重复创建Channel:通过notificationManager.getNotificationChannel(targetChannelId)判断Channel是否存在,避免重复创建导致的无效操作。

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

火山引擎 最新活动