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
相关产品推荐
相关产品推荐

