Android 튜토리얼 – 초간단 영상회의 서비스 만들어보기

영상/음성 통화 안드로이드 앱 만들기

SDK 2.2.0 버전 기준

SDK 사용을 위한 Application Manifest 작업

Application Manifest에 아래와 같은 Permissions 항목 추가합니다.

<!-- PlayRTC SDK permission START -->
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<user-feature android:name="android.hardware.camera.flash" />
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<!-- PlayRTC SDK 2.2.0 이상 AudioManager 설정 시-->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<!-- PlayRTC SDK permission END -->

PlayRTC 클래스

이번 튜토리얼에서 사용하게 되는 PlayRTC의 클래스로 각각 다음과 같은 기능을 합니다.

  1. PlayRTC
    • PlayRTC의 주요 기능과 P2P를 다루는 클래스
  2. PlayRTCFactory
    • PlayRTC 인스턴스를 생성하고 관리하기 위한 클래스
  3. PlayRTCSettings
    • PlayRTC의 각종 설정을 관리하는 클래스
  4. PlayRTCObserver
    • 채널에 접속할때, 연결이 끊어졌을때 등 각종 콜백 이벤트들이 지정된 인터페이스 클래스
  5. PlayRTCMedia
    • 비디오, 오디오 미디어 스트림을 다루는 클래스. 비디오를 표출하기 위해서는 PlayRTCVideoView가 지정되어야 함
  6. PlayRTCVideoView
    • 비디오를 표출하기위한 PlayRTC의 커스텀 뷰

PlayRTC Application 흐름

com.sktelecom.playrtc.PlayRTC는 PlayRTC SDK에서 가장 중요한 Class입니다. PlayRTC 클래스를 이용하여 P2P 연결에 필요한 각종 작업을 수행하고 명령을 내립니다. 또한 PlayRTCObserver 인터페이스를 구현한 클래스를 생성하여 이벤트에 따라 콜백 함수를 처리할 수 있습니다. 아래는 PlayRTC 클래스를 이용하여 작업하게 될 대부분의 일을 안드로이드 Activity 라이프사이클에 맞추어 간단하게 정리하였습니다.

  1. PlayRTC 객체 생성 – onCreate Activity Life Cycle
    • 각종 콜백 이벤트 인터페이스인 PlayRTCObserver, 인스턴스 생성의 PlayRTCFactory, 각종 설정의 PlayRTCConfig 객체를 다루게 됩니다.
    • PlayRTCObserver 인터페이스 구현
      • 이 인터페이스는 아래의 PlayRTC 인스턴스에 등록되어 “onConnectChannel”, “onDisconnectChannel”등의 이벤트에 콜백형태로 기능을 삽입할때 사용됩니다.
    • PlayRTCFactory를 통해 PlayRTC 인스턴스 생성
      • 이때 이전에 구현해 두었던 PlayRTCObserver 구현인스턴스를 인자로 넘겨주어 실질적으로 콜백 함수를 등록하게 됩니다.
    • PlayRTCSetting 객체를 통해 각종 설정
      • 기본적으로 T Developers의 Project Key를 설정합니다. 아래의 링크를 참고하여 내 앱을 위한 Project Key를 준비해 둡니다.
      • 그 외에 비디오, 오디오, 데이터 채널의 설정을 합니다.
  2. PlayRTCVideoView 생성 – onWindowFocusChanged View Event
    • 비디오 표출을 위한 PlayRTC의 커스텀 뷰인 PlayRTCVideoView 객체를 다루게 됩니다.
    • 튜토리얼에서는 모든 화면이 그려진 이후인 onWindowFocusChanged 시점에 뷰를 생성하는데 이는 부모뷰의 실제 크기를 얻기 위해서 입니다. 만약 이런 값이 필요없다면 Activity의 onCreate 시점에 뷰를 생성하도록 합니다.
    • PlayRTCVideoView로 로컬 비디오 뷰(내 얼굴이 표출)를 생성 합니다.
    • PlayRTCVideoView로 리모트 비디오 뷰(상대방의 얼굴이 표출)를 생성 합니다.
  3. PlayRTC 플랫폼 채널 입장 – Activity Running Life Cycle
    • PlayRTC의 connectChannel, createChannel 메소드를 다루게 됩니다.
    • PlayRTC 플랫폼 채널 서비스에 새로운 채널을 생성하고 입장을 하거나, 기존의 만들어진 채널에 입장하여 P2P연결 수립을 수행합니다. 한 사용자는 채널을 생성하여야 하고, 다음 사용자는 만들어진 채널의 아이디로 채널에 입장을 합니다.  PlayRTCObserver의 onConnectChannel 콜백 이벤트에 필요한 코드를 작성하게 됩니다.
  4. 채널 연결 수립 후 로컬미디어스트림 출력 – Activity Running Life Cycle
    • 미디어 스트림을 위한 PlayRTCMedia 객체를 다루게 됩니다.
    • 채널 연결 수립 후 PlayRTCObserver의 onAddLocalStream 콜백을 통해 PlayRTCMedia 인스턴스를 전달받게 됩니다. 전달받은 PlayRTCMedia를 이전에 만들어둔 PlayRTCVideoView의 로컬 비디오 뷰에 지정하면 화면이 표출 됩니다.
  5. P2P 연결수립 후 원격미디어스트림 출력 – Activity Running Life Cycle
    • 미디어 스트림을 위한 PlayRTCMedia 객체를 다루게 됩니다.
    • P2P 연결 수립 후 PlayRTCObserver의 onAddRemoteStream 콜백을 통해 PlayRTCMedia 인스턴스를 전달받게 됩니다. 전달 받은 PlayRTCMedia를 이전에 만들어둔 PlayRTCVideoView의 리모트 비디오 뷰에 지정하면 화면이 표출 됩니다.
  6. 상대방과의연결종료처리 – Activity Running Life Cycle
    • PlayRTC의 disconnectChannel, deleteChannel 메소드와 PlayRTCObserver의 onDisconnectChannel, onDeleteChannel 콜백 이벤트를 다루게 됩니다.
    • PlayRTC의 disconnectChannel을 호출하여 채널에서 퇴장하거나 deleteChannel을 호출하여 채널을 종료하여 상대방과의 연결을 종료하고 필요에 따라 PlayRTCObserver의 적절한 콜백 이벤트에 필요한 사항을 처리합니다.

