最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

android - How do I specify who to call using an Azure Communication Service? - Stack Overflow

programmeradmin2浏览0评论

I'm working on building an Android app that uses an Azure Communication Service for video. I used this tutorial as a starting point, and made a number of changes. But in the tutorial, it has the user copy a User Access Token generated from the CLI or Portal. This token is input into the "Call ID" to start things off. However, if I have two people, each of which has a token that was generated via the Portal, how do I use that token for calling each other?

The code in the tutorial for starting a call is:

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);
}

I have modified this code as follows:

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);
}

Where 'whoCall' and 'whoCalled' are strings that are the two tokens from the Portal, and are set using radio buttons for who to call, the idea of which is to select one of the two radio buttons for who you want to call, which will set 'whoCall' to one token and 'whoCalled' to the other.

When I try using things this way, though, via the emulator on my computer and the APK on my phone, nothing actually connects. I think my problem is not understanding how the token from the Portal is used in the Android app to connect one user to another user.

Some thoughts I have are:

  • Do I need to have both parties connect through the app to the same token? If that is the case, how do I have one person call the other person?
  • Do I need to change my code with regards to how I am using the token as part of the call initiation? I don't see how my code is so different from the tutorial in a way that breaks how the token is used.

Any other thoughts anyone has are appreciated.

I'm working on building an Android app that uses an Azure Communication Service for video. I used this tutorial as a starting point, and made a number of changes. But in the tutorial, it has the user copy a User Access Token generated from the CLI or Portal. This token is input into the "Call ID" to start things off. However, if I have two people, each of which has a token that was generated via the Portal, how do I use that token for calling each other?

The code in the tutorial for starting a call is:

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);
}

I have modified this code as follows:

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);
}

Where 'whoCall' and 'whoCalled' are strings that are the two tokens from the Portal, and are set using radio buttons for who to call, the idea of which is to select one of the two radio buttons for who you want to call, which will set 'whoCall' to one token and 'whoCalled' to the other.

When I try using things this way, though, via the emulator on my computer and the APK on my phone, nothing actually connects. I think my problem is not understanding how the token from the Portal is used in the Android app to connect one user to another user.

Some thoughts I have are:

  • Do I need to have both parties connect through the app to the same token? If that is the case, how do I have one person call the other person?
  • Do I need to change my code with regards to how I am using the token as part of the call initiation? I don't see how my code is so different from the tutorial in a way that breaks how the token is used.

Any other thoughts anyone has are appreciated.

Share Improve this question asked Nov 20, 2024 at 21:52 pbhuterpbhuter 4371 gold badge5 silver badges20 bronze badges 4
  • Tokens cannot be used as identifiers for calling. Instead, you must use the user ID (which is typically associated with the token) to set up the participants list. – Suresh Chikkam Commented Nov 21, 2024 at 3:36
  • 1 That makes sense, thank you. However, tokens expire. If I always have the same two participants (myself and one other party), is there a way to always use a 1:1 call between the two of us? – pbhuter Commented Nov 21, 2024 at 13:56
  • Yes, you can establish a persistent 1:1 call setup, The key is to focus on the user identifiers (e.g., 8:acs:<unique-user-id>) instead of the tokens. store these user identifiers securely in the app or a backend service. – Suresh Chikkam Commented Nov 22, 2024 at 14:02
  • you can issue long-lived tokens programmatically (valid for up to 24 hours) for please check my updated/modified answer. – Suresh Chikkam Commented Nov 22, 2024 at 14:04
Add a comment  | 

1 Answer 1

Reset to default 1

The issue is that you are directly passing the tokens (whoCall and whoCalled) as CommunicationUserIdentifier.

Tokens cannot be used as identifiers for calling. Instead, you must use the user ID (which is associated with token) to set up the participants list.

Firstly Tokens and User IDs Are Managed Correctly. Have a unique user identity It should be issued an access token associated with that identity.

Update the startCall method to use the user IDs (id in the above example) as CommunicationUserIdentifier, not the raw tokens.

private void startCall(String whoCallId, String whoCalledId) {
    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);
    }

    // Use user IDs as CommunicationUserIdentifiers
    participants.add(new CommunicationUserIdentifier(whoCallId));
    participants.add(new CommunicationUserIdentifier(whoCalledId));

    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);
}

Both users (caller and callee) need to authenticate with their access tokens to join the call.

  • When the app initializes the CallAgent for each user, check it uses the corresponding access token.
CommunicationTokenCredential credential = new CommunicationTokenCredential(accessToken);
callAgent = new CallClient().createCallAgent(context, credential).get();

Console output:

[INFO] Initializing CallAgent with token.
[DEBUG] CommunicationTokenCredential initialized successfully.
[INFO] CallAgent created successfully for user: 8:acs:12345678-90ab-cdef-ghij-klmnopqrstuv
[DEBUG] Device Manager initialized. Cameras detected: [Front Camera, Back Camera].
[INFO] Starting call to user: 8:acs:abcdefgh-ijkl-mnop-qrst-uvwxyzabcdef
[DEBUG] Adding participant: 8:acs:abcdefgh-ijkl-mnop-qrst-uvwxyzabcdef
[INFO] Call state changed: CONNECTING
[DEBUG] Local video stream enabled using Front Camera.
[INFO] Call is active. Total participants: 2
[DEBUG] Remote participant is speaking: true
[INFO] HangUp initiated by the local user.
[INFO] Call state changed: DISCONNECTED
[ERROR] Failed to initialize CallAgent: Invalid access token.
[ERROR] No internet connection detected. Cannot start call.
[ERROR] Call state changed: DISCONNECTED due to Network Error.

Update:

Create a backend service to issue tokens programmatically using the Azure Communication Services SDK or REST API.

// Create a Communication Identity Client
CommunicationIdentityClient client = new CommunicationIdentityClientBuilder()
    .connectionString("<YOUR_CONNECTION_STRING>")
    .buildClient();

// Generate a user and issue a token
CommunicationUserIdentifier user = client.createUser();
AccessToken token = client.getToken(user, Arrays.asList("voip"));

// Save `user.getId()` and `token.getToken()` for the app
发布评论

评论列表(0)

  1. 暂无评论