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

Android原生C++端WebRTC PeerConnection初始化与连接流程问询

Android WebRTC C++ 客户端连接后续步骤(接收Offer后)

一、确认PeerConnectionFactory的Android适配配置

之前默认参数崩溃的核心原因是Android端必须指定专属的音频设备模块与线程配置,以下是可靠的初始化代码片段:

// 从JNI调用中获取环境与上下文
JNIEnv* env = ...;
jobject android_context = ...;

// 创建Android专属音频设备模块
rtc::scoped_refptr<webrtc::AudioDeviceModule> adm =
    webrtc::CreateAndroidAudioDeviceModule(env, android_context);

// 初始化WebRTC所需线程
rtc::Thread* network_thread = rtc::Thread::CreateWithSocketServer();
rtc::Thread* worker_thread = rtc::Thread::Create();
rtc::Thread* signaling_thread = rtc::Thread::Create();
network_thread->Start();
worker_thread->Start();
signaling_thread->Start();

// 构建PeerConnectionFactory依赖
webrtc::PeerConnectionFactoryDependencies dependencies;
dependencies.network_thread = network_thread;
dependencies.worker_thread = worker_thread;
dependencies.signaling_thread = signaling_thread;
dependencies.adm = adm;
dependencies.video_encoder_factory = nullptr; // 纯数据通道无需视频
dependencies.video_decoder_factory = nullptr;

// 创建工厂实例
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory =
    webrtc::CreatePeerConnectionFactory(std::move(dependencies));

二、创建PeerConnection并实现观察者

必须实现PeerConnectionObserver接口处理连接回调,核心是监听ICE候选生成、连接状态、数据通道事件:

class PCObserver : public webrtc::PeerConnectionInterface::Observer,
                   public webrtc::DataChannelInterface::Observer {
public:
    void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) override {
        // 将本地生成的ICE候选转为字符串,通过Unix Socket发送给Windows服务器
        std::string candidate_sdp;
        candidate->ToString(&candidate_sdp);
        // 此处添加Unix Socket发送逻辑
    }

    void OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> channel) override {
        // 接收服务器主动创建的数据通道,保存用于收发数据
        data_channel_ = channel;
        data_channel_->RegisterObserver(this);
    }

    void OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState state) override {
        // 监听连接状态,如state变为kIceConnectionConnected则可开始数据传输
        if (state == webrtc::PeerConnectionInterface::kIceConnectionConnected) {
            // 连接建立成功后的逻辑
        }
    }

    // 实现其他必填纯虚函数(空实现即可)
    void OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState) override {}
    void OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState) override {}
    void OnAddStream(rtc::scoped_refptr<webrtc::MediaStreamInterface>) override {}
    void OnRemoveStream(rtc::scoped_refptr<webrtc::MediaStreamInterface>) override {}
    void OnDataChannelStateChange() override {}
    void OnMessage(const webrtc::DataBuffer& buffer) override {
        // 接收服务器发送的数据
        std::string recv_data(reinterpret_cast<const char*>(buffer.data.data()), buffer.data.size());
    }

private:
    rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel_;
};

// 创建PeerConnection实例
webrtc::PeerConnectionInterface::RTCConfiguration config;
// 若服务器使用STUN/TURN,添加到config.servers,示例:
// config.servers.push_back(webrtc::PeerConnectionInterface::IceServer{"stun:stun.l.google.com:19302"});

rtc::scoped_refptr<PCObserver> observer = new rtc::RefCountedObject<PCObserver>();
rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_conn =
    factory->CreatePeerConnection(config, nullptr, nullptr, observer.get());

三、设置远程SDP Offer

解析收到的服务器Offer字符串,设置到PeerConnection:

// 从Unix Socket接收的服务器SDP Offer字符串
std::string remote_offer_sdp = ...;
webrtc::SdpParseError parse_error;
rtc::scoped_refptr<webrtc::SessionDescriptionInterface> remote_offer =
    webrtc::CreateSessionDescription(webrtc::SdpType::kOffer, remote_offer_sdp, &parse_error);

if (!remote_offer) {
    // 处理SDP解析失败逻辑
    return;
}

peer_conn->SetRemoteDescription(
    webrtc::CreateSetSessionDescriptionObserver(
        [](webrtc::SessionDescriptionInterface*) {},
        [](const std::string& err) { /* 处理设置失败 */ }),
    remote_offer.release());

四、添加收到的ICE候选

逐个解析并添加服务器发送的20个ICE候选:

// 遍历收到的ICE候选字符串列表
for (const std::string& candidate_str : received_ice_candidates) {
    webrtc::SdpParseError err;
    rtc::scoped_refptr<webrtc::IceCandidateInterface> candidate =
        webrtc::CreateIceCandidate("", 0, candidate_str, &err);
    if (candidate) {
        peer_conn->AddIceCandidate(candidate.get());
    } else {
        // 处理单个候选解析失败逻辑
    }
}

五、生成并发送SDP Answer

创建Answer并设置本地描述,之后将Answer发送给服务器:

peer_conn->CreateAnswer(
    webrtc::CreateCreateSessionDescriptionObserver(
        [peer_conn, observer](webrtc::SessionDescriptionInterface* desc) {
            // 设置本地描述
            peer_conn->SetLocalDescription(
                webrtc::CreateSetSessionDescriptionObserver(
                    [desc, observer]() {
                        // 将Answer转为字符串,通过Unix Socket发送给服务器
                        std::string answer_sdp;
                        desc->ToString(&answer_sdp);
                        // 此处添加Unix Socket发送逻辑
                    },
                    [](const std::string& err) { /* 处理设置失败 */ }),
                desc);
        },
        [](const std::string& err) { /* 处理Answer创建失败 */ }),
    webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());

六、数据通道的使用

场景1:服务器主动创建数据通道

在PCObserver::OnDataChannel回调中已收到通道,直接使用即可:

// 发送数据示例
std::string send_data = "Hello from Android C++";
webrtc::DataBuffer buffer(rtc::CopyOnWriteBuffer(send_data.data(), send_data.size()));
observer->data_channel_->Send(buffer);

场景2:客户端主动创建数据通道

在连接建立后(如OnIceConnectionChange触发连接成功状态)调用:

webrtc::DataChannelInit init;
init.ordered = true; // 保证数据传输顺序
rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel =
    peer_conn->CreateDataChannel("data_channel", &init);
data_channel->RegisterObserver(observer.get());

// 发送数据
std::string send_data = "Initiate data channel from client";
webrtc::DataBuffer buffer(rtc::CopyOnWriteBuffer(send_data.data(), send_data.size()));
data_channel->Send(buffer);

关键注意事项

  • 所有WebRTC异步操作必须在对应线程执行:信号操作在signaling_thread,网络操作在network_thread,JNI调用需切换到对应线程执行
  • AndroidManifest需添加权限:INTERNET、ACCESS_NETWORK_STATE,纯数据通道无需音频权限,但必须初始化AudioDeviceModule
  • Unix Socket传输SDP与ICE候选时,需保证字符串完整无截断

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 16:15:31