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

来电服务触发应用后台自动启动问题及仿WhatsApp优化需求

问题分析与解决方案

这是代码实现导致的问题,并非系统默认行为。

问题根源

  1. 广播接收器收到来电广播后,直接调用startIncomingCall启动CallActivity,且给Intent添加了FLAG_ACTIVITY_NEW_TASK标记。该标记会让Activity在新的任务栈中启动,通话结束后,系统会将这个任务栈带到前台,导致应用被自动唤起。
  2. 通话结束后未正确处理任务栈状态,没有让系统回到通话前的前台应用。

解决方法

1. 使用系统通知唤起通话(推荐,符合WhatsApp逻辑)

不要直接通过广播启动Activity,而是发送高优先级来电通知,用户点击通知后再进入通话界面。这样应用在后台时只会显示通知,不会被直接唤起。

修改后的代码示例:

private val callReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent?) {
        val callId = intent?.getStringExtra(KEY_CALL_ID)
        val isVideoCall = intent?.getBooleanExtra(KEY_IS_VIDEO, false) ?: false
        callId?.let {
            showIncomingCallNotification(context, callId, isVideoCall)
        }
    }
}

fun showIncomingCallNotification(context: Context, callId: String, videoEnabled: Boolean) {
    // 启动通话界面的PendingIntent
    val acceptIntent = Intent(context, CallActivity::class.java).apply {
        putExtra(CallService.VIDEO_ENABLED, videoEnabled)
        putExtra(INCOMING_CALL, true)
        putExtra(CALL_ID, callId)
        addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
    }
    val acceptPendingIntent = PendingIntent.getActivity(
        context,
        0,
        acceptIntent,
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )

    // 挂断通话的PendingIntent(可自定义广播或服务处理挂断逻辑)
    val rejectIntent = Intent(context, CallRejectReceiver::class.java).apply {
        putExtra(CALL_ID, callId)
    }
    val rejectPendingIntent = PendingIntent.getBroadcast(
        context,
        1,
        rejectIntent,
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )

    // 构建来电通知
    val notification = NotificationCompat.Builder(context, "INCOMING_CALL_CHANNEL")
        .setSmallIcon(R.drawable.ic_call_icon)
        .setContentTitle("来电提醒")
        .setContentText("${if (videoEnabled) "视频" else "语音"}通话请求")
        .setPriority(NotificationCompat.PRIORITY_HIGH)
        .setCategory(NotificationCompat.CATEGORY_CALL)
        .addAction(R.drawable.ic_accept, "接听", acceptPendingIntent)
        .addAction(R.drawable.ic_reject, "挂断", rejectPendingIntent)
        .setFullScreenIntent(acceptPendingIntent, true) // 全屏显示来电界面(可选)
        .build()

    NotificationManagerCompat.from(context).notify(1, notification)
}

2. 调整Activity启动标记与结束逻辑

如果必须通过广播启动Activity,需调整Intent标记,并在通话结束时主动将任务栈移至后台:

  • 移除FLAG_ACTIVITY_NEW_TASK,或结合FLAG_ACTIVITY_NO_HISTORY、FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS使用;
  • 在通话结束时调用finishAndRemoveTask()彻底移除当前任务栈,避免应用留在前台:
// CallActivity中结束通话的逻辑
fun onCallEnded() {
    // 执行结束通话的业务操作
    finishAndRemoveTask() // 移除任务栈,回到之前的应用
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 10:09:26