Описание
Данный пример может использоваться для аудиочата между двумя участниками на Web Call Server и позволяет публиковать и проигрывать аудио WebRTC-поток.
Ниже представлен пример аудиочата в приложении
Поля ввода
- 'WCS URL', где
wss://demo.flashphoner.com:8443/
- адрес WCS-сервера - 'Login', где
bob
- имя пользователя - 'Room', где
room1
- имя "комнаты" чата
Работа с кодом примера
Для разбора кода возьмем класс AudioChatActivity.java примера audio chat, который доступен для скачивания в соответствующей сборке 1.1.0.61.
В отличии от прямого подключения к серверу методом createSession()
, для управления подключением к серверу и конференции используется объект RoomManager
. Соединение с сервером устанавливается при создании объекта RoomManager
, а для присоединения к конфренции вызывается метод RoomManager.join(),
При присоединении к новой "комнате" методом RoomManager.join()
, создается объект Room для работы с этой "комнатой". Для работы с участниками конференции используются объекты Participant.
Все события, происходящие в "комнате" (присоединение/выход пользователя, отправленные сообщения), транслируются другим участникам, подключенным к этой "комнате".
Например, в следующем коде подключаемся к "комнате" и запрашиваем список других участников:
room = roomManager.join(roomOptions); room.on(new RoomEvent() { public void onState(final Room room) { for (final Participant participant : room.getParticipants()) { ... } ... } ... });
1. Инициализация API
Flashphoner.init()
code
Flashphoner.init(this);
2. Создание объекта для рендера полученного аудио потока
SurfaceViewRenderer
code
renderer = new SurfaceViewRenderer(this);
3. Подключение к серверу
Flashphoner.createRoomManager()
code
Методу передается объект RoomManagerOptions со следующими параметрами
- URL WCS-сервера
- имя пользователя для присоединения к чат-комнате
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. Получение от сервера события, подтверждающего успешное соединение
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. Присоединение к конференции
RoomManager.join()
code
Методу RoomManager.join()
передается объект RoomOptions
с именем комнаты конференции
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. Получение от сервера события, подтверждающего успешное присоединение к конференции
Room.onState()
code
При получении данного события количество и состав других участников определяется с помощью метода Room.getParticipants()
. Если количество участников более 2, текущий участник выходит из комнаты.
Если текущий участник остается в комнате, запускается проигрывание потока от другого участника при помощи Participant.play()
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. Публикация аудиопотока
Room.publish()
code
Методу передаются ограничения, указывающие, что публиковаться должно только аудио
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. Получение от сервера события, сигнализирующего о присоединении к конференции другого участника
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. Получение от сервера события, сигнализирующего о публикации видеопотока другим участником
Room.onPublished()
code
При получении данного события поток, опубликованный участником, воспроизводится с помощью метода Participant.play()
. Этому методу передается SurfaceViewRenderer
, в котором будет проигрываться аудио
@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. Получение от сервера события, сигнализирующего об отправке сообщения другим участником
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. Отправка сообщения другому участнику
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. Остановка публикации аудиопотока при нажатии Unpublish
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
Room.leave()
code
Методу передается обработчик ответа REST хука, используемого при выходе из комнаты
room.leave(new RestAppCommunicator.Handler() { @Override public void onAccepted(Data data) { runOnUiThread(action); } @Override public void onRejected(Data data) { runOnUiThread(action); } });
14. Закрытие соединения
RoomManager.disconnect()
code
mConnectButton.setEnabled(false); /** * Connection to WCS server is closed with method RoomManager.disconnect(). */ roomManager.disconnect();
15. Включение/выключение аудио для публикуемого потока
Stream.unmuteAudio()
, Stream.muteAudio()
code
mMuteAudio = (Switch) findViewById(R.id.mute_audio); mMuteAudio.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { stream.muteAudio(); } else { stream.unmuteAudio(); } } });