本文にスキップする
Under translation
このページは現在翻訳中です。
Version: 6.1

Implement your first group video call

PlanetKit lets you integrate audio and video call functionality for 1-to-1 calls or group calls into your app. This guide shows how to get started with the implementation of a group video call in your Android app.

Note

For faster development, you can implement your app on top of our quick start.

Prerequisites

Create a project

To get started, open Android Studio and create a new project as follows:

  1. Click New Project in the Welcome to Android Studio window.
  2. Select Empty Activity and click Next.
  3. In the New Project window, do the following.
    1. Enter your project name in the Name field.
    2. Select API level 21 or higher in Minimum SDK.
    3. Select "Groovy DSL (build.gradle)" in Build configuration language.
    4. Click Finish. Create an Android project

Install the SDK

Install the SDK using Gradle. Add the following dependency to your module-level build.gradle file:

build.gradle
dependencies {
...
implementation 'com.linecorp.planetkit:planetkit:6.1.0'
...
}
Note

Starting with version 5.3.3, PlanetKit for Android is distributed through the Maven Central Repository.

If the Maven Central Repository is not set up in your project, add the repository as follows:

build.gradle
// Root-level build.gradle
allprojects {
repositories {
mavenCentral()
}
}

Request system permissions

To enable video call functionality, PlanetKit for Android requires system permissions. The following permissions are included in AndroidManifest.xml of PlanetKit:

AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

Users need to grant runtime permissions when they launch the app for the first time. To facilitate this process, request the RECORD_AUDIO, CAMERA, READ_PHONE_STATE, and BLUETOOTH_CONNECT permissions as follows.

Permissions.kt
fun checkAllRequirePermissions(context: Context): MutableList<String> {
val permissions: MutableList<String> = mutableListOf()

if (ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO)
!= PackageManager.PERMISSION_GRANTED) {
permissions.add(Manifest.permission.RECORD_AUDIO)
}

if (ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
permissions.add(Manifest.permission.CAMERA)
}

if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) {
permissions.add(Manifest.permission.READ_PHONE_STATE)
}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
&& ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT)
!= PackageManager.PERMISSION_GRANTED) {
permissions.add(Manifest.permission.BLUETOOTH_CONNECT)
}
return permissions
}

fun requestPermissions(activity: Activity, permissions: Array<String>) {
ActivityCompat.requestPermissions(activity, permissions,0)
}

val requirePermissions = checkAllRequirePermissions(this)
if (requirePermissions.isNotEmpty()) {
requestPermissions(this, requirePermissions.toTypedArray())
return
}
Note

For more information about requesting runtime permissions, see the Android official documentation.

Initialize the SDK

To call the PlanetKit APIs, you must initialize PlanetKit first. Initialize PlanetKit using PlanetKit.initialize() with a PlanetKitConfiguration object.

You must set the server URL (planet_base_url) in the PlanetKitConfiguration object before calling PlanetKit.initialize(). Make sure that you use an appropriate planet_base_url depending on the development environment that you're using.

GroupVideoCallApplication.kt
class GroupVideoCallApplication : Application() {
override fun onCreate() {
val config = PlanetKit.PlanetKitConfiguration.Builder(getApplicationContext())
.setServerUrl(planet_base_url)
.build()

PlanetKit.initialize(config) { isSuccessful, isVideoHwCodecSupport, userAgent ->
// Implement the completion callback if necessary
}
}
}
Note

The PlanetKit.initialize() method must be called once initially in your app. It is recommended to initialize the SDK in the onCreate() method of your Application instance.

Get the access token

In the client app, request your app server to generate an access token and get the generated access token.

Note

You must get a new access token and use it each time you call PlanetKit.joinConference().

Join a group video call

To join a group video call, call PlanetKit.joinConference() with the following arguments:

  • PlanetKitConferenceParam object, which includes the following properties:
    • myId: Local user's user ID
    • roomId: Room ID
    • myServiceId: Local user's service ID
    • roomServiceId: Room service ID
    • mediaType: Set to PlanetKitMediaType.AUDIOVIDEO for video call
    • accessToken: Access token
  • ConferenceListener object, which includes the implementation of event callbacks
