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

Android持续来电类型通知失效问题求助

问题分析与修复方案

你的代码存在几个关键问题,导致通知无法持续显示、铃声提前停止:

  1. 冲突的通知属性:同时设置setOngoing(true)和setAutoCancel(true),后者会让通知点击后自动取消,与来电通知持续显示的需求矛盾。
  2. 缺少全屏Intent配置:普通通知会在几秒后自动缩小,而Teams/WhatsApp这类来电通知需要触发全屏交互界面,依赖setFullScreenIntent才能保持通知展开状态并强制系统弹出交互窗口。
  3. 铃声播放依赖系统限制:仅靠FLAG_INSISTENT在高版本Android中可能被系统拦截,需要结合独立的铃声播放逻辑保障持续响铃。

修复后的完整代码

private void showIncomingCallNotification(Context context) {
    String channelId = "call_channel";

    // 1. 配置全屏来电界面Intent
    Intent fullScreenIntent = new Intent(context, IncomingCallActivity.class);
    PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(
            context, 1, fullScreenIntent, 
            PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);

    // 2. 配置通知点击跳转Intent
    Intent notificationIntent = new Intent(context, MainActivity.class);
    PendingIntent contentIntent = PendingIntent.getActivity(
            context, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);

    Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, channelId)
            .setSmallIcon(R.drawable.ic_launcher_background)
            .setContentTitle("Incoming Call")
            .setContentText("You have an incoming call")
            .setCategory(Notification.CATEGORY_CALL)
            .setOngoing(true) // 强制通知持续显示,无法手动清除
            .setPriority(NotificationCompat.PRIORITY_MAX)
            .setContentIntent(contentIntent)
            .setFullScreenIntent(fullScreenPendingIntent, true) // 触发全屏来电界面
            .setVisibility(NotificationCompat.VISIBILITY_PUBLIC); // 锁屏显示完整通知内容

    // 3. 创建通知渠道(仅首次执行时创建)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        // 避免重复创建渠道导致异常
        if (notificationManager.getNotificationChannel(channelId) == null) {
            CharSequence channelName = "Incoming Calls";
            // 来电通知需要最高重要性,才能触发全屏Intent
            int importance = NotificationManager.IMPORTANCE_HIGH;

            NotificationChannel notificationChannel = new NotificationChannel(channelId, channelName, importance);
            notificationChannel.enableVibration(true);
            long[] pattern = {0, 1000, 500, 1000};
            notificationChannel.setVibrationPattern(pattern);
            
            // 配置符合通话场景的音频属性
            AudioAttributes att = new AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION_RINGTONE)
                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                    .build();
            
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                notificationChannel.setAllowBubbles(true);
            }
            notificationChannel.setLockscreenVisibility(NotificationCompat.VISIBILITY_PUBLIC);
            notificationChannel.setSound(ringtoneUri, att);
            notificationManager.createNotificationChannel(notificationChannel);
        }
    } else {
        notificationBuilder.setSound(ringtoneUri);
        notificationBuilder.setDefaults(Notification.DEFAULT_VIBRATE);
        notificationBuilder.setPriority(Notification.PRIORITY_MAX);
    }

    Notification notification = notificationBuilder.build();
    notification.flags |= Notification.FLAG_INSISTENT; // 低版本系统强制铃声重复播放

    NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(0, notification);

    // 4. 独立播放铃声(高版本系统下保障持续响铃)
    Ringtone ringtone = RingtoneManager.getRingtone(context, ringtoneUri);
    if (!ringtone.isPlaying()) {
        ringtone.setStreamType(AudioManager.STREAM_RING);
        ringtone.play();
    }
}

关键修改点说明

  1. 移除setAutoCancel(true):来电通知需要持续显示至用户主动处理,因此不能设置自动取消。
  2. 添加setFullScreenIntent:
    • 传入指向来电交互界面(IncomingCallActivity)的PendingIntent,系统会在锁屏或后台状态下弹出全屏界面,同时保持通知展开状态。
    • 第二个参数设为true,确保应用在后台时也能触发全屏Intent。
  3. 优化通知渠道创建逻辑:先检查渠道是否存在,避免重复创建引发异常。
  4. 独立铃声播放:仅依赖通知的setSound可能被高版本系统限制,单独使用Ringtone类播放铃声,确保持续响铃直到用户处理。
  5. 调整音频属性:使用USAGE_VOICE_COMMUNICATION_RINGTONE替代USAGE_NOTIFICATION_RINGTONE,更贴合来电场景,提升系统优先级。

额外注意事项

  • 权限申请:
    • Android 12及以上需动态申请POST_NOTIFICATIONS权限,Manifest中添加:<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />。
    • 若需读取通话状态,需申请READ_PHONE_STATE权限。
  • 来电界面配置:IncomingCallActivity需设置为全屏无标题栏,Manifest中添加android:showOnLockScreen="true"(Android 10及以下),或通过KeyguardManager解锁屏幕。
  • 停止铃声与通知:用户处理来电(接听/挂断)时,需调用ringtone.stop()停止铃声,并执行notificationManager.cancel(0)取消通知。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 07:55:19