이제 이 흐름에 맞추어 구체적인 코드가 어떻게 구성되는지 알아보겠습니다.

PlayRTC 객체 생성

PlayRTCFactory 클래스의createPlayRTC 메소드를 이용하여 PlayRTC 객체를 생성할 수 있습니다.

이때설정 객체 PlayRTCConfig과 콜백 이벤트 처리를 위한 PlayRTCObserver 인터페이스를 구현한 observer 인스턴스를 인수로 등록합니다.

PlayRTCConfig 객체를 통해 각종 설정

PlayRTCConfig 객체는 PlayRTCFactory의 createConfig메소드를 이용하여 생성합니다.

다음과 같은 값을 설정하여 PlayRTC 에 전달해야 합니다.

  • Android Application Context
  • PlayRTC T-DEV 프로젝트 키
  • PlayRTC 미디어 관련 설정
  • PlayRTC 로깅 설정 – 사용자 지정

다음과 같은 형태로 구현할 수 있습니다.

 private PlayRTCConfig setPlayRTCConfiguration() {
     PlayRTCConfig settings = PlayRTCFactory.createConfig();

     // PlayRTC instance have to get the application context.
     settings.setAndroidContext(getApplicationContext());

     // T Developers Project Key.
     settings.setProjectId(MY_PROJECT_ID);

     // video는 기본 640x480 30 frame
     settings.video.setEnable(true);
     setting.video.cetCameraType(CameraType.Front);

     settings.audio.setEnable(true);
     settings.audio.setAudioManagerEnable(true); //음성 출력 장치 자동 선택 기눙 활성화 

     settings.data.setEnable(false);

     return settings;

PlayRTCObserver 인터페이스 구현

PlayRTCObserver에는 채널 접속, 끊김, 리모트 이벤트의 추가에 대한 다양한 이벤트 콜백이 담겨 있습니다. 이를 아래와 같이 구현하여 각 이벤트가 발생시에 필요한 코드를 작성할 수 있습니다.

private PlayRTCObserver playrtcObserver;

private void createPlayRTCObserverInstance() {
    playrtcObserver = new PlayRTCObserver() {
        @Override
        public void onConnectChannel(final PlayRTC obj, final String channelId, final String channelCreateReason) {
            ....Something....
        }

        @Override
        public void onAddLocalStream(final PlayRTC obj, final PlayRTCMedia playRTCMedia) {
            ....Something....
        }

        @Override
        public void onAddRemoteStream(final PlayRTC obj, final String peerId, final String peerUserId, final PlayRTCMedia playRTCMedia) {
            ....Something....
        }

        @Override
        public void onDisconnectChannel(final PlayRTC obj, final String disconnectReason) {
            ....Something....
        }

        @Override
        public void onOtherDisconnectChannel(final PlayRTC obj, final String peerId, final String peerUserId) {
            ....Something....
        }
};

PlayRTCFactory로 PlayRTC 인스턴스 생성

구성해 두었던 PlayRTCConfig 객체와 PlayRTCObserver 인터페이스를 구현한 observer 인스턴스를 인수로 등록하여 새로운 인스턴스를 생성합니다.

private PlayRTC playrtc = null;
private PlayRTCObserverImple playrtcObserver = null;
private void createPlayRTCInstance() {
    try {
        PlayRTCconfig setting = setPlayRTCConfiguration();
        playrtc = PlayRTCFactory.createPlayRTC(setting, playrtcObserver);
    } catch (UnsupportedPlatformVersionException e) {
        e.printStackTrace();
    } catch (RequiredParameterMissingException e) {
        e.printStackTrace();
    }
}

PlayRTCVideoView 생성

비디오를 담아둘 뷰 그룹를 준비

보통 화상통화 앱은 배경의 큰 화면에는 상대방의 화면이, 작은 화면에는 나의 모습이 보여지게 됩니다. 이 튜토리얼에서도 이런 형태로 구현 하도록 하겠습니다.

이를 위해서는 레이아웃에서 적절히 이 둘을 표출할 뷰를 지정해 두도록 합니다.

 <RelativeLayout
     android:id="@+id/video_view_group"
     android:layout_width="match_parent"
     android:layout_height="match_parent"/>

그리고 아래와 같이 비어있는 뷰를 만들고 로컬 뷰와 리모트 뷰를 생성하도록 하겠습니다.

 private void createVideoView() {
     // Set the videoViewGroup which is contained local and remote video views.
     RelativeLayout myVideoViewGroup = (RelativeLayout) findViewById(R.id.video_view_group);

     if (localView != null) {
         return;
     }

     // Give my screen size to child view.
     Point myViewDimensions = new Point();
     myViewDimensions.x = myVideoViewGroup.getWidth();
     myViewDimensions.y = myVideoViewGroup.getHeight();

     if (remoteView == null) {
         createRemoteVideoView(myViewDimensions, myVideoViewGroup);
     }

     if (localView == null) {
         createLocalVideoView(myViewDimensions, myVideoViewGroup);
     }
 }

로컬 뷰 생성

나의 모습이 표출되는 로컬뷰를 생성합니다. 이때 다음과 같은 단계를 수행합니다.

  1. 비디오 스트림의 크기를 정하는 Point 인스턴스를 만들어 크기값을 정합니다.
  2. 비디오 스트림이 표출되는 뷰의 각정 설정을 정합니다.
  3. 비디오 스트림크기를 인수로 하여 뷰를 만듭니다.
  4. 뷰의 설정값을 적용합니다.
private PlayRTCVideoView localView; 

private void createLocalVideoView(final Point parentViewDimensions, RelativeLayout parentVideoViewGroup) {
     if (localView == null) {
         // Create the video size variable.
         Point myVideoSize = new Point();
         myVideoSize.x = (int) (parentViewDimensions.x * 0.3);
         myVideoSize.y = (int) (parentViewDimensions.y * 0.3);

         // Create the view parameter.
         RelativeLayout.LayoutParams param = new RelativeLayout.LayoutParams(myVideoSize.x, myVideoSize.y);
         param.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
         param.addRule(RelativeLayout.ALIGN_PARENT_TOP);
         param.setMargins(30, 30, 30, 30);

         // Create the localViews.
         localView = new PlayRTCVideoView(parentVideoViewGroup.getContext(), myVideoSize);

         // Set the layout parameters.
         localView.setLayoutParams(param);

         // Add the view to the parentVideoViewGrop.
         parentVideoViewGroup.addView(localView);

         // Set the z-order.
         localView.setZOrderMediaOverlay(true);
     }
 }

리모트 뷰 생성

상대방의 모습이 표출되는 리모트 뷰를 생성합니다.  이때 다음과 같은 단계를 수행합니다.

  1. 비디오 스트림의 크기를 정하는 Point 인스턴스를 만들어 크기값을 정합니다.
  2. 비디오 스트림이 표출되는 뷰의 각정 설정을 정합니다.
  3. 비디오 스트림크기를 인수로 하여 뷰를 만듭니다.
  4. 뷰의 설정값을 적용합니다.
private PlayRTCVideoView remoteView;  

private void createRemoteVideoView(final Point parentViewDimensions, RelativeLayout parentVideoViewGroup) {
     if (remoteView == null) {
         // Create the video size variable.
         Point myVideoSize = new Point();
         myVideoSize.x = parentViewDimensions.x;
         myVideoSize.y = parentViewDimensions.y;

         // Create the view parameters.
         RelativeLayout.LayoutParams param = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);

         // Create the remoteView.
         remoteView = new PlayRTCVideoView(parentVideoViewGroup.getContext(), myVideoSize);

         // Set the layout parameters.
         remoteView.setLayoutParams(param);

         // Add the view to the videoViewGroup.
         parentVideoViewGroup.addView(remoteView);
     }
 }

PlayRTC 플랫폼 채널 입장

처음 채널에 입장히는 사용자가 채널을 생성하며 다른 사용자는 생성된 채널의 아이디로 채널에 입장을 하여 P2P연결을 합니다.

신규 채널을 생성하고 입장하기 – Peer A

PlayRTC 플랫폼 채널 서비스에 채널을 새로 생성하고 입장하는 메소드는 PlayRTC.createChannel 입니다. 이 메소드를 호출하면 Peer A를 위한 채팅방이 PlayRTC 플렛폼 서버에 만들어지게 되며 채널 Id와 Peer A에게 할당된 토큰값등을 반환해줄 것입니다. 가장 기본적인 사용법은 아무런 입력값 없이 null을 입력하여 createChannel(null) 메소드 호출하여 채널을 생성합니다.

private void createChannel() {
    try {
        // createChannel must have a JSON Object
        playrtc.createChannel(new JSONObject());
    } catch (RequiredConfigMissingException e) {
        e.printStackTrace();
    }
}

만들어진 채널에 입장하기 – Peer B

이미 생성된 채널에 입장히는 메소드는 connectChannel 입니다.

connectChannel 호출 시 해당 채널 아이디가 필요합니다. 채널 사용자의 부가 정보를 같이 전달하여 채널/사용자 정보 조회 시 받아볼 수 있습니다. connectChannel가 잘 수행되면 onConnectChannel 메소드를 통해 보안등을 위한 채널 사용자 토큰정보등을 받을 수 있습니다.

다음과 같은 형태로 구현할 수 있습니다.

private void connectChannel() {
    try {
        channelId = "CHS1234567890";
        // connectChannel must have a JSON Object
        playrtc.connectChannel(channelId, new JSONObject());
    } catch (RequiredConfigMissingException e) {
        e.printStackTrace();
    }
}

PlayRTC 미디어 스트림 출력

PlayRTCMedia 객체는 미디어 스트림을 다루고 있으며, 이를 화면으로 표출하기 위해서 이전 단계에서 만들었던 뷰와 연결을 하여 실제 화면을 표출합니다.

로컬 미디어 스트림 출력

PlayRTCObserver 인터페이스의 콜백 이벤트 onAddLocalStream을 통해 미디어를 뷰로 표출토록 합니다. onAddLocalStream은 채널 연결이 성공적으로 수행된 이후 발생됩니다.

 @Override
 public void onAddLocalStream(final PlayRTC obj, final PlayRTCMedia playRTCMedia) {
     long delayTime = 0;

     localView.show(delayTime);

     // Link the media stream to the view.
     playRTCMedia.setVideoRenderer(localView.getVideoRenderer());
 }

리모트 미디어 스트림 출력

PlayRTCObserver 인터페이스의 콜백 이벤트 onAddRemoteStream을 통해 미디어를 뷰로 표출토록 합니다. onAddRemoteStream은 P2P연결이 성공적으로 수행된 이후 발생됩니다.

 @Override
 public void onAddRemoteStream(final PlayRTC obj, final String peerId, final String peerUserId, final PlayRTCMedia playRTCMedia) {
     long delayTime = 0;

     remoteView.show(delayTime);

     // Link the media stream to the view.
     playRTCMedia.setVideoRenderer(remoteView.getVideoRenderer());

 }

PlayRTC 연결 종료

PlayRTC에서 상대방과 연결을 종료하는 경우는 다음의 경우가 있습니다.

  1. 상대방이 채널에서 퇴장 하는 경우 – 채널이 유효한 상태
    • 상대방이 disconnectChannel를 호출하면 SDK는 채널 서비스로부터 채널 퇴장 이벤트를 받아 채널에서 퇴장하며, 채널 서비스는 나에게 상대방의 채널 퇴장을 알리는 이벤트(onOtherDisconnectChannel)를 보내 줍니다.
  2. 자신이 채널에서 퇴장하는 경우 – 채널이 유효한 상태
    • disconnectChannel을 호출하면 SDK는 채널 서비스로부터 채널 퇴장 이벤트(onDisconnectChannel)를 받아 채널에서 퇴장하고, 채널 서비스는 상대방에게도 나의 채널 퇴장 이벤트(onOtherDisconnectChannel)를 전달하게 됩니다. 상대방은 이 이벤트를 받아 나의 채널 퇴장을 알게 됩니다.
  3. 상대방 또는 자신이 채널을 종료 하는 경우 – 예제에서의 채널 종료 방법
    • deleteChannel을 호출하면 채널 서비스는 채널에 입장한 모든 사용자에게 채널 종료를 통보(onDisconnectChannel)하고 채널에 있는 모든 사용자의 연결을 종료합니다. 이때 각각의 사용자는 종료하는 과정을 진행합니다.
  4. PlayRTC 인스턴스 해제
    • close를 호출하여 내부 인스턴스를 해제합니다. 새로운 PlayRTC 인스턴스를 만들거나 PlayRTC를 구현한 Activity 종료 시 호출합니다.

채널 종료를 이용한 PlayRTC 연결 종료

Android 단말기의 Back-Key를 이용하여 종료과정을 구현합니다. boolean isCloseAction이라는 멤버 변수를 선언한 후 onBackPressed에서 isCloseActivity 값을 확인하여 false이면 사용자에게 종료 의사를 물어보는 다이얼로그를 화면에 출력하고, 사용자가 확인을 선택하면 deleteChannel을 호출하여 채널 종료를요청합니다.

채널 서비스에서 채널 종료 이벤트(onDeleteChannel)를 받으면 isCloseActivity을 true로 설정하여 onBackPressed를 호출합니다.

다음과 같은 형태로 구현할 수 있습니다.

@Override
protected void onDestroy() {
   if(playrtc != null) {
        playrtc.close();
   }
   ,,,,,
   super.onDestroy();
}

@Override
public void onBackPressed() {
    if (isCloseActivity) {
        super.onBackPressed();
    } else {
        this.createCloseAlertDialog();
        closeAlertDialog.show();
    }
}

private void createCloseAlertDialog() {
    // Create the Alert Builder.
    AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);

    // Set a Alert.
    alertDialogBuilder.setTitle(R.string.alert_title);
    alertDialogBuilder.setMessage(R.string.alert_message);
    alertDialogBuilder.setPositiveButton(R.string.alert_positive, new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialogInterface, int id) {
            dialogInterface.dismiss();
            if (isChannelConnected == true) {
                isCloseActivity = false;

                // null means my user id.
                playrtc.disconnectChannel(null);
            } else {
                isCloseActivity = true;
                onBackPressed();
            }
        }
    });
    alertDialogBuilder.setNegativeButton(R.string.alert_negative, new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialogInterface, int id) {
            dialogInterface.dismiss();
            isCloseActivity = false;
        }
    });

    // Create the Alert.
    closeAlertDialog = alertDialogBuilder.create();
}
 

Play RTC

서비스 체험

Play RTC build PlaygrOund

나만의 플레이그라운드를 만들어 친구를 초대해보세요 !

www.playrtc.com/

번거로운 가입이나 설치 없이ID만 만들어서 영상통화나 파일 공유, 채팅 서비스를 무료로 즐겨보세요.

 

Play RTC

서비스 체험

개설한 Playground 주소를 복하해서 친구에게 보내조세요. 친구가 Playground에 접속하면 이곳에 친구의 영상과 음성이 나타납니다. Waiting..

Photo

X
이미지 미리보기
이미지
 

서비스 체험

 

서비스 체험

서비스 체험은 크롬과 파이어폭스 브라우저에 최적화되어 있습니다.
크롬 또는 파이어폭스 브라우저를 설치 후 다시 이용해주세요.