Android应用中Azure Communication Service用户间呼叫连接失败问题咨询
Azure Communication Service Android视频通话连接问题排查
我正在开发基于Azure Communication Service的Android视频通话应用,参考官方教程修改代码。教程里用CLI/Portal生成的单用户访问令牌作为呼叫ID发起呼叫,但我给两个用户分别配置Portal生成的令牌,修改代码传入两个令牌作为呼叫参与者后,模拟器和真机测试都无法建立连接。
教程原启动呼叫代码
private void startCall() { Context context = this.getApplicationContext(); EditText callIdView = findViewById(R.id.call_id); String callId = callIdView.getText().toString(); ArrayList<CommunicationIdentifier> participants = new ArrayList<CommunicationIdentifier>(); List<VideoDeviceInfo> cameras = deviceManager.getCameras(); StartCallOptions options = new StartCallOptions(); if(!cameras.isEmpty()) { currentCamera = getNextAvailableCamera(null); currentVideoStream = new LocalVideoStream(currentCamera, context); LocalVideoStream[] videoStreams = new LocalVideoStream[1]; videoStreams[0] = currentVideoStream; VideoOptions videoOptions = new VideoOptions(videoStreams); options.setVideoOptions(videoOptions); showPreview(currentVideoStream); } participants.add(new CommunicationUserIdentifier(callId)); call = callAgent.startCall( context, participants, options); //Subscribe to events on updates of call state and remote participants remoteParticipantUpdatedListener = this::handleRemoteParticipantsUpdate; onStateChangedListener = this::handleCallOnStateChanged; call.addOnRemoteParticipantsUpdatedListener(remoteParticipantUpdatedListener); call.addOnStateChangedListener(onStateChangedListener); }
我的修改后代码
private void startCall(String whoCall, String whoCalled) { Context context = this.getApplicationContext(); ArrayList<CommunicationIdentifier> participants = new ArrayList<CommunicationIdentifier>(); List<VideoDeviceInfo> cameras = deviceManager.getCameras(); StartCallOptions options = new StartCallOptions(); if(!cameras.isEmpty()) { currentCamera = getNextAvailableCamera(null); currentVideoStream = new LocalVideoStream(currentCamera, context); LocalVideoStream[] videoStreams = new LocalVideoStream[1]; videoStreams[0] = currentVideoStream; VideoOptions videoOptions = new VideoOptions(videoStreams); options.setVideoOptions(videoOptions); showPreview(currentVideoStream); } participants.add(new CommunicationUserIdentifier(whoCall)); participants.add(new CommunicationUserIdentifier(whoCalled)); call = callAgent.startCall( context, participants, options); //Subscribe to events on updates of call state and remote participants remoteParticipantUpdatedListener = this::handleRemoteParticipantsUpdate; onStateChangedListener = this::handleCallOnStateChanged; call.addOnRemoteParticipantsUpdatedListener(remoteParticipantUpdatedListener); call.addOnStateChangedListener(onStateChangedListener); callButton.setVisibility(View.INVISIBLE); funStuffButton.setVisibility((View.VISIBLE)); hangupButton.setVisibility(View.VISIBLE); }
其中whoCall与whoCalled为从Portal获取的两个用户访问令牌,通过单选按钮设置呼叫对象。我存在以下疑问:
- 是否需要双方使用同一个令牌?若如此,如何实现用户间呼叫?
- 是否需要修改令牌在呼叫初始化中的使用逻辑?
解决方案与排查思路
核心误解纠正
用户访问令牌≠用户ID,你混淆了这两个核心概念:
- 令牌是客户端的身份认证凭证,每个用户必须使用自己的专属令牌初始化
CallAgent,而非作为参与者ID传入。 - 呼叫参与者参数需要传入的是对方的Communication User ID,不是令牌。
代码错误修正
你的修改代码把两个令牌都加入参与者列表是完全错误的,正确逻辑如下:
- 初始化CallAgent(每个客户端单独执行)
// 用当前用户的专属令牌初始化CallAgent,完成身份认证 CommunicationTokenCredential credential = new CommunicationTokenCredential("当前用户的访问令牌"); CallAgent callAgent = new CallClient().createCallAgent(context, credential).get();
- 发起呼叫(仅传入对方用户ID)
private void startCall(String targetUserId) { Context context = this.getApplicationContext(); ArrayList<CommunicationIdentifier> participants = new ArrayList<>(); List<VideoDeviceInfo> cameras = deviceManager.getCameras(); StartCallOptions options = new StartCallOptions(); if(!cameras.isEmpty()) { currentCamera = getNextAvailableCamera(null); currentVideoStream = new LocalVideoStream(currentCamera, context); LocalVideoStream[] videoStreams = new LocalVideoStream[1]; videoStreams[0] = currentVideoStream; VideoOptions videoOptions = new VideoOptions(videoStreams); options.setVideoOptions(videoOptions); showPreview(currentVideoStream); } // 仅添加对方的用户ID(不是令牌) participants.add(new CommunicationUserIdentifier(targetUserId)); call = callAgent.startCall( context, participants, options); // 事件订阅逻辑保持不变 remoteParticipantUpdatedListener = this::handleRemoteParticipantsUpdate; onStateChangedListener = this::handleCallOnStateChanged; call.addOnRemoteParticipantsUpdatedListener(remoteParticipantUpdatedListener); call.addOnStateChangedListener(onStateChangedListener); callButton.setVisibility(View.INVISIBLE); funStuffButton.setVisibility(View.VISIBLE); hangupButton.setVisibility(View.VISIBLE); }
排查步骤
- 确认令牌与用户ID的绑定关系:从Portal生成令牌时,每个令牌都对应唯一的Communication User ID,需记录该ID作为呼叫目标,而非使用令牌本身。
- 检查CallAgent初始化:确保两个客户端分别用自己的令牌初始化
CallAgent,禁止共用令牌。 - 查看错误日志:在Android Studio的Logcat中搜索ACS相关错误信息(如认证失败、参与者不存在),直接定位问题原因。
- 验证权限配置:确认应用已申请
INTERNET、CAMERA、RECORD_AUDIO等必要权限,且运行时已授权。 - 回归基础流程测试:先确保单个客户端能正常完成初始化,再逐步扩展到双端呼叫测试。
内容的提问来源于stack exchange,提问作者pbhuter
相关产品推荐
相关产品推荐