GroupVideoCallActivity.kt
fun joinConferenceExample(userId: String, roomId: String, serviceId: String, accessToken: String)
{
val param = PlanetKitConferenceParam.Builder()
.myId(userId)
.roomId(roomId)
.myServiceId(serviceId)
.roomServiceId(serviceId)
.accessToken(accessToken)
.mediaType(PlanetKitMediaType.AUDIOVIDEO)
.build()

val result = PlanetKit.joinConference(param, conferenceListener = object : ConferenceListener {

override fun onConnected(conference: PlanetKitConference,
isVideoHwCodecEnabled: Boolean,
isVideoShareModeSupported: Boolean) {
// This is called when the call is connected.
// Write your own code here.
}

override fun onDisconnected(conference: PlanetKitConference,
param: PlanetKitDisconnectedParam) {
// This is called when the call is disconnected.
// Write your own code here.
}

override fun onPeerListUpdated(param: PlanetKitConferencePeerListUpdatedParam) {
// This is called when the list of peers is updated.
// Write your own code here.
}

override fun onPeersVideoUpdated(conference: PlanetKitConference, param: PlanetKitConferenceVideoUpdateParam) {
// This is called when the video of one or more peers is updated.
// Write your own code here.
}
})

if (result.reason == PlanetKitStartFailReason.NONE && result.conference != null) {
// The "result.conference" instance is the main instance to call APIs from now on.
// You must keep it to control this call.
}
else {
// Handle an error by referring to result.reason.
}
}
Note

Users need the room ID to enter the room from the client app, so the room ID must be shared with other users through an application-defined communication channel.

Render a video view for the local user

To display the local user's video, use the PlanetKitMyView component as follows.

What is PlanetKitMyView?

PlanetKitMyView is a UI component provided by PlanetKit, which renders the local user's video streams. It handles:

  • Rendering the local user's video
  • Tracking first frame rendering
  • Notifying changes in video status
  • Managing lifecycle events via a listener interface

Declare PlanetKitMyView in the layout

Declare PlanetKitMyView in the layout file. This view is typically wrapped with UI overlays for:

  • No video (no_video)
  • Video resumed (video_resume)
simple_my_view.xml
<com.linecorp.planetkit.ui.PlanetKitMyView
android:id="@+id/my_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- Overlays for video status -->
<LinearLayout android:id="@+id/no_video" ... />
<LinearLayout android:id="@+id/video_resume" ... />
...

Bind the conference to the view

Bind the current conference instance to PlanetKitMyView and register a listener.

SimpleMyView.kt
fun setMe() {
showNoVideoView() // Default state before rendering
PlanetKit.getConference()?.let {
binding.myView.setMe(it, myViewListener)
}
}

Implement the listener for PlanetKitMyView

Implement PlanetKitMyView.MyViewListener to handle initialization, first frame rendering, and video status updates.

  • onInitialized is called when PlanetKitMyView is ready.
  • onRenderFirstFrame is called when the first video frame is rendered.
  • onVideoStatusUpdated informs whether the video is enabled or disabled.
SimpleMyView.kt
private val myViewListener = object : PlanetKitMyView.MyViewListener {
override fun onInitialized(userData: Any?) {
val status = binding.myView.myVideoStatus
when (status.videoState) {
VideoState.DISABLED -> showNoVideoView()
VideoState.ENABLED -> showResumedView()
else -> {}
}
}

override fun onRenderFirstFrame() {
binding.videoResume.isVisible = false
}

override fun onVideoStatusUpdated(videoStatus: PlanetKitVideoStatus) {
when (videoStatus.videoState) {
VideoState.DISABLED -> showNoVideoView()
VideoState.ENABLED -> showResumedView()
else -> {}
}
}
}

Manage UI based on video state

Show or hide overlays depending on the video state.

  • If the video is off, show the noVideo overlay.
  • If the video is on, show videoResume overlay until the first frame is rendered, then hide it.
SimpleMyView.kt
private fun showNoVideoView() {
binding.videoResume.isVisible = false
binding.noVideo.isVisible = true
}

private fun showResumedView() {
binding.videoResume.isVisible = true
binding.noVideo.isVisible = false
binding.myView.resetFirstFrameRendered()
}

