Android Audio Chat¶
Overview¶
The application is used to test two participants audio chat and allows to publish and play audio only WebRTC stream from Web Call Server.
The example of audio chat in application is shown on the screenshot below.
The application uses the following input fields:
WCS URL
, wherewss://demo.flashphoner.com:8443/
is the WCS server addressLogin
, wherebob
is the participant nameRoom
, whereroom1
is the chat room name
Analyzing the code¶
To explore the code, use the class AudioChatActivity.java of the audio chat example which is available to download in the Android SDK build 1.1.0.61.
Unlike a direct connection to server with method createSession()
, the RoomManager
object is used for managing connection to the server room. Connection to the server is established when RoomManager
object is created, and method RoomManager.join()
is called to join a room.
The Room
object is created to work with the room locally when joined. A Participant
objects are used to work with room participants locally.
All events occurring in the room (a user joined/left, or sent a message), are sent to all users connected to the room.
For example, in the following code, a user joins a room and gets the list of already connected users:
room = roomManager.join(roomOptions);
room.on(new RoomEvent() {
public void onState(final Room room) {
for (final Participant participant : room.getParticipants()) {
...
}
...
}
...
});
1. API initialization¶
Flashphoner.init()
code
2. Create an object to render a received audio stream¶
SurfaceViewRenderer
code
3. Connection to the server¶
Flashphoner.createRoomManager()
code
The RoomManagerOptions
object is passed to the method with the following parameters:
- URL of WCS server
- participant name to join a room
RoomManagerOptions roomManagerOptions = new RoomManagerOptions(mWcsUrlView.getText().toString(), mLoginView.getText().toString());
/**
* RoomManager object is created with method createRoomManager().
* Connection session is created when RoomManager object is created.
*/
roomManager = Flashphoner.createRoomManager(roomManagerOptions);
4. Receiving the event confirming successful connection¶
RoomManager.onConnected()
code
@Override
public void onConnected(final Connection connection) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mConnectButton.setText(R.string.action_disconnect);
mConnectButton.setTag(R.string.action_disconnect);
mConnectButton.setEnabled(true);
mConnectStatus.setText(connection.getStatus());
mJoinButton.setEnabled(true);
}
});
}
5. Joining a room¶
RoomManager.join()
code
The RoomOptions
object with the room name is passed to the method
RoomOptions roomOptions = new RoomOptions();
roomOptions.setName(mJoinRoomView.getText().toString());
/**
* The participant joins a audio chat room with method RoomManager.join().
* RoomOptions object is passed to the method.
* Room object is created and returned by the method.
*/
room = roomManager.join(roomOptions);
6. Receiving the event describing chat room state¶
Room.onState()
code
The current participants array is received by Room.getParticipants()
method. If there are more than 2 participants in the room, the current participant leaves it.
If the current participant stays in the room, the stream playback from other participant starts with Participant.play()
method
if (room.getParticipants().size() >= 2) {
room.leave(null);
runOnUiThread(
new Runnable() {
@Override
public void run() {
mJoinStatus.setText("Room is full");
mJoinButton.setEnabled(true);
}
}
);
return;
}
final StringBuffer chatState = new StringBuffer("participants: ");
/**
* Iterating through the collection of the other participants returned by method Room.getParticipants().
* There is corresponding Participant object for each participant.
*/
for (final Participant participant : room.getParticipants()) {
/**
* A player view is assigned to each of the other participants in the room.
*/
chatState.append(participant.getName()).append(",");
runOnUiThread(
new Runnable() {
@Override
public void run() {
participant.play(renderer);
mParticipantName.setText(participant.getName());
}
}
);
}
7. Audio stream publishing¶
Room.publish()
code
The audio only constraints object is passed to the method
case PUBLISH_REQUEST_CODE: {
if (grantResults.length == 0 ||
grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Log.i(TAG, "Permission has been denied by user");
} else {
/**
* Stream is created and published with method Room.publish().
*/
StreamOptions streamOptions = new StreamOptions();
streamOptions.setConstraints(new Constraints(true, false));
stream = room.publish(null, streamOptions);
...
Log.i(TAG, "Permission has been granted by user");
}
}
8. Receiving the other participant joined notification event¶
Room.onJoined()
code
@Override
public void onJoined(final Participant participant) {
/**
* When a new participant joins the room, a player view is assigned to that participant.
*/
runOnUiThread(
new Runnable() {
@Override
public void run() {
mParticipantName.setText(participant.getName());
addMessageHistory(participant.getName(), "joined");
}
}
);
}
9. Receiving the other participant publishing notification event¶
Room.onPublished()
code
When the notification event is received the stream publishing by other participants is starting to play by Participant.play()
method. The SurfaceViewRenderer
object to render the audio stream is passed to this method
@Override
public void onPublished(final Participant participant) {
/**
* When one of the other participants starts publishing, playback of the stream published by that participant is started.
*/
runOnUiThread(
new Runnable() {
@Override
public void run() {
participant.play(renderer);
}
}
);
}
10. Receiving the other participant messaging notification event¶
Room.onMessage()
code
@Override
public void onMessage(final Message message) {
/**
* When one of the participants sends a text message, the received message is added to the messages log.
*/
runOnUiThread(
new Runnable() {
@Override
public void run() {
addMessageHistory(message.getFrom(), message.getText());
}
}
);
}
11. Sending a message to other participant¶
Participant.sendMessage()
code
mSendButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
String text = mMessage.getText().toString();
if (!"".equals(text)) {
for (Participant participant : room.getParticipants()) {
participant.sendMessage(text);
}
addMessageHistory(mLoginView.getText().toString(), text);
mMessage.setText("");
}
}
});
12. Stop audio stream publishing by Unpublish button click¶
Room.unpublish()
code
@Override
public void onClick(View view) {
if (mPublishButton.getTag() == null || Integer.valueOf(R.string.action_publish).equals(mPublishButton.getTag())) {
ActivityCompat.requestPermissions(AudioChatActivity.this,
new String[]{Manifest.permission.RECORD_AUDIO},
PUBLISH_REQUEST_CODE);
} else {
mPublishButton.setEnabled(false);
/**
* Stream is unpublished with method Room.unpublish().
*/
room.unpublish();
}
...
}
13. Leave the room by Leave button click¶
Room.leave()
code
Server REST hook response handler is passed to the method
room.leave(new RestAppCommunicator.Handler() {
@Override
public void onAccepted(Data data) {
runOnUiThread(action);
}
@Override
public void onRejected(Data data) {
runOnUiThread(action);
}
});
14. Closing the server connection¶
RoomManager.disconnect()
code
mConnectButton.setEnabled(false);
/**
* Connection to WCS server is closed with method RoomManager.disconnect().
*/
roomManager.disconnect();
15. Mute/unmute audio stream published¶
Stream.unmuteAudio()
, Stream.muteAudio()
code