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

Android Oreo及以上版本自定义通知音和振动失效问题排查

问题分析与修复方案

你的代码在Android Oreo及以上版本无法生效的核心问题是每次发送通知时重复创建NotificationChannel——Android系统规定,NotificationChannel一旦创建,后续调用createNotificationChannel()不会修改已有channel的配置(包括声音、振动等)。如果第一次调用sendNotif时isSoundEnabled或isVibrationEnabled为false,后续即使传入true,channel的配置也不会更新,导致通知始终无声音/振动。

除此之外还有几个细节问题需要修正:

具体问题点

  1. NotificationChannel创建时机错误
    你在每次发送通知时都创建channel,正确做法是在App初始化阶段(比如Application的onCreate()或主Activity的onCreate())只创建一次,后续发送通知直接复用已创建的channel。

  2. 振动设置冗余
    当isVibrationEnabled为false时,设置vibrationEmpty = {0}是多余的,直接调用channel.enableVibration(false)即可禁用振动。

  3. PendingIntent Flag适配问题
    Android 12+(API 31)要求PendingIntent必须指定FLAG_IMMUTABLE或FLAG_MUTABLE,你当前使用的FLAG_CANCEL_CURRENT在高版本可能会抛出异常。

修复后的代码示例

第一步:在App初始化时创建NotificationChannel

将channel创建逻辑移到Application类或主Activity的onCreate中:

// 在Application的onCreate()中执行
private void createNotificationChannel() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        String channelName = "EEE";
        String channelId = "CHANNEL_1";
        NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH);
        channel.enableLights(true);
        
        // 初始化时设置默认的声音和振动配置
        NotificationManager notificationManager = getSystemService(NotificationManager.class);
        notificationManager.createNotificationChannel(channel);
    }
}

第二步:修改sendNotif方法,移除重复创建channel的逻辑

private void sendNotif(String title, String text, boolean isSoundEnabled, boolean isVibrationEnabled) {
    NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
    String channelId = "CHANNEL_1";
    long[] vibrationPattern = new long[]{40, 75, 75, 75, 75, 75, 75, 750};
    Uri soundUri = Uri.parse("android.resource://" + context.getPackageName() + "/" + R.raw.notification);

    Intent intent = new Intent(context, ActivityOne.class);
    // 适配Android 12+的PendingIntent Flag
    int flag = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ? PendingIntent.FLAG_IMMUTABLE : PendingIntent.FLAG_CANCEL_CURRENT;
    PendingIntent pIntent = PendingIntent.getActivity(context, 0, intent, flag);

    NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle(title)
            .setContentText(text)
            .setPriority(NotificationCompat.PRIORITY_MAX)
            .setAutoCancel(true)
            .setContentIntent(pIntent);

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
        // 低版本直接设置声音和振动
        if (isSoundEnabled) {
            builder.setSound(soundUri);
        }
        if (isVibrationEnabled) {
            builder.setVibrate(vibrationPattern);
        } else {
            builder.setVibrate(new long[]{0});
        }
    } else {
        // Oreo+版本注意:代码无法动态修改已创建channel的声音/振动配置
        // 若需根据参数动态切换,需提前创建多个不同配置的channel(例如CHANNEL_1_SOUND_ON、CHANNEL_1_SOUND_OFF)
        // 发送通知时根据isSoundEnabled和isVibrationEnabled选择对应channelId
    }

    notificationManager.notify(new Random().nextInt(10000), builder.build());
}

关键说明

Android Oreo+的NotificationChannel设计核心是让用户拥有更高控制权,一旦channel创建,开发者无法通过代码修改其声音、振动、重要性等核心配置,只能引导用户到系统设置页面修改。如果需要动态切换通知的声音和振动状态,正确做法是提前创建多个不同配置的NotificationChannel,发送通知时根据参数选择对应的channelId。

另外,可再次确认R.raw.notification文件是否存在且格式支持(推荐mp3或wav格式),低版本正常说明文件本身无问题,但路径需确保正确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 23:30:57