Handle PlanetKitMyView in the activity

Call setMe() on your custom view when the group call is connected, which initializes the PlanetKitMyView.

GroupVideoCallActivity.kt
override fun onConnected(conference: PlanetKitConference, ...) {
binding.simpleMyView.setMe()
}

Render a video view for peers

To display peers' video, use the PlanetKitPeerView component as follows.

What is PlanetKitPeerView?

PlanetKitPeerView is a UI component provided by PlanetKit, which renders video streams from peers in a group call. It handles:

  • Rendering a video for a specific PlanetKitConferencePeer
  • Tracking first frame rendering
  • Notifying changes in video status
  • Managing lifecycle events via a listener interface

Declare PlanetKitPeerView in the layout

Declare PlanetKitPeerView in the layout file. This view is typically wrapped with UI overlays for:

  • No video (no_video)
  • Video paused (video_pause)
  • Video resumed (video_resume)
simple_peer_view.xml
<com.linecorp.planetkit.ui.PlanetKitPeerView
android:id="@+id/peer_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- Overlays for video status -->
<LinearLayout android:id="@+id/no_video" ... />
<LinearLayout android:id="@+id/video_pause" ... />
<LinearLayout android:id="@+id/video_resume" ... />
...

Bind a peer to the view

Bind a PlanetKitConferencePeer to PlanetKitPeerView and register a listener.

SimplePeerView.kt
fun setUser(newConferencePeer: PlanetKitConferencePeer, userData: Any? = null) {
PlanetKit.getConference()?.let {
conferencePeer = newConferencePeer
if (!binding.peerView.setPeer(it, newConferencePeer, peerViewListener, userData)) {
Log.e(TAG, "Failed to set peer video")
}
}
}

Implement the listener for PlanetKitPeerView

Implement PlanetKitPeerView.PeerViewListener to manage state changes such as video status and peer disconnection.

  • onInitialized is called when PlanetKitPeerView is ready.
  • onRenderFirstFrame is called when the first video frame is rendered.
  • onDisconnected is called when the peer is disconnected from the call.
  • onVideoUpdated informs whether the video is enabled, paused, or disabled.
SimplePeerView.kt
private val peerViewListener = object : PlanetKitPeerView.PeerViewListener {
override fun onInitialized(peer, userData) {
updateVideo(peer.getVideoStatus(...).videoStatus)
}

override fun onRenderFirstFrame(peer) {
// Hide all overlays
}

override fun onDisconnected(peer) {
clearUser()
}

override fun onVideoUpdated(peer, videoStatus, subgroupName) {
updateVideo(videoStatus)
}
}

Control video and the UI

Update the UI based on the peer's video status.

SimplePeerView.kt
private fun updateVideo(videoStatus: PlanetKitVideoStatus) {
when (videoStatus.videoState) {
VideoState.DISABLED -> showNoVideoView()
VideoState.ENABLED -> {
startVideoImpl(binding.peerView)
}
VideoState.PAUSED -> showPausedView()
}
}

When the video is enabled, start rendering the video with the recommended resolution.

SimplePeerView.kt
private fun startVideoImpl(peerView: PlanetKitPeerView) {
showResumedView()
peerView.startVideo(PlanetKitVideoResolution.RECOMMENDED, ..., callbacks)
...
}

Handle the peer view in the activity

Call setUser() on your custom view when a peer for rendering video is selected.

GroupVideoCallActivity.kt
binding.simplePeerView.setUser(selectedPeer)

Call clearUser() on your custom view to remove the peer and reset the view state.

GroupVideoCallActivity.kt
binding.simplePeerView.clearUser()

Next steps

See the following documents to learn more about the various features provided by PlanetKit and how to use each feature.

  • Call flow: Familiarize yourself with the call flow for each call type.
  • Subgroup: Read the guides on subgroups, which allows you to implement advanced features such as multi-subgroup rooms or translation rooms.
  • Extended functions: Explore the guides on extended functions, such as screen share and data sessions.
  • Code examples: See the code examples that you can use for implementing your own app.
  • Reference: Refer to the API reference, API changelog, and release notes.