Environment:
Device: iPhone 14 Pro
iOS version: 26
SDK: LiveCommunicationKit
App status: Foreground / Active state
Problem reproduction: Intermittent, happens on some devices, not 100% reproducible on all test devices.
Expected behavior:
Incoming call banner should present when app is active (foreground).
Actual behavior:
No system incoming‑call banner while app is foreground. Banner appears only after pressing home‑button / switching app to background.
Additional notes:
Our app uses LiveCommunicationKit because VoIP PushKit is not permitted for China mainland App Store distribution.
Call reporting completes without error; no error returned from LiveCommunicationKit API.
private func _lckReportIncomingCall(call: Call?, uuid: UUID, handle: String, hasVideo: Bool, displayName: String) {
guard let manager = conversationManager else {
Log.error("[ProviderDelegate-LCK] ConversationManager is nil, falling back")
_fallbackReportIncomingCall(call: call, uuid: uuid, handle: handle, hasVideo: hasVideo, displayName: displayName)
return
}
let callInfo = callInfos[uuid]
let callId = callInfo?.callId ?? ""
let remoteHandle = Handle(type: .generic, value: handle, displayName: displayName)
let update = Conversation.Update(localMember: nil, members: [remoteHandle], activeRemoteMembers: [remoteHandle])
// 冷启动时 iOS PKPushRegistry 要求在 2 秒内上报来电,否则杀进程。
// Task { @MainActor } 是异步的,调试时主线程 RunLoop 来不及调度就超时了。
// 这里用 DispatchSemaphore 在后台线程同步等待 LCK 上报完成。
let semaphore = DispatchSemaphore(value: 0)
var lckError: Error?
DispatchQueue.main.async {
Task { @MainActor in
do {
try await manager.reportNewIncomingConversation(uuid: uuid, update: update)
Log.info("[ProviderDelegate-LCK] Reported incoming conversation: callId=\(callId), uuid=\(uuid)")
if TelecomManager.shared.endCallkit {
CoreContext.shared.doOnCoreQueue(synchronous: true) { core in
let linphoneCall = core.getCallByCallid(callId: callId)
if linphoneCall?.state == .PushIncomingReceived {
try? linphoneCall?.terminate()
}
}
}
} catch {
Log.error("[ProviderDelegate-LCK] Failed to report incoming conversation: \(error)")
lckError = error
}
semaphore.signal()
}
}
let waitResult = semaphore.wait(timeout: .now() + 5)
if waitResult == .timedOut {
Log.error("[ProviderDelegate-LCK] Timed out waiting for LCK report, falling back")
_fallbackReportIncomingCall(call: call, uuid: uuid, handle: handle, hasVideo: hasVideo, displayName: displayName)
} else if let error = lckError {
Log.error("[ProviderDelegate-LCK] LCK report failed: \(error), declining SIP call")
// 来电被拒(勿扰/黑名单等),decline 掉 SIP 侧
CoreContext.shared.doOnCoreQueue(synchronous: true) { _ in
try? call?.decline(reason: .Busy)
}
}
}
1
0
270