Skip to end of metadata
Go to start of metadata

Пример Android приложения с двумя Websocket сессиями

Данное приложение демонстрирует использование одновременно двух Websocket сессий для подключения к одному или двум разным WCS серверам. Публиковать при этом можно только один поток, т.к. Android не позволяет захватить одновременно две камеры, либо дважды одну и ту же камеру. Воспроизводить можно одновременно два потока.

На скриншоте представлен пример публикации на один сервер и проигрывания этого потока в двух сессиях

Работа с кодом примера

Для разбора кода возьмем класс TwoSessionsActivity.java примера 2sessions, который доступен для скачивания в соответствующей сборке 1.1.0.57

Реализация представляет собой два примера Two Way Streaming  в одном приложении, поэтому далее рассмотрим подробно код одной из двух сессий

 1. Инициализация API.

Flashphoner.init() code

Независимо от количества сессий, API инициализируется один раз на приложение

        Flashphoner.init(this);

2. Создание сессии

Flashphoner.createSession() code

Методу передается объект SessionOptions со следующими параметрами

  • URL WCS-сервера
  • SurfaceViewRenderer localRenderer, который будет использоваться для отображения видео с камеры
  • SurfaceViewRenderer remoteRenderer, который будет использоваться для отображения воспроизводимого потока
                    SessionOptions sessionOptions = new SessionOptions(mWcsUrl1View.getText().toString());
                    sessionOptions.setRemoteRenderer(remote1Render);
                    sessionOptions.setLocalRenderer(local1Render);

                    /**
                     * Session for connection to WCS server is created with method createSession().
                     */
                    session1 = Flashphoner.createSession(sessionOptions);

3. Подключение к серверу.

Session.connect() code

                    session1.connect(new Connection());

4. Получение от сервера события, подтверждающего успешное соединение.

session.onConnected() code

По данному событию запрашиваются права на доступ к камере и микрофону

                        @Override
                        public void onConnected(final Connection connection) {
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    mConnect1Button.setText(R.string.action_disconnect);
                                    mConnect1Button.setTag(R.string.action_disconnect);
                                    mConnect1Button.setEnabled(true);
                                    mConnect1Status.setText(connection.getStatus());
                                    mPlay1Button.setEnabled(true);
                                    if (mPublish2Button.getTag() == null || Integer.valueOf(R.string.action_publish).equals(mPublish2Button.getTag())) {
                                        mPublish1Button.setEnabled(true);
                                    }

                                    ActivityCompat.requestPermissions(TwoSessionsActivity.this,
                                            new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA},
                                            PUBLISH_REQUEST_CODE);
                                }
                            });
                        }

5. Публикация потока по нажатию кнопки Publish1Button

Session.createStream(), Stream.publish() code

        mPublish1Button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                mPublish1Button.setEnabled(false);
                mPublish2Button.setEnabled(false);
                mConnect1Button.setEnabled(false);
                mConnect2Button.setEnabled(false);
                if (mPublish1Button.getTag() == null || Integer.valueOf(R.string.action_publish).equals(mPublish1Button.getTag())) {
                    /**
                     * The options for the stream to play are set.
                     * The stream name is passed when StreamOptions object is created.
                     * SurfaceViewRenderer to be used to display the video stream is set using method StreamOptions.setRenderer().
                     */
                    StreamOptions streamOptions = new StreamOptions(mPublish1StreamView.getText().toString());
                    streamOptions.setRenderer(local1Render);

                    /**
                     * Stream is created with method Session.createStream().
                     */
                    publish1Stream = session1.createStream(streamOptions);
                    ...
                    publish1Stream.publish();
                } else {
                    ...
                }
            }
        });

6. Воспроизведение потока при нажатии Play1Button

Session.createStream(), Stream.play() code

        mPlay1Button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                mPlay1Button.setEnabled(false);
                if (mPlay1Button.getTag() == null || Integer.valueOf(R.string.action_play).equals(mPlay1Button.getTag())) {
                    /**
                     * The options for the stream to play are set.
                     * The stream name is passed when StreamOptions object is created.
                     * SurfaceViewRenderer to be used to display the video stream is set using method StreamOptions.setRenderer().
                     */
                    StreamOptions streamOptions = new StreamOptions(mPlay1StreamView.getText().toString());
                    streamOptions.setRenderer(remote1Render);

                    /**
                     * Stream is created with method Session.createStream().
                     */
                    play1Stream = session1.createStream(streamOptions);
                    ...
                    play1Stream.play();
                    ...
                } else {
                    ...
                }
            }
        });

7. Остановка воспроизведение потока

Stream.stop() code

        mPlay1Button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                mPlay1Button.setEnabled(false);
                if (mPlay1Button.getTag() == null || Integer.valueOf(R.string.action_play).equals(mPlay1Button.getTag())) {
                    ...
                } else {
                    /**
                     * Method Stream.stop() is called to stop playback of the stream.
                     */
                    play1Stream.stop();
                    play1Stream = null;
                }
                ...
            }
        });

8. Остановка публикации потока

Stream.stop() code

        mPublish1Button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                mPublish1Button.setEnabled(false);
                mPublish2Button.setEnabled(false);
                mConnect1Button.setEnabled(false);
                mConnect2Button.setEnabled(false);
                if (mPublish1Button.getTag() == null || Integer.valueOf(R.string.action_publish).equals(mPublish1Button.getTag())) {
                    ...
                } else {
                    /**
                     * Method Stream.stop() is called to stop playback of the stream.
                     */
                    publish1Stream.stop();
                    publish1Stream = null;
                }
                ...
            }
        });

9. Закрытие соединения

Session.disconnect() code

        mConnect1Button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mConnect1Button.getTag() == null || Integer.valueOf(R.string.action_connect).equals(mConnect1Button.getTag())) {
                    ...
                } else {
                    mConnect1Button.setEnabled(false);

                    /**
                     * Connection to WCS server is closed with method Session.disconnect().
                     */
                    session1.disconnect();
                }
                ...
            }
        });

10. Получение события, подтверждающего разъединение.

session.onDisconnection() code

                        public void onDisconnection(final Connection connection) {
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    mConnect1Button.setText(R.string.action_connect);
                                    mConnect1Button.setTag(R.string.action_connect);
                                    mConnect1Button.setEnabled(true);
                                    mPlay1Button.setText(R.string.action_play);
                                    mPlay1Button.setTag(R.string.action_play);
                                    mPlay1Button.setEnabled(false);
                                    mPublish1Button.setEnabled(false);
                                    mPublish1Button.setText(R.string.action_publish);
                                    mPublish1Button.setTag(R.string.action_publish);
                                    mConnect1Status.setText(connection.getStatus());
                                    mPlay1Status.setText("");
                                    if (mConnect2Button.getTag() == null || Integer.valueOf(R.string.action_disconnect).equals(mConnect2Button.getTag())) {
                                        mPublish2Button.setEnabled(true);
                                    }
                                }
                            });
                        }
  • No labels