Android SDK 개발자 가이드
Android 버전의 카카오 i 커넥트 라이브 SDK 2.0은 안드로이드 앱에서 카카오 i 커넥트 라이브 서비스의 개발을 지원하는 Kotlin 라이브러리이며, Java 인터페이스도 제공합니다. SDK에서 제공하는 메서드와 이벤트를 활용하여 화상과 음성을 교환하는 실시간 스트리밍 서비스를 쉽게 만들 수 있습니다.
SDK 개발 순서는 크게 다음으로 구분할 수 있으며, 이 과정에서 사용되는 주요 메서드는 signIn(인증), createLocalMedia(로컬미디어생성), createRoom(Room 생성), connect(Room 접속), publish(로컬 미디어 공유), subscribe(리모트 미디어 구독)입니다. 이때 사용되는 이벤트는 connected, remoteVideoPublished입니다.
SDK에서 제공하는 메서드에 대한 자세한 설명은 API 레퍼런스 > Android 문서를 참고하시기 바랍니다.
그림Android SDK
주요 클래스 간 다이어그램
그림주요 클래스 간 다이어그램
클래스 | 설명 |
---|---|
ConnectLive | 카카오 i 커넥트 라이브 SDK 2.0의 최상위 클래스 - 인증, Room 생성, 미디어 생성을 담당 |
Room | 스트리밍 서비스의 연결 단위 그룹을 나누는 개념의 클래스이며, 스트리밍 연결 및 기타 정보를 관리 |
Participant | 라이브 스트리밍 서비스의 채팅방에 참여한 참여자 - LocalParticipant(로컬 참여자, 나 자신)와 RemoteParticipant(리모트 참여자, 리모트 참여자(Remote Participant))로 구분됨 |
Content | 미디어의 기본 인터페이스 |
EventsCallback | Room에서 발생하는 이벤트를 처리하기 위한 Callback |
AudioHelper | 오디오 포커스 및 장치 우선권을 제어하는 유틸리티 모듈 |
최소 개발 환경
Android SDK를 사용하기 위해서 아래의 환경을 요구합니다.
- Android OS: 7.0(API 24, Nougat) 또는 그 이상
- Kotlin: 1.6 이상 (또는 Java 1.8 이상)
사전 작업
카카오 i 커넥트 라이브 SDK 2.0을 사용하여 실시간 스트리밍 서비스를 개발하기 전, 다음의 사전 작업을 수행해야 합니다.
서비스 인증 정보 발급받기
카카오 i 커넥트 라이브 SDK 2.0을 사용하기 위해서는 고객사에서 선정한 인증 방식에 따라 카카오 i 커넥트 라이브 콘솔에서 서비스 인증 정보를 발급받아야 합니다.
SDK 기본 인증 방식인 커넥트 라이브 내부 인증 방식의 경우, 콘솔에서 서비스 ID(serviceId)와 서비스 시크릿(serviceSecret)을 발급받아야 합니다. 이 정보는 프로젝트 생성 시 자동 생성되며, 서비스 (앱)별로 구분되어 사용량 측정 및 과금의 기준이 됩니다. 따라서 하나 이상의 애플리케이션을 만들 경우에는 앱의 개수만큼 서비스 ID와 서비스 시크릿을 각각 발급받아야 합니다. 서비스 인증 정보를 발급받는 방법은 다음과 같습니다.
고급 인증 방식인 서비스 자체 인증 방식의 경우, 콘솔에서 서비스 ID(serviceId)를 발급받아야 합니다. 각 인증 방식 별 자세한 인증 프로세스는 인증 및 키 처리 문서를 참고하시기 바랍니다.
인증 방식 구분 | 설명 |
---|---|
기본 인증 방식: 커넥트 라이브 내부 인증 | 카카오 i 커넥트 라이브 SDK 2.0의 기본 인증 방식 - 콘솔에서 서비스 ID(serviceId)와 서비스 시크릿(serviceSecret) 발급 필요 - SDK 기본 인증 방식으로 별도의 서버 및 개발 작업이 필요 없음 - 자세한 설명은 서비스 인증 정보 발급하기 참고 |
고급 인증 방식: 서비스 자체 인증 | 최종 사용자에게 신원 확인용 토큰을 부여하고, 권한을 부여하는 서비스 자체 인증 방식 - 콘솔에서 서비스 ID(serviceId) 발급 필요 - 수준 높은 보안 레벨을 충족하며, 별도의 서버 및 개발 작업 필요 - 자세한 설명은서비스 인증 정보 발급하기 참고 |
주의
serviceId와 serviceSecret 정보가 외부로 유출될 경우에는 해킹 등 악용의 소지가 발생할 수 있으므로 코드 저장소 등에 노출되지 않도록 주의하시기 바랍니다.
안내
카카오 i 커넥트 라이브 콘솔에서는 사용자 인증 정보 관리, 워크스페이스 관리, 멤버 초대 등의 기능을 제공합니다. 콘솔 사용과 관련한 자세한 설명은 부록. 카카오 i 커넥트 라이브 콘솔 문서를 참고하시기 바랍니다.
Android Studio 설정하기
Android 버전의 카카오 i 커넥트 라이브 SDK 2.0을 설치하기 위해서는 Android Studio 프로젝트에서 Gradle 설정과 Manifest 설정을 완료해야 합니다
Gradle 설정하기
-
Android Studio를 최신 버전으로 업데이트합니다.
-
Android Studio > New Project 메뉴에서 신규 프로젝트를 생성합니다.
-
gradle
설정에 ‘카카오 i 커넥트 라이브 SDK 2.0’의 의존성을 추가합니다.- 의존성 추가
프로젝트에 종속 항목을 추가하려면
build.gradle
파일의dependencies
블록에implementation
과 같은 종속 항목 구성을 지정합니다.코드예제의존성 추가 Syntax
apply plugin: 'com.android.application' android { ... } dependencies { // Dependency on a remote binary implementation 'com.kakaoenterprise:icl2:2.+' }
- 원격 저장소 추가
종속 항목이 로컬 라이브러리나 파일 트리가 아닌 경우 Gradle은
build.gradle
파일의repositories
블록에서 지정된 온라인 저장소에서 파일을 찾습니다. 각 저장소를 나열하는 순서에 따라 Gradle이 각 프로젝트 종속 항목의 저장소를 검색하는 순서가 결정됩니다. 예를 들어 종속 항목을 저장소 A와 B에서 다운로드할 수 있고 A를 먼저 나열한 경우 Gradle은 저장소 A에서 종속 항목을 다운로드합니다.
기본적으로 새 Android 스튜디오 프로젝트에서는 아래와 같이 Google Maven 저장소와 JCenter를 프로젝트의 최상위 수준build.gradle
파일의 저장소 위치로 지정합니다.코드예제원격 저장소 추가 Syntax
repositories { google() jcenter() maven { url "https://icl.jfrog.io/artifactory/kakaoenterprise" } }
-
본 가이드의 예제는 View Binding을 사용하고 있으며,
build.gradle
설정은 다음과 같습니다.코드예제View Binding Syntax
android { defaultConfig{ ... } ... buildFeatures{ viewBinding true } }
Manifest 설정하기
사용자 권한을 획득하기 위해서 Android Manifest를 업데이트합니다.
-
Project/…/AndroidManifest.xml
파일을 엽니다. -
다음 표. Manifest 권한 획득을 참고하여, 필요한 퍼미션을 업데이트합니다.
- SDK는 기본적으로 런타임 권한 요청이 필요한 2가지(
RECORD_AUDIO
,CAMERA
)를 포함해서 몇 가지 권한이AndroidManifest.xml
에 등록되어 있습니다.
파라미터 타입 필수 여부 설명 INTERNET 필수
normal 네트워크 통신을 위해 필요 ACCESS_NETWORK_STATE 필수
normal 네트워크 상태 확인을 위해 필요 FOREGROUND_SERVICE 선택
normal 화면공유 목적의 MediaProjection을 위해 필요 MODIFY_AUDIO_SETTINGS 선택
normal 오디오 장치 관리를 위해 필요 RECORD_AUDIO 필수
dangerous 로컬 오디오 전송 시 필요 CAMERA 필수
dangerous 로컬 카메라 전송 시 필요 - SDK는 기본적으로 런타임 권한 요청이 필요한 2가지(
서비스 개발 순서
카카오 i 커넥트 라이브 SDK 2.0을 사용하여 간단한 실시간 화상회의 서비스를 구현하는 개발 순서는 다음과 같습니다. 서비스 개발은 사전 작업을 모두 완료해야 진행할 수 있습니다.
안내
카카오 i 커넥트 라이브 서비스에서 Local Participant(로컬 참여자)는 나 자신을 의미하며, Remote Participant(리모트 참여자)는 Room의 다른 참여자, 즉 리모트 참여자(Remote Participant)을 의미합니다.
예제 시나리오
본 문서에서 다루는 개발 예제는 Github의 simple 프로젝트를 기준으로 하며, 개발 시나리오는 다음과 같습니다.
그림예제 시나리오
- 앱 시작시 로컬카메라를 사용해 프리뷰를 보여줍니다.
- [JOIN] 버튼 터치 시 설정한 roomId에 해당하는 Room으로 접속합니다.
- Remote Participant(리모트 참여자)가 동일 roomId로 동일 Room에 접속하면 서로의 비디오와 오디오를 시청합니다.
- [CLOSE] 버튼 터치 시 연결을 끊고 앱을 종료합니다.
Step 1. SDK 초기화하기
Android 버전의 Kakao i Connect Live SDK 2.0을 초기화합니다. 모든 메서드를 호출하기 전 반드시 init() 메서드를 호출해야 합니다.
코드예제SDK 초기화하기 Syntax
ConnectLive.init(this)
Step 2. 서비스 인증하기
콘솔에서 발급받은 서비스 인증 정보를 signIn() 메서드의 인자로 전달하여 서비스를 인증합니다. SDK 인증 방식은 커넥트 라이브 내부 인증과 서비스 자체 인증으로 구분됩니다. 각 인증 방식에 대한 자세한 설명은 signIn(카카오 i 커넥트 라이브 내부 인증)과 signIn(서비스 자체 인증)을 참고하시기 바랍니다.
코드예제커넥트 라이브 내부 인증 Syntax
// 커넥트 라이브 내부 인증
ConnectLive.signIn {
serviceId = "ICLEXMPLPUBL"
servicSecret = "YOUR0SRVC0SECRET"
}
코드예제서비스 자체 인증 Syntax
// 서비스 자체 인증
ConnectLive.signIn {
endpoint = "https://icl2-provisioning-ap2.k9ertc.io/api/rpc"
serviceId = "ICLEXMPLPUBL"
token = "YOUR_SERVICE_TOKEN"
errorHandler = ErrorHandler { code, message, isFatal ->
// 에러 처리
}
}
안내
인증 방식 별 인증 프로세스와 키 처리에 대한 자세한 설명은 인증 및 키 처리 문서를 참고하시기 바랍니다.
Step 3. 권한 확인 및 로컬카메라 렌더링하기
디바이스 권한을 확인하고 로컬 카메라를 생성하여 바인딩하는 방법은 다음과 같습니다.
-
Activity Result API의 registerForActivityResult()를 활용하여 권한 확인 후, Local camera를 생성하고 local(VideoRenderer) 뷰에
bind
합니다.코드예제권한 확인 및 로컬카메라 렌더링 1단계 Syntax
private lateinit var binding: ActivityMainBinding private var camera: LocalCamera? = null private val requestPermissionForActivateMedia = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result -> result[Manifest.permission.CAMERA]?.let { cameraGranted -> if (cameraGranted && camera == null) { camera = ConnectLive.createLocalCamera().apply { start() } binding.local.bind(camera) } } }
-
ActivityResultLauncher 클래스 launch 시
Manifest.permission.CAMERA
와Manifest.permission.RECORD_AUDIO
를 주입합니다.코드예제권한 확인 및 로컬카메라 렌더링 2단계 Syntax
requestPermissionForActivateMedia.launch( arrayOf( Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO ) )
Step 4. 화면(View) 구성하기
SDK에서 제공하는 VideoRenderer를 사용하여 내 카메라를 렌더링하는 local( VideoRenderer)과 리모트 참여자의 영상을 렌더링하는 remote(VideoRenderer)를 생성합니다. 예제에서는 Room에 접속과 종료 트리거링을 위한 Button을 포함합니다.
코드예제화면(View) 구성하기 Syntax
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<io.kakaoi.connectlive.view.VideoRenderer
android:id="@+id/local"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="9:16"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/btn_action"/>
<io.kakaoi.connectlive.view.VideoRenderer
android:id="@+id/remote"
android:layout_width="200dp"
android:layout_height="0dp"
android:layout_margin="10dp"
app:layout_constraintDimensionRatio="9:16"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/btn_action"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_action"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="join"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
위 예제에서는 viewBinding
을 사용하였습니다. viewBinding 설정은 build.gradle(:simple)
에서 확인하시기 바랍니다.
코드예제viewBinding 설정 Syntax
buildFeatures{
viewBinding true
}
그림화면 및 버튼 구성 예제
Step 5. 오디오 포커스 요청하기
SDK에서 오디오를 관리하기 위해 AudioHelper 클래스에 오디오 포커스를 요청합니다
코드예제오디오 포커스 요청하기 Syntax
AudioHelper.acquireFocus(context = this)
앱에서 카카오 i 커넥트 라이브 SDK 2.0의 사용 시나리오 종료 시, releaseFocus() 메서드를 통해 오디오 포커스 요청을 취소해야 합니다.
코드예제오디오 포커스 요청 취소 Syntax
override fun onDestroy() {
// ...
AudioHelper.releaseFocus()
}
Step 6. Room 객체 생성 및 Events 처리하기
리모트 참여자(Remote Participant)와 통신하기 위해서는 같은 Room에 들어가야 하며, 이를 위해 Room 객체를 생성해야 합니다. Room은 서비스에 따라 채팅방, 화상회의실 등 참여자들이 서비스를 이용하기 위해 입장하는 공간입니다. 자세한 설명은 createRoom()을 참고하시기 바랍니다.
코드예제Room 객체 생성 Syntax
room = ConnectLive.createRoom(events = OnEventListener())
Room을 생성할 때 Events를 등록해야 하며, 해당 샘플에서는 다음과 같이 작성합니다. Room에서 발생하는 다양한 이벤트의 처리는 Room.Events를 참고하시기 바랍니다.
코드예제Events 등록 Syntax
private lateinit var binding: ActivityMainBinding
private var localVideo: LocalVideo? = null
private inner class OnEventListener : EventsCallback {
override fun onConnecting(progress: Float) {
// 접속중...
}
override fun onConnected(participants: List<RemoteParticipant>) {
// 해당 Room 접속 완료
// 기존에 참여중이던 사람들의 목록을 받습니다.
// 예제에서는 처음 들어는 비디오만 bind 하여 확인 합니다.
if (participants.isNotEmpty()) {
val remoteVideo = participants.flatMap { it.videos.values }.first()
binding.remote.bind(remoteVideo)
}
// 버튼의 문구를 변경합니다.
binding.btnAction.text = "close"
}
override fun onDisconnected(reason: DisconnectedReason) {
finish()
}
override fun onError(code: Int, message: String, isFatal: Boolean) {
val errorMessage = "code: $code, message: $message, isFatal: $isFatal"
Log.d("onError", errorMessage)
if (isFatal)
finish()
}
override fun onLocalVideoPublished(video: LocalVideo) {
// 나의 video가 publish 되었을때 불리며, 내 video를 local에 렌더링
localVideo = video
binding.local.bind(localVideo)
}
override fun onRemoteVideoPublished(participant: RemoteParticipant, video: RemoteVideo) {
// 내가 참여 후 published 된 다른사람의 video를 VideoRenderer 에 bind
binding.remote.bind(video)
}
override fun onRemoteVideoUnpublished(participant: RemoteParticipant, video: RemoteVideo) {
// 다른 사람이 퇴장 혹은 video를 unPublish 했을때 unbind
binding.remote.unbind()
}
}
Step 7. Room 접속하기
다음은 Button의 문구가 “join”일 때 클릭 이벤트가 들어오면 Room에 접속하는 샘플 코드입니다. Room에 접속할 때는 connect()메서드를 사용하며, Room의 고유한 ID 값인 roomId를 인자로 사용합니다.
샘플에는 roomId 값이 비어 있어 해당 값을 기입해야 합니다. roomId는 영문 대소문자, 숫자, -
으로 구성이 가능하며, 길이 제한은 32자입니다.
주의
샘플에는roomId
값이 비어 있으니, 해당 값을 기입해야 합니다.
- roomId는 영문 대소문자, 숫자,
-
으로 구성이 가능하며, 길이 제한은 32자입니다.roomId
값이 허용조건에 해당하지 않는 경우 Join 버튼을 눌렀을때 앱이 종료됩니다.
코드예제Room 접속하기 Syntax
private lateinit var binding: ActivityMainBinding
private lateinit var room: Room
private var camera: LocalCamera? = null
binding.btnAction.setOnClickListener {
if ((it as Button).text == "join") {
// 로컬 프리뷰카메라 정지및 해제
camera?.stop()
camera?.dispose()
// 해당 roomId로 접속
room.connect(roomId = "roomId를 넣어주세요.")
val localMedia = ConnectLive.createLocalMedia().apply {
video?.isEnabled = true
audio?.isEnabled = true
}
// 내 localMedia publish
room.publish(localMedia)
}
}
자신의 화면을 Room에 게시하기
참여자 자신의 스크린 화면을 Room에 게시하기 위해서는, createLocalScreen()
을 통해 LocalScreen 객체를 생성하고 게시하면 됩니다. 자세한 내용은 createLocalScreen()을 참고하시기 바랍니다.
코드예제자신의 화면을 Room에 게시하기 Syntax
val localScreen = ConnectLive.createLocalScreen(data, onStop = { })
publish(localScreen)
Step 8. 로컬 미디어 처리하기
createLocalMedia() 메서드를 사용하여 참여자 자신의 로컬 마이크와 카메라에 접근할 수 있습니다. 이를 통해 실시간 스트리밍 서비스에 이용할 수 있는 LocalMedia 객체가 생성됩니다. LocalMedia는 audio(오디오)와 video(비디오) 객체를 가지고 있으며, 서비스에 맞게 객체를 설정할 수 있습니다.
코드예제createLocalMedia() 메서드 Syntax
private lateinit var room: Room
val localMedia = ConnectLive.createLocalMedia().apply {
video?.isEnabled = true
audio?.isEnabled = true
}
room.publish(localMedia)
게시 중인 video(비디오)를 내가 원하는 Step 3. 권한 확인 및 로컬카메라 렌더링하기에서 선언한 local view(VideoRenderer)에 바인딩(binding)합니다.
코드예제local view(VideoRenderer)에 bind Syntax
private lateinit var binding: ActivityMainBinding
private inner class OnEventListener : EventsCallback {
...
override fun onLocalVideoPublished(video: LocalVideo) {
// 나의 video가 publish 되었을때 불리며, 내 video를 local에 렌더링합니다.
localVideo = video
binding.local.bind(localVideo)
}
...
}
Step 9. 리모트 미디어 처리하기
Room에 성공적으로 접속하면 onConnected 이벤트가 호출됩니다. onConnected에서는 기존에 참여 중인 모든 참여자의 정보(RemoteParticipant)를 받을 수 있습니다. 이 정보에서 RemoteVideo를 꺼내 Step 4. 화면(View) 구성하기에서 선언한 remote view(VideoRenderer)에 바인딩(binding)하면 리모트 참여자(Remote Participant)의 리모트 미디어(Remote Media)를 수신할 수 있습니다.
코드예제리모트 미디어 처리하기 Syntax
private lateinit var binding: ActivityMainBinding
private inner class OnEventListener : EventsCallback {
...
override fun onConnected(participants: List<RemoteParticipant>) {
// 해당 Room 접속 완료
// 기존에 참여중이던 사람들의 목록을 받습니다.
// 예제에서는 처음 들어는 비디오만 bind하여 확인합니다.
if (participants.isNotEmpty()) {
val remoteVideo = participants.flatMap { it.videos.values }.first()
binding.remote.bind(remoteVideo)
}
}
}
안내
위 예제에서는 단 한 명의 리모트 참여자(Remote Participant)만 볼 수 있도록 구현이 되어있으며, 여러 명의 참여자가 있을 때 최초 한 명만 Rendering 되게 됩니다. remote view(VideoRenderer) 사용 시, 이 점을 유의하시기 바랍니다.
만약 리모트 참여자가 로컬 참여자(나 자신)보다 늦게 참여한 경우에는 onRemoteVideoPublished
의 이벤트를 확인하여, Step 4. 화면(View) 구성하기에서 선언한 remote view(VideoRenderer)에 바인딩(binding)하여 리모트 참여자(Remote Participant)의 미디어를 수신할 수 있습니다.
코드예제onRemoteVideoPublished 이벤트 Syntax
private lateinit var binding: ActivityMainBinding
private inner class OnEventListener : EventsCallback {
...
override fun onRemoteVideoPublished(participant: RemoteParticipant, video: RemoteVideo) {
// 내가 참여후 published 된 다른사람의 video를 VideoRenderer에 bind
binding.remote.bind(video)
}
...
}
리모트 참여자가 Room에서 퇴장 또는 video(비디오)의 게시를 취소한 경우에는 onRemoteVideoUnpublished 이벤트가 발생합니다. 해당 이벤트에서 unbind 하면 렌더링을 취소할 수 있습니다.
코드예제onRemoteVideoUnpublished 이벤트 Syntax
private lateinit var binding: ActivityMainBinding
private inner class OnEventListener : EventsCallback {
...
override fun onRemoteVideoUnpublished(participant: RemoteParticipant, video: RemoteVideo) {
binding.remote.unbind()
}
...
}
Step 10. Room 접속 해제하기
다음은 Button의 문구가 “join”이 아닌 경우 접속 해제를 하는 코드입니다.
샘플에서는 ConnectLive.createRoom()으로 생성된 Room 객체에 disconnect() 함수를 호출하여 Room 접속을 종료합니다.
코드예제Room 접속 해제하기 Syntax
binding.btnAction.setOnClickListener {
if ((it as MaterialButton).text == "join") {
...
} else {
// 연결해제
room.disconnect()
}
}
주요 이벤트
Android 버전의 카카오 i 커넥트 라이브 SDK 2.0의 주요 이벤트는 다음과 같습니다. 주요 이벤트 외 모든 이벤트 정보는 Room.Events 문서를 참고하시기 바랍니다.
onConnected
onConnected는 참여자가 Room과의 연결이 완료되었을 때 발생하는 이벤트입니다. 해당 이벤트는 이미 Room에 참여하고 있는 Remote Participant(리모트 참여자) 목록을 인자로 전달합니다. RemoteVideo들을 VideoRenderer에 바인드(bind)시키면 영상이 렌더링됩니다.
코드예제onConnected Syntax
private val remoteVideos = MutableLiveData(emptyList<RemoteVideo>())
private inner class OnEventListener : EventsCallback {
...
override fun onConnected(participants: List<RemoteParticipant>) {
remoteVideos.value = participants.flatMap { it.videos.values }
}
...
}
onParticipantEntered
onParticipantEntered는 새로운 Remote Participant(리모트 참여자)가 Room에 입장했을 때 호출됩니다. 이곳에서 새로운 Remote Participant(리모트 참여자) 목록을 만들어 화면에 표시할 수 있습니다.
코드예제onParticipantEntered Syntax
private inner class OnEventListener : EventsCallback {
...
override fun onParticipantEntered(participant: RemoteParticipant) {
// participant를 참여자 목록에 추가
}
...
}
onParticipantLeft
Remote Participant(리모트 참여자)가 Room에서 퇴장하여 Room과 연결이 끊겼을 때 호출됩니다. 해당 이벤트는 Remote Participant(리모트 참여자) 정상 종료와 비정상 종료를 구분하지 않습니다. 정상 종료의 경우 이벤트는 바로 호출이 되며 비정상 종료의 경우 수 초 후에 이벤트가 호출됩니다. 이곳에서 기존 Remote Participant(리모트 참여자) 목록에서 해당 참여자를 제거할 수 있습니다.
코드예제onParticipantLeft Syntax
private inner class OnEventListener : EventsCallback {
...
override fun onParticipantLeft(participant: RemoteParticipant) {
// participant를 참여자 목록에서 제거
}
...
}
onRemoteVideoPublished
Remote Participant(리모트 참여자)가 비디오를 공유했을 때 호출됩니다. 해당 이벤트는 remoteVideo와 remoteParticipant 두 객체를 인자로 전달받아, 어떤 비디오를 어떤 Remote Participant(리모트 참여자가) 공유했는지 알 수 있으며, remoteVideo.owner 를 통해 공유자를 확인할 수 있습니다.
코드예제onRemoteVideoPublished Syntax
private val remoteVideos = MutableLiveData(emptyList<RemoteVideo>())
private inner class OnEventListener : EventsCallback {
...
override fun onRemoteVideoPublished(participant: RemoteParticipant, video: RemoteVideo) {
remoteVideos.value = remoteVideos.value.orEmpty() + video
}
...
}
onRemoteVideoUnpublished
Remote Participant(리모트 참여자)가 비디오를 공유 해제하면 호출됩니다.
코드예제onRemoteVideoUnpublished Syntax
private val remoteVideos = MutableLiveData(emptyList<RemoteVideo>())
private inner class OnEventListener : EventsCallback {
...
override fun onRemoteVideoUnpublished(participant: RemoteParticipant, video: RemoteVideo) {
remoteVideos.value = remoteVideos.value.orEmpty() - video
}
...
}
에러 처리
Android 버전의 카카오 i 커넥트 라이브 SDK 2.0의 에러에는 서버로부터 발생한 서버 에러(Server Error)와 클라이언트에서 비정상 접근으로 인한 에러(throws)가 존재합니다. 서버 에러는 ErrorHandler와 Room.Events.onError 이벤트로 처리할 수 있습니다.
표에러 처리에러 타입 | 설명 |
---|---|
서버 에러
- 서버에서 발생한 에러 코드와 메시지를 담고 있으며, error code는 음수 다섯 자릿수로 표현 - 서버 에러는 ErrorHandler 또는 Room.Events.onError 이벤트로 처리 |
|
ErrorHandler | 인증 체계와 관련된 에러를 처리 - 서버의 응답이나 사전의 정의한 오류 코드를 내보냄 |
Room.Events.onError | Room 생성 후 발생하는 클라이언트 에러를 처리 |
클라이언트 에러(throws) | 클라이언트 에러 - 비정상 접근으로 인한 SDK 발생 Throw이며, 메시지에는 에러 코드가 포함됨 |
서버 에러 처리
서버 에러는 ErrorHandler 또는 Room.Events.onError 이벤트로 처리합니다.
ErrorHandler
ConnectLive.signIn() 메서드에서 ErrorHandler를 정의하여, 인증 체계와 관련된 에러를 확인할 수 있습니다.
코드예제ErrorHandler Syntax
ConnectLive.signIn {
serviceId = "ICLEXMPLPUBL"
serviceSecret = "YOUR0SRVC0SECRET"
errorHandler = ErrorHandler { code, message, isFatal ->
val errorMessage = "Error(ConnectLive): code: $code / message: $message / isFatal: $isFatal"
Log.e("TAG", errorMessage)
if (isFatal)
finish()
}
}
Room.Events.onError
Room에 연결부터 종료까지, 해당 객체를 사용하면서 발생한 에러를 확인할 수 있습니다.
코드예제Room.Events.onError Syntax
private inner class OnEventListener : EventsCallback {
...
override fun onError(code: Int, message: String, isFatal: Boolean) {
val errorMessage = "Error(ConnectLive): code: $code / message: $message / isFatal: $isFatal"
Log.e("TAG", errorMessage)
if (isFatal)
finish()
}
...
}
클라이언트 에러 처리
클라이언트 에러로 비정상 접근으로 인해 SDK에서 Throw를 발생시키며, 메시지에는 에러 코드가 포함됩니다
표비정상 접근으로 발생한 ThrowThrows | 설명 |
---|---|
IllegalStateException | 다음의 경우를 포함
- 인증을 수행하는 signIn(카카오 i 커넥트 라이브 내부 인증) 메서드를 호출하지 않은 상태에서 Room에 접근한 경우 - createRoom 당시 로그인이 유효하지 않음
- 기존 로그인이 유효한 상태로 재인증이 필요 없음 - 장치 접근 권한(CAMERA, RECORD_AUDIO)이 확보되지 않음 |
IllegalArgumentException | 다음의 경우를 포함
- signIn 중 필요한 정보가 누락되거나 불필요한 정보가 존재하는 경우
- 스트림의 상태가 video/audio 중 하나에 포함되지 않는 경우 |
RuntimeException | Local Video 또는 Audio 생성에 실패함 |
에러 코드
전체 에러 코드는 다음과 같습니다.
표에러 코드 전체 목록Code | Message | 설명 |
---|---|---|
1103 | 인증을 위한 서비스 정보가 입력되지 않았습니다. | signIn() 메서드 사용 시 인증정보가 모두 입력되지 않았을 경우 |
1106 | Room 생성 전 인증이 필요합니다. | creteRoom() 메서드 사용 당시 미인증 상태인 경우 |
1208 | 로컬 카메라 생성에 실패했습니다. | 비디오 트랙을 얻기 위해 createLocalMedia() 메서드를 호출하는 경우 |
1209 | 로컬 오디오 생성에 실패했습니다. | 오디오 트랙을 얻기 위해 createLocalMedia() 메서드를 호출하는 경우 |
1210 | 이미 Focus가 존재합니다. | AudioHelper의 포커스가 이미 존재한 경우이며, isFocusAcquired 를 통해 미리 확인할 수 있음 |
1301 | 입력한 룸 id가 지원하지 않는 길이, 문자를 포함합니다.(32자 이하, 영문자/숫자/- 만 가능) |
connect() 메서드 호출 시 room id를 검증하지 못했을 때 발생할 수 있음 |
1326 | 비디오 구독을 위한 리시버를 할당받을 수 없습니다. | video Receiver를 추가할 수 없는 경우 |
1361 | 비정상 스트림 정보가 존재합니다. | subscribe() 메서드 호출 시 이미 구독 중인 비디오라면 발생할 수 있음 |
1362 | 이미 게시 중인 video입니다. | 이미 게시된 video를 중복으로 게시할 경우 |
1363 | 이미 게시 중인 audio입니다. | 이미 게시된 audio를 중복으로 게시할 경우 |
1401 | PeerConnection 생성이 실패했습니다. | connect() 메서드 호출 시 발생할 수 있음 |
1402 | 데이터 채널 생성이 실패했습니다. | connect() 메서드 호출 시 발생할 수 있음 |
1439 | 송신 세션의 Offer, Answer 설정이 실패했습니다. | 미디어를 Room에 송출 중 발생할 수 있음 |
1440 | Description 설정에 실패했습니다. | connect() 메서드 호출 시 발생할 수 있음 |
1442 | 스트림 추가 에러(native 원본 메시지) | 스트림 추가 에러 |
1450 | 스트림 설정 변경에 실패했습니다. | 스트림 설정 변경에 확인되지 않은 Participant가 있는 경우 |
1452 | 스트림 설정 요청이 실패했습니다. | 이미 요청되었거나, 존재하지 않는 요청인 경우 |
1911 | publish() 후 extraValue 변경은 불가합니다. | publish() 메서드 호출 후, video 또는 audio의 extraValue를 수정한 경우 |
1912 | 통신 프로토콜 종료됨 | 통신 프로토콜이 종료된 상태에서 이벤트를 보내려는 경우 |
안내
클라이언트 관련 에러 코드 및 설명은 Error Code 문서를 참고하시기 바랍니다.