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

iOS VoIP应用中如何用PJSIP挂断振铃状态的呼叫?

Fixing Ringing Call Hangup Issues in PJSIP-based iOS VoIP Apps

Hey there, I’ve wrestled with this exact problem before while building a PJSIP iOS VoIP app—nothing’s more annoying than trying to hang up a ringing call and having it just keep going! Let’s break down the common fixes that got it working for me.

First, Understand the Ringing Call States

PJSIP categorizes ringing calls into two key states depending on direction:

  • Outgoing ringing: Your app initiated the call, and the recipient’s device is ringing. The local call state here is PJSUA_CALL_STATE_CALLING.
  • Incoming ringing: Someone’s calling your app, and your device is ringing. The local call state here is PJSUA_CALL_STATE_INCOMING.

The mistake many devs make is only handling hangup for the PJSUA_CALL_STATE_CONFIRMED (connected) state—you need to explicitly handle these ringing states too.

Fix 1: Use the Correct API for the Call Direction

For Outgoing Ringing Calls (You’re the Caller)

To hang up an outgoing call that’s still ringing, use pjsua_call_hangup() directly with the correct call ID. Make sure you saved the call ID returned by pjsua_call_make_call() when you initiated the call!

// Replace `yourCallId` with the actual call ID from your outgoing call
pj_status_t hangupStatus = pjsua_call_hangup(yourCallId, 0, NULL, NULL);
if (hangupStatus != PJ_SUCCESS) {
    NSLog(@"Failed to hangup outgoing ringing call: Status code %d", hangupStatus);
}

For Incoming Ringing Calls (You’re the Callee)

You can either hang up directly or send a decline signal. Both work, but sending a decline is more polite for SIP networks:

// Option 1: Decline the incoming ringing call (recommended)
pj_status_t declineStatus = pjsua_call_answer(yourCallId, PJSUA_SC_DECLINE, NULL, NULL);

// Option 2: Hang up directly
// pj_status_t declineStatus = pjsua_call_hangup(yourCallId, PJSUA_SC_DECLINE, NULL, NULL);

if (declineStatus != PJ_SUCCESS) {
    NSLog(@"Failed to decline incoming ringing call: Status code %d", declineStatus);
}

Fix 2: Always Call PJSIP APIs on the Right Thread

PJSIP is not thread-safe—never call PJSIP APIs directly from the main thread. You need to run hangup/decline calls on a background thread or use PJSIP’s own thread scheduling.

Using GCD to Run on a Background Queue

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // Your hangup/decline code here
    pj_status_t status = pjsua_call_hangup(yourCallId, 0, NULL, NULL);
    if (status != PJ_SUCCESS) {
        NSLog(@"Hangup failed: %d", status);
    }
});

Using PJSIP’s Thread Scheduler (More Reliable)

If you want to ensure full compatibility with PJSIP’s internal threading, use pjsua_thread_schedule():

// Schedule the hangup to run on PJSIP's worker thread
pjsua_thread_schedule(0, hangupRingingCall, (void*)yourCallId, NULL);

// Define the helper function to run the hangup
static int hangupRingingCall(pj_timer_heap_t *th, pj_timer_entry *entry) {
    pjsua_call_id callId = (pjsua_call_id)(entry->user_data);
    pj_status_t status = pjsua_call_hangup(callId, 0, NULL, NULL);
    
    if (status != PJ_SUCCESS) {
        PJ_LOG(3, (__FILE__, "Failed to hangup ringing call. Status: %d", status));
    }
    return 0;
}

Fix 3: Verify Your Call State Handling

Double-check your on_call_state callback to make sure you’re not blocking hangup actions for ringing states. For example, if your hangup button is only enabled when the call is connected, that’s why it’s not working during ringing—update your UI state to enable hangup/decline when the call is in CALLING or INCOMING states.

- (void)onCallState:(pjsua_call_id)callId info:(pjsua_call_info*)callInfo {
    switch (callInfo->state) {
        case PJSUA_CALL_STATE_CALLING:
            // Enable hangup button for outgoing ringing
            [self updateHangupButtonEnabled:YES];
            break;
        case PJSUA_CALL_STATE_INCOMING:
            // Enable decline/hangup button for incoming ringing
            [self updateDeclineButtonEnabled:YES];
            break;
        case PJSUA_CALL_STATE_CONFIRMED:
            // Enable hangup button for connected call
            [self updateHangupButtonEnabled:YES];
            break;
        default:
            [self updateHangupButtonEnabled:NO];
            [self updateDeclineButtonEnabled:NO];
            break;
    }
}

Quick Troubleshooting Checks

  • Did you save the correct call ID when initiating/receiving the call? It’s easy to mix up call IDs if you have multiple calls in progress.
  • Are you getting any PJSIP error codes? Look up the status code in the PJSIP docs to pinpoint the issue (e.g., PJ_EINVAL means invalid parameters like a bad call ID).
  • Have you registered your call callbacks correctly? Missing callbacks might mean you’re not updating state properly.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:52:09