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

I'm working on building an Android app that uses an Azure Communication Service for video. I used

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

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742326088a4422781.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信