Code Monkey home page Code Monkey logo

client-sdk-android's Introduction

The LiveKit icon, the name of the repository and some sample code in the background.

Android Kotlin SDK for LiveKit

Maven Central

Use this SDK to add realtime video, audio and data features to your Android/Kotlin app. By connecting to LiveKit Cloud or a self-hosted server, you can quickly build applications such as multi-modal AI, live streaming, or video calls with just a few lines of code.

Table of Contents

Docs

Docs and guides at https://docs.livekit.io.

API reference can be found at https://docs.livekit.io/client-sdk-android/index.html .

Note

This is v2 of the Android SDK. When migrating from v1.x to v2.x you might encounter a small set of breaking changes. Read the migration guide for a detailed overview of what has changed.

Installation

LiveKit for Android is available as a Maven package.

...
dependencies {
  def livekit_version = "2.8.1"

  implementation "io.livekit:livekit-android:$livekit_version"
  // CameraX support with pinch to zoom, torch control, etc.
  implementation "io.livekit:livekit-android-camerax:$livekit_version"

  // Snapshots of the latest development version are available at:
  // implementation "io.livekit:livekit-android:2.8.2-SNAPSHOT"
}

Compose-based apps should check out our Android Components SDK for composables support.

You'll also need JitPack as one of your repositories. In your settings.gradle file:

dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        //...
        maven { url 'https://jitpack.io' }

        // For SNAPSHOT access
        // maven { url 'https://s01.oss.sonatype.org/content/repositories/snapshots/' }
    }
}

Usage

Permissions

LiveKit relies on the RECORD_AUDIO and CAMERA permissions to use the microphone and camera. These permission must be requested at runtime. Reference the sample app for an example.

Publishing camera and microphone

room.localParticipant.setCameraEnabled(true)
room.localParticipant.setMicrophoneEnabled(true)

Sharing screen

// create an intent launcher for screen capture
// this *must* be registered prior to onCreate(), ideally as an instance val
val screenCaptureIntentLauncher = registerForActivityResult(
    ActivityResultContracts.StartActivityForResult()
) { result ->
    val resultCode = result.resultCode
    val data = result.data
    if (resultCode != Activity.RESULT_OK || data == null) {
        return@registerForActivityResult
    }
    lifecycleScope.launch {
        room.localParticipant.setScreenShareEnabled(true, data)
    }
}

// when it's time to enable the screen share, perform the following
val mediaProjectionManager =
    getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
screenCaptureIntentLauncher.launch(mediaProjectionManager.createScreenCaptureIntent())

Rendering subscribed tracks

LiveKit uses SurfaceViewRenderer to render video tracks. A TextureView implementation is also provided through TextureViewRenderer. Subscribed audio tracks are automatically played.

class MainActivity : AppCompatActivity() {

    lateinit var room: Room

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main)

        // Create Room object.
        room = LiveKit.create(applicationContext)

        // Setup the video renderer
        room.initVideoRenderer(findViewById<SurfaceViewRenderer>(R.id.renderer))

        connectToRoom()
    }

    private fun connectToRoom() {

        val url = "wss://your_host"
        val token = "your_token"

        lifecycleScope.launch {

            // Setup event handling.
            launch {
                room.events.collect { event ->
                    when (event) {
                        is RoomEvent.TrackSubscribed -> onTrackSubscribed(event)
                        else -> {}
                    }
                }
            }

            // Connect to server.
            room.connect(
                url,
                token,
            )

            // Turn on audio/video recording.
            val localParticipant = room.localParticipant
            localParticipant.setMicrophoneEnabled(true)
            localParticipant.setCameraEnabled(true)
        }
    }

    private fun onTrackSubscribed(event: RoomEvent.TrackSubscribed) {
        val track = event.track
        if (track is VideoTrack) {
            attachVideo(track)
        }
    }

    private fun attachVideo(videoTrack: VideoTrack) {
        videoTrack.addRenderer(findViewById<SurfaceViewRenderer>(R.id.renderer))
        findViewById<View>(R.id.progress).visibility = View.GONE
    }
}

See the basic sample app for the full implementation.

Audio modes

By default, the audio is configured for two-way communications.

If you are building a livestreaming or media playback focus app, you can use the preset MediaAudioType when creating the Room object for better audio quality.

val room = LiveKit.create(
    appContext = application,
    overrides = LiveKitOverrides(
        audioOptions = AudioOptions(
            audioOutputType = AudioType.MediaAudioType()
        )
    )
)

Note: audio routing becomes automatically handled by the system and cannot be manually controlled.

For more control over the specific audio attributes and modes, a CustomAudioType can be passed instead.

@FlowObservable

Properties marked with @FlowObservable can be accessed as a Kotlin Flow to observe changes directly:

coroutineScope.launch {
    room::activeSpeakers.flow.collectLatest { speakersList ->
        /*...*/
    }
}

Sample App

Note: If you wish to run the sample apps directly from this repo, please consult the Dev Environment instructions.

We have a basic quickstart sample app here, showing how to connect to a room, publish your device's audio/video, and display the video of one remote participant.

There are two more full featured video conferencing sample apps:

They both use the CallViewModel , which handles the Room connection and exposes the data needed for a basic video conferencing app.

The respective ParticipantItem class in each app is responsible for the displaying of each participant's UI.

Dev Environment

To develop the Android SDK or running the sample app directly from this repo, you'll need:

  • Clone the repo to your computer
  • Ensure the protocol submodule repo is initialized and updated
git clone https://github.com/livekit/client-sdk-android.git
cd client-sdk-android
git submodule update --init

For those developing on Macs with Apple silicon (e.g. M1, M2, etc.), please add below to $HOME/.gradle/gradle.properties

protoc_platform=osx-x86_64

Optional (Dev convenience)

  1. Download webrtc sources from https://webrtc.googlesource.com/src
  2. Add sources to Android Studio by pointing at the webrtc/sdk/android folder.


LiveKit Ecosystem
Realtime SDKsReact Components · Browser · Swift Components · iOS/macOS/visionOS · Android · Flutter · React Native · Rust · Node.js · Python · Unity (web) · Unity (beta)
Server APIsNode.js · Golang · Ruby · Java/Kotlin · Python · Rust · PHP (community)
Agents FrameworksPython · Playground
ServicesLiveKit server · Egress · Ingress · SIP
ResourcesDocs · Example apps · Cloud · Self-hosting · CLI

client-sdk-android's People

Contributors

antonito avatar cloudwebrtc avatar davidliu avatar davidzhao avatar dsa avatar dshkil avatar frostbyte73 avatar jfilo-ebay avatar jossephus avatar lukasio avatar newjins-papa avatar ocupe avatar tidoemanuele avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

client-sdk-android's Issues

IllegalArgumentException: Receiver not registered

Describe the bug
We detected the following crash in production, through our crash reporting system. Unfortunately we don't have repro steps.

Fatal Exception: java.lang.IllegalArgumentException: Receiver not registered: s8.b@9017346
       at android.app.LoadedApk.forgetReceiverDispatcher(LoadedApk.java:1523)
       at android.app.ContextImpl.unregisterReceiver(ContextImpl.java:1712)
       at android.content.ContextWrapper.unregisterReceiver(ContextWrapper.java:733)
       at com.twilio.audioswitch.wired.WiredHeadsetReceiver.stop(WiredHeadsetReceiver.kt:45)
       at com.twilio.audioswitch.AudioSwitch.closeListeners(AudioSwitch.kt:362)
       at com.twilio.audioswitch.AudioSwitch.stop(AudioSwitch.kt:180)
       at io.livekit.android.audio.AudioSwitchHandler.stop(AudioSwitchHandler.kt:37)
       at io.livekit.android.room.Room$state$2.invoke(Room.kt:86)
       at io.livekit.android.room.Room$state$2.invoke(Room.kt:82)
       at io.livekit.android.util.MutableStateFlowDelegate.setValue(FlowDelegate.kt:90)
       at io.livekit.android.room.Room.c0(Room.kt:7)
       at io.livekit.android.room.Room.handleDisconnect(Room.kt:448)
       at io.livekit.android.room.Room.onEngineDisconnected(Room.kt:695)
       at io.livekit.android.room.RTCEngine.onLeave(RTCEngine.kt:691)
       at io.livekit.android.room.SignalClient.handleSignalResponseImpl(SignalClient.kt:514)
       at io.livekit.android.room.SignalClient.access$sendRequestImpl(SignalClient.kt:36)
       at io.livekit.android.room.SignalClient$onReadyForResponses$1$1.emit(SignalClient.kt:167)
       at io.livekit.android.room.SignalClient$onReadyForResponses$1$1.emit(SignalClient.kt:165)
       at kotlinx.coroutines.flow.SharedFlowImpl.collect$suspendImpl(SharedFlow.kt:383)
       at kotlinx.coroutines.flow.SharedFlowImpl$collect$1.invokeSuspend(SharedFlow.kt:12)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
       at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
       at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
       at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
       at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:749)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)

Device Info:

  • Device: Motorola, Samsung, Xiaomi, LGE, Others
  • OS: Android 7 to Android 12
  • LiveKit SDK version: io.livekit:livekit-android:1.1.0

Fatal Exception: kotlin.UninitializedPropertyAccessException: publisher has not been initialized yet

Describe the bug
We detected the following crash in production, through our crash reporting system. Unfortunately we don't have repro steps.

Fatal Exception: kotlin.UninitializedPropertyAccessException: publisher has not been initialized yet.
       at io.livekit.android.room.RTCEngine.getPublisher$livekit_android_sdk_release(RTCEngine.kt:96)
       at io.livekit.android.room.RTCEngine.onTrickle(RTCEngine.kt:634)
       at io.livekit.android.room.SignalClient.handleSignalResponseImpl(SignalClient.kt:499)
       at io.livekit.android.room.SignalClient.access$sendRequestImpl(SignalClient.kt:36)
       at io.livekit.android.room.SignalClient$onReadyForResponses$1$1.emit(SignalClient.kt:167)
       at io.livekit.android.room.SignalClient$onReadyForResponses$1$1.emit(SignalClient.kt:165)
       at kotlinx.coroutines.flow.SharedFlowImpl.collect$suspendImpl(SharedFlow.kt:383)
       at kotlinx.coroutines.flow.SharedFlowImpl$collect$1.invokeSuspend(SharedFlow.kt:12)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
       at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
       at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
       at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
       at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:749)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)

Device Info:

  • Device: Samsung, Motorola, Xiaomi, LGE, Others
  • OS: Android 7 to Android 12
  • LiveKit SDK version: io.livekit:livekit-android:1.1.0

Build is broken

Steps to reproduce

  1. git clone [email protected]:livekit/client-sdk-android.git
  2. open project in Android Studio
  3. sync project with gradle files
  4. build sample-app

Found issues

Still results in Task :livekit-android-sdk:compileDebugKotlin FAILED due to various unresolved references.

The other participant failed.

@davidliu

The signaling of both participant is online, but only one party can mediaTrack published successfully. Sometimes it's just audio, no video. This scene cannot be reproduced because it is an production environment. This happens to about 40% of users. We didn't found any of the failed user mediaTrack event logs on Likit-Server. I don't know if it's #77 causes.

[client-sdk-android:v0.9.1]
[livekit-server:v0.15.7]

The following log is what happens to most users,

2022-04-29T16:08:07.776+0800	INFO	livekit	service/rtcservice.go:211	new client WS connected	{"room": "random_newl_2_1651219685941", "participant": "13762851", "connID": "13762851", "roomID": "RM_AdtJtYuQ7Jfh"}
2022-04-29T16:08:07.777+0800	INFO	livekit	rtc/room.go:227	new participant joined	{"room": "random_newl_2_1651219685941", "roomID": "RM_AdtJtYuQ7Jfh", "pID": "PA_Z7KL57X5siTJ", "participant": "13762851", "protocol": 6, "options": {"AutoSubscribe":true}}

2022-04-29T16:08:08.867+0800	INFO	livekit	service/rtcservice.go:211	new client WS connected	{"room": "random_newl_2_1651219685941", "participant": "15174375", "connID": "15174375", "roomID": "RM_AdtJtYuQ7Jfh"}
2022-04-29T16:08:08.867+0800	INFO	livekit	rtc/room.go:227	new participant joined	{"room": "random_newl_2_1651219685941", "roomID": "RM_AdtJtYuQ7Jfh", "pID": "PA_hGm84x7iamw3", "participant": "15174375", "protocol": 6, "options": {"AutoSubscribe":true}}

2022-04-29T16:08:13.419+0800	INFO	livekit	buffer/buffer.go:170	REMB not supported, RTCP feedback will not be generated	{"room": "random_newl_2_1651219685941", "roomID": "RM_AdtJtYuQ7Jfh", "participant": "15174375", "pID": "PA_hGm84x7iamw3", "trackID": "TR_VCrPZQGR9tJVyS", "layer": 0}
2022-04-29T16:08:13.419+0800	INFO	livekit	rtc/participant.go:989	mediaTrack published	{"room": "random_newl_2_1651219685941", "roomID": "RM_AdtJtYuQ7Jfh", "participant": "15174375", "pID": "PA_hGm84x7iamw3", "kind": "video", "trackID": "TR_VCrPZQGR9tJVyS", "rid": "", "SSRC": 3942531100}
2022-04-29T16:08:13.596+0800	INFO	livekit	rtc/participant.go:989	mediaTrack published	{"room": "random_newl_2_1651219685941", "roomID": "RM_AdtJtYuQ7Jfh", "participant": "15174375", "pID": "PA_hGm84x7iamw3", "kind": "audio", "trackID": "TR_AM2AaJmKYCXd3m", "rid": "", "SSRC": 2664125092}

2022-04-29T16:08:23.493+0800	INFO	livekit	rtc/signalhandler.go:77	client leaving room	{"room": "random_newl_2_1651219685941", "roomID": "RM_AdtJtYuQ7Jfh", "participant": "13762851", "pID": "PA_Z7KL57X5siTJ"}
2022-04-29T16:08:23.493+0800	INFO	livekit	rtc/participant.go:595	closing participant	{"room": "random_newl_2_1651219685941", "roomID": "RM_AdtJtYuQ7Jfh", "participant": "13762851", "pID": "PA_Z7KL57X5siTJ", "sendLeave": true}

2022-04-29T16:08:23.493+0800	INFO	livekit	sfu/downtrack.go:559	close down track	{"room": "random_newl_2_1651219685941", "roomID": "RM_AdtJtYuQ7Jfh", "participant": "13762851", "pID": "PA_Z7KL57X5siTJ", "trackID": "TR_VCrPZQGR9tJVyS", "peerID": "PA_Z7KL57X5siTJ", "trackID": "TR_VCrPZQGR9tJVyS", "flushBlankFrame": true}
2022-04-29T16:08:23.493+0800	INFO	livekit	sfu/downtrack.go:559	close down track	{"room": "random_newl_2_1651219685941", "roomID": "RM_AdtJtYuQ7Jfh", "participant": "13762851", "pID": "PA_Z7KL57X5siTJ", "trackID": "TR_AM2AaJmKYCXd3m", "peerID": "PA_Z7KL57X5siTJ", "trackID": "TR_AM2AaJmKYCXd3m", "flushBlankFrame": true}
2022-04-29T16:08:23.493+0800	INFO	livekit	service/rtcservice.go:230	source closed connection	{"room": "random_newl_2_1651219685941", "participant": "13762851", "connID": "13762851"}
2022-04-29T16:08:23.493+0800	INFO	livekit	rtc/room.go:336	closing participant for removal	{"room": "random_newl_2_1651219685941", "roomID": "RM_AdtJtYuQ7Jfh", "pID": "PA_Z7KL57X5siTJ", "participant": "13762851"}
2022-04-29T16:08:23.493+0800	INFO	livekit	service/rtcservice.go:257	exit ws read loop for closed connection	{"room": "random_newl_2_1651219685941", "participant": "13762851", "connID": "13762851"}
2022-04-29T16:08:23.493+0800	INFO	livekit	service/rtcservice.go:191	server closing WS connection	{"room": "random_newl_2_1651219685941", "participant": "13762851", "connID": "13762851"}

2022-04-29T16:08:23.865+0800	INFO	livekit	rtc/signalhandler.go:77	client leaving room	{"room": "random_newl_2_1651219685941", "roomID": "RM_AdtJtYuQ7Jfh", "participant": "15174375", "pID": "PA_hGm84x7iamw3"}
2022-04-29T16:08:23.865+0800	INFO	livekit	rtc/participant.go:595	closing participant	{"room": "random_newl_2_1651219685941", "roomID": "RM_AdtJtYuQ7Jfh", "participant": "15174375", "pID": "PA_hGm84x7iamw3", "sendLeave": true}
2022-04-29T16:08:23.865+0800	INFO	livekit	service/rtcservice.go:257	exit ws read loop for closed connection	{"room": "random_newl_2_1651219685941", "participant": "15174375", "connID": "15174375"}
2022-04-29T16:08:23.865+0800	INFO	livekit	service/rtcservice.go:191	server closing WS connection	{"room": "random_newl_2_1651219685941", "participant": "15174375", "connID": "15174375"}
2022-04-29T16:08:23.865+0800	INFO	livekit	service/rtcservice.go:243	error writing to websocket	{"room": "random_newl_2_1651219685941", "participant": "15174375", "error": "websocket: close sent"}
2022-04-29T16:08:23.865+0800	INFO	livekit	rtc/room.go:336	closing participant for removal	{"room": "random_newl_2_1651219685941", "roomID": "RM_AdtJtYuQ7Jfh", "pID": "PA_hGm84x7iamw3", "participant": "15174375"}
2022-04-29T16:08:43.997+0800	INFO	livekit	rtc/room.go:489	closing room	{"room": "random_newl_2_1651219685941", "roomID": "RM_AdtJtYuQ7Jfh"}
2022-04-29T16:08:43.997+0800	INFO	livekit	service/roommanager.go:86	deleting room state	{"room": "random_newl_2_1651219685941"}

Unable to run sample app

While running the build I am getting this error "Unresolved reference: livekit" in livekit-android-sdk module. Its not able to import classes in livekit. What's the fix or workaround so that I can setup and run sample app

Media connections too slow.

Media connections are established 5 seconds more with livekit server. This means that with livekit server the average time between a customer calling the subscription operation and the video being actually played on their device, it could average around 5 seconds. With mediasoup it averages 0.25 seconds.

Android Client Version: 0.9.0-SNAPSHOT
Server Version: v0.15.4

room.metadata null

Hi I need to access the room.metadata but it is always null.
Also in the room events collect is never fired the RoomMetadataChanged

room.events.collect {
when (it) {
is RoomEvent.RoomMetadataChanged -> {
Timber.v { "metadata: ${it.newMetadata}" }
}
}
}

Duplicate class in modules jetified-protobuf-java-3.15.1 and jetified-protobuf-javalite-3.17.2

Hi

I got the error as bellow after integrated this client SDK.
Is there any way to solve this error?

Thank you.

Duplicate class com.google.protobuf.AbstractMessageLite found in modules jetified-protobuf-java-3.15.1 (com.google.protobuf:protobuf-java:3.15.1) and jetified-protobuf-javalite-3.17.2 (com.google.protobuf:protobuf-javalite:3.17.2)
Duplicate class com.google.protobuf.AbstractMessageLite$Builder found in modules jetified-protobuf-java-3.15.1 (com.google.protobuf:protobuf-java:3.15.1) and jetified-protobuf-javalite-3.17.2 (com.google.protobuf:protobuf-javalite:3.17.2)
Duplicate class com.google.protobuf.AbstractMessageLite$Builder$LimitedInputStream found in modules jetified-protobuf-java-3.15.1 (com.google.protobuf:protobuf-java:3.15.1) and jetified-protobuf-javalite-3.17.2 (com.google.protobuf:protobuf-javalite:3.17.2)
Duplicate class com.google.protobuf.AbstractMessageLite$InternalOneOfEnum found in modules jetified-protobuf-java-3.15.1 (com.google.protobuf:protobuf-java:3.15.1) and jetified-protobuf-javalite-3.17.2 (com.google.protobuf:protobuf-javalite:3.17.2)
Duplicate class com.google.protobuf.AbstractParser found in modules jetified-protobuf-java-3.15.1 (com.google.protobuf:protobuf-java:3.15.1) and jetified-protobuf-javalite-3.17.2 (com.google.protobuf:protobuf-javalite:3.17.2)
...

Android Studio Arctic Fox | 2020.3.1 Patch 3

app/build.gradle

dependencies {
    implementation 'io.livekit:livekit-android:0.8.0'
}

settings.gradle

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        maven { url 'https://jitpack.io' }
        jcenter() // Warning: this repository is going to shut down soon
    }
}
rootProject.name = "Livekit"
include ':app'

Crash upon calling room.disconnect multiple times

java.lang.IllegalArgumentException: NetworkCallback was already unregistered
        at com.android.internal.util.Preconditions.checkArgument(Preconditions.java:47)
        at android.net.ConnectivityManager.unregisterNetworkCallback(ConnectivityManager.java:3388)
        at io.livekit.android.room.Room.handleDisconnect(Room.kt:256)
        at io.livekit.android.room.Room.onDisconnect(Room.kt:416)
        at io.livekit.android.room.RTCEngine.onLeave(RTCEngine.kt:520)
        at io.livekit.android.room.SignalClient.handleSignalResponseImpl(SignalClient.kt:409)
        at io.livekit.android.room.SignalClient.access$handleSignalResponseImpl(SignalClient.kt:37)
        at io.livekit.android.room.SignalClient$onReady$1$invokeSuspend$$inlined$collect$1.emit(Collect.kt:136)
        at kotlinx.coroutines.flow.SharedFlowImpl.collect(SharedFlow.kt:351)
        at kotlinx.coroutines.flow.SharedFlowImpl$collect$1.invokeSuspend(Unknown Source:15)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)

Why must use Android Studio Arctic Fox Beta?

I'm try to use the repo on Android Studio 4.2.2, but report Unresolved reference: livekit...

e: PublisherTransportObserver.kt: (4, 8): Unresolved reference: livekit
e: PublisherTransportObserver.kt: (16, 57): Unresolved reference: LivekitRtc

sample-app: the speaking participant has no UI feedback

Describe the bug
The sample-app-compose demo already support UI feedback for the speaking participant but this funcionality is still missed in the sample-app

To Reproduce
Steps to reproduce the behavior:

  1. Connect a room with a valid token
  2. give the mic permission
  3. Start talking
  4. Check that there is no visual feedback to the speaking participant

Expected behavior
When a participant is speaking should have a visual feedback that identify him as a participant that is speaking

Device Info:

  • Device: Xiaomi Redmi Note 9 Pro
  • OS: Android 11
  • LiveKit SDK version: 1.1.1

Failed to enable camera on device with only a back camera

  • When trying to start the video using the helper setCameraEnabled(true) on a device with only a back camera the call fails with the following error:
java.lang.NullPointerException
        at io.livekit.android.room.track.LocalVideoTrack$Companion.createCameraCapturer(LocalVideoTrack.kt:234)
        at io.livekit.android.room.track.LocalVideoTrack$Companion.createVideoCapturer(LocalVideoTrack.kt:187)
        at io.livekit.android.room.track.LocalVideoTrack$Companion.createTrack$livekit_android_sdk_release(LocalVideoTrack.kt:165)
        at io.livekit.android.room.participant.LocalParticipant.createVideoTrack(LocalParticipant.kt:105)
        at io.livekit.android.room.participant.LocalParticipant.createVideoTrack$default(LocalParticipant.kt:101)
        at io.livekit.android.room.participant.LocalParticipant.setTrackEnabled(LocalParticipant.kt:177)
        at io.livekit.android.room.participant.LocalParticipant.setTrackEnabled$default(LocalParticipant.kt:164)
        at io.livekit.android.room.participant.LocalParticipant.setCameraEnabled(LocalParticipant.kt:145)
        at enterprises.vital.android.app.callv2.CallService$startCall$1.invokeSuspend(CallService.kt:155)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:39)
        at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)

Crash when connect peer to peer

I use version 0.9.1 and i have crash log when connect:

Fatal Exception: java.lang.NullPointerException
subscriber.peerConnection.localDescription must not be null.

io.livekit.android.room.RTCEngine.sendSyncState (RTCEngine.kt:705)
io.livekit.android.room.Room.sendSyncState (Room.kt:408)
io.livekit.android.room.Room.onSignalConnected (Room.kt:629)
io.livekit.android.room.RTCEngine$reconnect$job$1.invokeSuspend (RTCEngine.kt:364)
kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith (ContinuationImpl.kt:33)
kotlinx.coroutines.DispatchedTask.run (DispatchedTask.kt:106)
kotlinx.coroutines.internal.LimitedDispatcher.run (LimitedDispatcher.kt:42)
kotlinx.coroutines.scheduling.TaskImpl.run (Tasks.kt:95)
kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely (CoroutineScheduler.kt:570)
kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask (CoroutineScheduler.kt:749)
kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker (CoroutineScheduler.kt:677)
kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run (CoroutineScheduler.kt:664)

Please check my issue.
Thanks team

Use immutables for flows

State flows won't refire for internal changes within objects. Need to create immutable versions for flows.

SIGSEGV when leaving the the room

Reported by Matthew Brown in Slack:

I'm currently experiencing a SIGSEGV exception when leaving a video call on Android (both in our application which uses the LiveKit Android SDK, and the sample application you provide in the repo). We're using the latest 0.8.1 release, but this problem has existed in prior versions as well I believe.
This particular (or very similar) exception has been mentioned here before, but in the context of Flutter, and when connecting to a room (as opposed to disconnecting from one): https://livekit-users.slack.com/archives/C01KZ61HZRR/p1634861475005100?thread_ts=1634511225.150100&cid=C01KZ61HZRR
The crash is not reliably reproducible, and it happens maybe 1/5 times when disconnecting from a room, seemingly randomly. I've attached some error-level logging output (that was generated by the sample application) which includes the backtrace for the SIGSEGV (with a few preceding log statements in case they are relevant).

Server version: v0.15.3

Logs: livekit_sigsegv.txt

Unmuting after reconnection does not work

If LiveKit reconnection happens while I'm muted, then after successful reconnection I have to unmute/mute/unmute myself to get my audio stream working (the first unmute does nothing).

This is reproducible in the sample app.

Repro steps:

  • Connect 2 clients on 2 different devices (device-1 and device-2) to the same room
  • Test that audio sent from device-1 is heard on device-2
  • Mute local participant on device-1
  • Put device-1 in airplane mode
  • Turn off airplane mode on device-1
  • Unmute local participant on device-1: audio is not heard on device-2. NOK
    then:
  • Mute and unmute local participant on device-1: audio is heard on device-2

End call crash (v1.1.4)

Describe the bug

On version, 1.1.4 try to end the call with the calling room.disconnect(), the crash is happens

Create room in ViewModel

    val audioHandler = AudioSwitchHandler(app)
    val room = LiveKit.create(
        appContext = app,
        options = RoomOptions(adaptiveStream = true, dynacast = true),
        overrides = LiveKitOverrides(
            audioHandler = audioHandler
        )
    )
  1. Start a call
  2. Waiting until UI is loaded
  3. End a call
 fun endCall(){
        viewModelScope.launch {

            val sessionId = getSessionCode() ?: return@launch
            val endSessionResponse = conferenceManager.stopLiveKitConference(sessionId)

            if (!endSessionResponse.success) return@launch

            disconnect()
        }
    }
    
       fun disconnect() {
        if (room.state != Room.State.DISCONNECTED) {
            room.disconnect()
        }
        state = CallState.IDLE
    }

When I call stopLiveKitConference our server deletes the room and sends me a response of server call, after that I call the room.disconnect() and a crash happens.
But when I call delay like 2000 before of room.dissconnect(), and all works normally without the crash.

Expected behavior
Call must end

Device Info:

  • Device: [Google Pixel 2]

  • OS: [Android 11]

  • LiveKit SDK version: [1.1.4]

    kotlin.UninitializedPropertyAccessException: publisher has not been initialized yet.
    at io.livekit.android.room.RTCEngine.getPublisher$livekit_android_sdk_release(RTCEngine.kt:98)
    at io.livekit.android.room.participant.LocalParticipant.unpublishTrack(LocalParticipant.kt:413)
    at io.livekit.android.room.participant.LocalParticipant.unpublishTrack$default(LocalParticipant.kt:402)
    at io.livekit.android.room.participant.LocalParticipant.cleanup(LocalParticipant.kt:566)
    at io.livekit.android.room.Room.cleanupRoom(Room.kt:446)
    at io.livekit.android.room.Room.handleDisconnect(Room.kt:465)
    at io.livekit.android.room.Room.disconnect(Room.kt:248)
    at -------------LiveKitCallViewModel.disconnect(LiveKitCallViewModel.kt:321)

Flip camera error

Describe the bug
When flipping the camera using exactly same code as in the sample

fun flipCamera() {
val videoTrack = room.localParticipant.getTrackPublication(Track.Source.CAMERA)
?.track as? LocalVideoTrack
?: return
val newOptions = when (videoTrack.options.position) {
CameraPosition.FRONT -> LocalVideoTrackOptions(position = CameraPosition.BACK)
CameraPosition.BACK -> LocalVideoTrackOptions(position = CameraPosition.FRONT)
else -> LocalVideoTrackOptions()
}
videoTrack.restartTrack(newOptions)
}
, the device camera is crashing and is unusable, even by other apps, until full device reboot.

To Reproduce
Steps to reproduce the behavior:

  1. Flip camera few times (usually 2 to 5 times)

Expected behavior
Flipping the camera should not crash the camera, nor retain a lock on it, preventing other apps to use it.

Device Info:

  • Device: Samsung S10e
  • OS: Android 12
  • LiveKit SDK version: [e.g. 1.1.3]

Additional context
Cannot reproduce on emulator using Android 12. It's probably hardware specific, but it should at least fail gracefully? Here are the logs:

2022-09-20 15:05:31.448 11886-13713/com.nabla.sdk.playground.dev I/CameraManagerGlobal: Camera 1 facing CAMERA_FACING_FRONT state now CAMERA_STATE_OPEN for client com.nabla.sdk.playground.dev API Level 2
2022-09-20 15:05:31.496 11886-13713/com.nabla.sdk.playground.dev I/CameraManagerGlobal: Camera 1 facing CAMERA_FACING_FRONT state now CAMERA_STATE_ACTIVE for client com.nabla.sdk.playground.dev API Level 2
2022-09-20 15:05:31.547 11886-11904/com.nabla.sdk.playground.dev I/CameraManagerGlobal: Camera 0 facing CAMERA_FACING_BACK state now CAMERA_STATE_IDLE for client com.nabla.sdk.playground.dev API Level 2
2022-09-20 15:05:31.626 11886-13713/com.nabla.sdk.playground.dev I/CameraManagerGlobal: Camera 0 facing CAMERA_FACING_BACK state now CAMERA_STATE_CLOSED for client com.nabla.sdk.playground.dev API Level 2
2022-09-20 15:05:31.627 11886-11908/com.nabla.sdk.playground.dev W/.playground.de: Long monitor contention with owner VideoCaptureThread (29105) at void android.hardware.camera2.impl.CameraDeviceImpl.close()(CameraDeviceImpl.java:1400) waiters=0 in void android.hardware.camera2.impl.CameraDeviceImpl$CameraDeviceCallbacks.onResultReceived(android.hardware.camera2.impl.CameraMetadataNative, android.hardware.camera2.impl.CaptureResultExtras, android.hardware.camera2.impl.PhysicalCaptureResultInfo[]) for 204ms
2022-09-20 15:05:32.457 11886-29218/com.nabla.sdk.playground.dev I/MediaCodec: setCodecState state(0), called in 6
2022-09-20 15:05:33.218 11886-29193/com.nabla.sdk.playground.dev I/MediaCodec: setCodecState state(0), called in 6
2022-09-20 15:05:33.305 11886-29206/com.nabla.sdk.playground.dev I/MediaCodec: setCodecState state(0), called in 6
2022-09-20 15:05:35.219 11886-29262/com.nabla.sdk.playground.dev E/CameraCaptureSession: Session 0: Exception while stopping repeating: 
    android.hardware.camera2.CameraAccessException: CAMERA_ERROR (3): The camera device has encountered a serious error
        at android.hardware.camera2.impl.CameraDeviceImpl.checkIfCameraClosedOrInError(CameraDeviceImpl.java:2378)
        at android.hardware.camera2.impl.CameraDeviceImpl.stopRepeating(CameraDeviceImpl.java:1305)
        at android.hardware.camera2.impl.CameraCaptureSessionImpl.close(CameraCaptureSessionImpl.java:579)
        at org.webrtc.Camera2Session.stopInternal(Camera2Session.java:384)
        at org.webrtc.Camera2Session.reportError(Camera2Session.java:405)
        at org.webrtc.Camera2Session.access$600(Camera2Session.java:31)
        at org.webrtc.Camera2Session$CameraStateCallback.onError(Camera2Session.java:110)
        at android.hardware.camera2.impl.CameraDeviceImpl.notifyError(CameraDeviceImpl.java:1776)
        at android.hardware.camera2.impl.CameraDeviceImpl.$r8$lambda$KBQCqQRdhVVn7uHI9Xdha6OqnsU(Unknown Source:0)
        at android.hardware.camera2.impl.CameraDeviceImpl$$ExternalSyntheticLambda0.accept(Unknown Source:8)
        at com.android.internal.util.function.pooled.PooledLambdaImpl.doInvoke(PooledLambdaImpl.java:281)
        at com.android.internal.util.function.pooled.PooledLambdaImpl.invoke(PooledLambdaImpl.java:204)
        at com.android.internal.util.function.pooled.OmniFunction.run(OmniFunction.java:97)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loopOnce(Looper.java:226)
        at android.os.Looper.loop(Looper.java:313)
        at android.os.HandlerThread.run(HandlerThread.java:67)

I can produce more detailed logs if needed. Thanks!

Inconsistent echo behavior on certain android devices

Reported in Slack community.

I’m playing a lot with RoomOptions.audioTrackCaptureDefaults flags and with LiveKitOverrides.javaAudioDeviceModuleCustomizer (to set UseHardwareAcousticEchoCanceler and UseHardwareNoiseSuppressor). Sometimes I find combination that seems to solve the problem, but the flags configurations end up being completely different on every device I try. On some other devices I don’t find a working configuration at all.

Examples

  • Samsung S8 (with Android 9): this one generates echo for all the other participants in the room if the audioTrackCaptureDefaults are true, but it doesn’t if they are false
  • pixel 2 we need to enable hardware cancellation not to get echoes & audio artifacts (by setting UseHardwareAcousticEchoCanceler to true in the audio module)

`RoomEvent.Reconnected` never received

After switching from WiFi to 4G the livekit client successfully recovers as I receive a RoomEvent.Reconnecting followed by the video stream coming back on track after few ms of being frozen.

Though, I never receive RoomEvent.Reconnected so I had to rely on RoomEvent.TrackPublished happening after a reconnection to consider the reconnection as successful.

All received events during a reconnection:

10:31:53.644 New event in room: Reconnecting
10:31:54.257 New event in room: TrackUnpublished
10:31:54.257 New event in room: TrackUnpublished
10:31:58.011 New event in room: TrackPublished
10:31:58.064 New event in room: TrackPublished
10:31:58.455 New event in room: ConnectionQualityChanged

Verbose livekit logs starting from reconnecting state:

PublisherTransportObserver: onIceConnection new state: CHECKING
PublisherTransportObserver: onConnection new state: CONNECTING
RTCEngine: received ice candidate from peer
SubscriberTransportObserver: onIceCandidate
SignalClient: sending request: # livekit.LivekitRtc$SignalRequest@d816c463
trickle {.. some json ..}
PublisherTransportObserver: onIceCandidate
SignalClient: sending request: # livekit.LivekitRtc$SignalRequest@77d15186
trickle {.. some json ..}
PublisherTransportObserver: onIceCandidate
SignalClient: sending request: # livekit.LivekitRtc$SignalRequest@77d15186
trickle {.. some json ..}

PublisherTransportObserver: onConnection new state: CONNECTED
PublisherTransportObserver: onIceConnection new state: CONNECTED
RTCEngine$reconnect$job: publisher reconnected to ICE
SubscriberTransportObserver: onConnectionChange new state: CONNECTED
RTCEngine$configure$connectionStateListener: onIceConnection new state: CONNECTED
RTCEngine: primary ICE connected
SubscriberTransportObserver: onIceConnection new state: CONNECTED
RTCEngine$reconnect$job: reconnected to ICE
SignalClient: sending request: # livekit.LivekitRtc$SignalRequest@f27316f0
add_track {.. some json ..}
SignalClient: response: # livekit.LivekitRtc$SignalResponse@73ed16fc
track_published {.. some json ..}
RTCEngine: local track published 2f15daa6-0c03-4785-a0e1-4c5aabe67c17
LocalParticipant: using video encoding: VideoEncoding(maxBitrate=2000000, maxFps=30)

IllegalArgumentException: Receiver not registered: com.twilio.audioswitch.wired.WiredHeadsetReceiver

Describe the bug
We got the following crash:

2022-08-16 08:49:04.973 10854-15268/? E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-2
    Process: com.jaumo, PID: 10854
    java.lang.IllegalArgumentException: Receiver not registered: com.twilio.audioswitch.wired.WiredHeadsetReceiver@a51e4e8
        at android.app.LoadedApk.forgetReceiverDispatcher(LoadedApk.java:1439)
        at android.app.ContextImpl.unregisterReceiver(ContextImpl.java:1652)
        at android.content.ContextWrapper.unregisterReceiver(ContextWrapper.java:726)
        at com.twilio.audioswitch.wired.WiredHeadsetReceiver.stop(WiredHeadsetReceiver.kt:45)
        at com.twilio.audioswitch.AudioSwitch.closeListeners(AudioSwitch.kt:362)
        at com.twilio.audioswitch.AudioSwitch.stop(AudioSwitch.kt:180)
        at io.livekit.android.audio.AudioSwitchHandler.stop(AudioSwitchHandler.kt:37)
        at io.livekit.android.room.Room$state$2.invoke(Room.kt:86)
        at io.livekit.android.room.Room$state$2.invoke(Room.kt:82)
        at io.livekit.android.util.MutableStateFlowDelegate.setValue(FlowDelegate.kt:90)
        at io.livekit.android.room.Room.setState(Room.kt:82)
        at io.livekit.android.room.Room.handleDisconnect(Room.kt:448)
        at io.livekit.android.room.Room.onEngineDisconnected(Room.kt:695)
        at io.livekit.android.room.RTCEngine.onLeave(RTCEngine.kt:691)
        at io.livekit.android.room.SignalClient.handleSignalResponseImpl(SignalClient.kt:514)
        at io.livekit.android.room.SignalClient.access$handleSignalResponseImpl(SignalClient.kt:36)
        at io.livekit.android.room.SignalClient$onReadyForResponses$1$1.emit(SignalClient.kt:167)
        at io.livekit.android.room.SignalClient$onReadyForResponses$1$1.emit(SignalClient.kt:165)
        at kotlinx.coroutines.flow.SharedFlowImpl.collect$suspendImpl(SharedFlow.kt:383)
        at kotlinx.coroutines.flow.SharedFlowImpl$collect$1.invokeSuspend(Unknown Source:15)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
        at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:749)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
    	Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@d8e94c1, Dispatchers.IO]

To Reproduce
Unfortunately we don't have repro steps

Device Info:

  • Device: Xiaomi Mi 10
  • OS: Android 12
  • LiveKit SDK version: 1.1.1

Support custom frame processing

Intension

Currently the camera access and capturing is handled within the LiveKit SDK.
For AR applications which use ARCore and render some 3D objects into the camera image the camera is accessed by ARCore itself. In order to allow such applications to use LiveKit for an audio and video call the SDK need to provide an option to configure which image frames should be used and sent to WebRTC.

Solution

One possible solution for this is to allow a custom VideoCapturer in the LocalVideoTrack. This VideoCapturer can then be implemented by the application using the LiveKit SDK to define how to retrieve the image. E.g. using PixelCopy to grab the view a surface.
I'm fully open for other ideas and suggestions.

Video Not Rendering Created new app using Readme

2022-07-26 13:03:28.237 17201-17370/com.example.livekit W/AudioCapabilities: Unsupported mime audio/x-ima
2022-07-26 13:03:28.242 17201-17370/com.example.livekit W/AudioCapabilities: Unsupported mime audio/mpeg-L1
2022-07-26 13:03:28.243 17201-17370/com.example.livekit W/AudioCapabilities: Unsupported mime audio/mpeg-L2
2022-07-26 13:03:28.244 17201-17370/com.example.livekit W/AudioCapabilities: Unsupported mime audio/x-ms-wma
2022-07-26 13:03:28.295 17201-17370/com.example.livekit W/VideoCapabilities: Unsupported mime video/wvc1
2022-07-26 13:03:28.353 17201-17370/com.example.livekit W/VideoCapabilities: Unsupported mime video/mp43
2022-07-26 13:03:28.355 17201-17370/com.example.livekit W/VideoCapabilities: Unrecognized profile/level 1/32 for video/mp4v-es
2022-07-26 13:03:28.355 17201-17370/com.example.livekit W/VideoCapabilities: Unrecognized profile/level 32768/2 for video/mp4v-es
2022-07-26 13:03:28.355 17201-17370/com.example.livekit W/VideoCapabilities: Unrecognized profile/level 32768/64 for video/mp4v-es
2022-07-26 13:03:28.357 17201-17370/com.example.livekit W/VideoCapabilities: Unsupported mime video/wvc1
2022-07-26 13:03:28.361 17201-17370/com.example.livekit W/VideoCapabilities: Unsupported mime video/x-ms-wmv7
2022-07-26 13:03:28.362 17201-17370/com.example.livekit W/VideoCapabilities: Unsupported mime video/x-ms-wmv8

Crash when flipping camera too fast

Describe the bug
When flipping the cameras too fast on Pixel 6 Pro I end up with a crash

To Reproduce
Steps to reproduce the behavior:

  1. Flip camera super quick like 10 times

Expected behavior
No crash

Device Info:

  • Device: Pixel 6 Pro
  • OS: Android 13
  • LiveKit SDK version: io.livekit:livekit-android:1.1.1

Additional context

Crash log:

FATAL EXCEPTION: main
                                                                                                    Process: xxx, PID: 28272
                                                                                                    kotlin.NotImplementedError: An operation is not implemented.
                                                                                                    	at io.livekit.android.room.track.LocalVideoTrack$Companion.createTrack$livekit_android_sdk_release(LocalVideoTrack.kt:169)
                                                                                                    	at io.livekit.android.room.track.LocalVideoTrack.restartTrack(LocalVideoTrack.kt:81)
                                                                                                    	at xxx$onFlipCameraClicked$1.invokeSuspend(VideoCallViewModel.kt:229)
                                                                                                    	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
                                                                                                    	at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:234)
                                                                                                    	at kotlinx.coroutines.DispatchedTaskKt.resumeUnconfined(DispatchedTask.kt:190)
                                                                                                    	at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:161)
                                                                                                    	at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:397)
                                                                                                    	at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:431)
                                                                                                    	at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:420)
                                                                                                    	at kotlinx.coroutines.CancellableContinuationImpl.resumeWith(CancellableContinuationImpl.kt:328)
                                                                                                    	at xxx$awaitAllCamerasAvailable$2$callback$1.onCameraAvailable(VideoCallViewModel.kt:248)
                                                                                                    	at android.hardware.camera2.CameraManager$CameraManagerGlobal$6.run(CameraManager.java:2093)
                                                                                                    	at android.os.Handler.handleCallback(Handler.java:942)
                                                                                                    	at android.os.Handler.dispatchMessage(Handler.java:99)
                                                                                                    	at android.os.Looper.loopOnce(Looper.java:201)
                                                                                                    	at android.os.Looper.loop(Looper.java:288)
                                                                                                    	at android.app.ActivityThread.main(ActivityThread.java:7898)
                                                                                                    	at java.lang.reflect.Method.invoke(Native Method)
                                                                                                    	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
                                                                                                    	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
                                                                                                    	Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@fbd1c9c, Dispatchers.Main.immediate]

Crash happens here:

val (capturer, newOptions) = createVideoCapturer(context, options) ?: TODO()

lateinit property localParticipant has not been initialized

Hi,

I integrated this SDK (0.8.0) and copy the code snippet from the README.md.
But it always crash when my device handle the connection for the first time.
The code snippet works well after the crash, it won't crash again in short time (maybe 3 mins).

This crash happens to my devices:
Samsung A30s, Android 10
Samsung A70, Android 9
Pixel 3a, Android 11
Vivo Y20, Android 10
Vivo Y15, Android 9

Here is the stack trace:

kotlin.UninitializedPropertyAccessException: lateinit property localParticipant has not been initialized
        at io.livekit.android.room.Room.getLocalParticipant(Room.kt:120)
        at io.livekit.android.room.Room.getParticipant(Room.kt:195)
        at io.livekit.android.room.Room.onConnectionQuality(Room.kt:455)
        at io.livekit.android.room.RTCEngine.onConnectionQuality(RTCEngine.kt:537)
        at io.livekit.android.room.SignalClient.handleSignalResponseImpl(SignalClient.kt:439)
        at io.livekit.android.room.SignalClient.access$handleSignalResponseImpl(SignalClient.kt:36)
        at io.livekit.android.room.SignalClient$onReady$1$invokeSuspend$$inlined$collect$1.emit(Collect.kt:136)
        at kotlinx.coroutines.flow.SharedFlowImpl.collect$suspendImpl(SharedFlow.kt:372)
        at kotlinx.coroutines.flow.SharedFlowImpl.collect(Unknown Source:0)
        at io.livekit.android.room.SignalClient$onReady$1.invokeSuspend(SignalClient.kt:505)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
        at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:39)
        at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)

I also record my screen:
https://imgur.com/a/9CGuLHB

In this video, I called

launch {
        room = LiveKit.connect(...)
}

in onCreate() after I clicked the button, then I got a crash.
But after relaunch my app, it didn't trigger the crash again.

Resuming camera video track after use in other apps fails to resume

User reports:

if I’m in a call with the camera active on the android side, when the activity pauses I’m calling the localParticipant.setCameraEnabled(false) so that the camera is released and it can be used by other apps, I’m re-enabling it on resume, that’s all well and good, I can send my call activity to the background and then bring it back to the foreground and the video feed resumes fine, the problem I’m having is that if during the time my activity is in the background I capture a picture with the camera app, then when I return to the call activity the video feed doesn’t resume, I just get a black screen instead of the camera feed

and by the way, this is not the case if I unpublish the track when pausing, if I unpublish the track and then upon resuming I create and publish it again, the video resumes fine

Unresolved reference: livekit

e: /home/livekit-pract/client-sdk-android/livekit-android-sdk/src/main/java/io/livekit/android/room/PublisherTransportObserver.kt: (4, 8): Unresolved reference: livekit

I'm getting this error

Can i use simulcast with VP8 Codec

I tried to use SimulcastVideoEncoderFactoryWrapper class and i saw that codec i used is H264 so can you help me to change codec to VP8.

Video not place correct in full window

To Reproduce
I integrated version 0.9.1 and even version 1.1.1 of Android SDK

Connecting two android phones A to B, audio and video flows only from one side to another.

However, I see video from the remote side coming into the small window when I scroll sideways in the small window.

It seems like the audio triggers when it starts from the side where the video is supposed to come. So then the video shows in the large main window on the recipient side.

The audio also doesn’t start about 20% of the time.

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Device Info:

  • Device: [e.g. Google Pixel 4]
  • OS: [e.g. Android 12]
  • LiveKit SDK version: 0.9.1 , 1.1.1

Additional context
Add any other context about the problem here.

Calling room.disconnect(), kotlin.UninitializedPropertyAccessException: localParticipant has not been initialized yet.

Hi, here is my source code:
override fun onDestroy() {
super.onDestroy()
binding.speakerVideoView.release()
viewModel.mutableRoom.value?.disconnect()
// Undo audio mode changes
val audioManager = getSystemService(AUDIO_SERVICE) as AudioManager
with(audioManager) {
isSpeakerphoneOn = previousSpeakerphoneOn
isMicrophoneMute = previousMicrophoneMute
abandonAudioFocus(focusChangeListener)
mode = AudioManager.MODE_NORMAL
}
}
override fun onParticipantDisconnected(room: Room, participant: RemoteParticipant) {
super.onParticipantDisconnected(room, participant)
viewModelScope.launch {
TimeUtils.getInstance().stopNewTimer()
ToastUtils.showShort("call ended")
finish()
}
}
Here is my crash log:
2022-06-02 10:23:21.701 12556-12556/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.fy.chatsdk, PID: 12556
kotlin.UninitializedPropertyAccessException: localParticipant has not been initialized yet.
at io.video.android.room.Room.getLocalParticipant(Room.kt:132)
at com.micmd.chat.data.module.call.CallViewModel$participants$lambda-3$$inlined$map$1$2.emit(Emitters.kt:224)
at kotlinx.coroutines.flow.StateFlowImpl.collect(StateFlow.kt:398)
at kotlinx.coroutines.flow.StateFlowImpl$collect$1.invokeSuspend(Unknown Source:15)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at android.os.Handler.handleCallback(Handler.java:808)
at android.os.Handler.dispatchMessage(Handler.java:101)
at android.os.Looper.loop(Looper.java:166)
at android.app.ActivityThread.main(ActivityThread.java:7529)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
2022-06-02 10:23:21.703 12556-12556/? E/CustomActivityOnCrash: App has crashed, executing CustomActivityOnCrash's UncaughtExceptionHandler
kotlin.UninitializedPropertyAccessException: localParticipant has not been initialized yet.
at io.video.android.room.Room.getLocalParticipant(Room.kt:132)
at com.micmd.chat.data.module.call.CallViewModel$participants$lambda-3$$inlined$map$1$2.emit(Emitters.kt:224)
at kotlinx.coroutines.flow.StateFlowImpl.collect(StateFlow.kt:398)
at kotlinx.coroutines.flow.StateFlowImpl$collect$1.invokeSuspend(Unknown Source:15)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at android.os.Handler.handleCallback(Handler.java:808)
at android.os.Handler.dispatchMessage(Handler.java:101)
at android.os.Looper.loop(Looper.java:166)
at android.app.ActivityThread.main(ActivityThread.java:7529)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@a6f6323, Dispatchers.Main.immediate]

can you help me how should i solve it thanks

Spam enabling and disabling camera let LiveKit client out of control

Describe the bug
When spamming localParticipant.setCameraEnabled(!localParticipant.isCameraEnabled()), let say because it is tied to an UI button, LiveKit client could go out of control and start enabling and disabling camera by itself with no action, until the call is terminated.

To Reproduce
Steps to reproduce the behavior:

  1. Spam localParticipant.setCameraEnabled(!localParticipant.isCameraEnabled()) on an ongoing call.
  2. At some point the client will start switching camera by itself until the termination of the call.

Expected behavior
It should stop switching camera at some point, without user action.

Video
https://user-images.githubusercontent.com/7696995/191460485-596f0b84-3ad7-4f1c-9389-b5ad500b8c53.mp4

Device Info:

  • Device: Nexus 6P, S10e, Emulators
  • OS: [Android 8, 12]
  • LiveKit SDK version: [1.1.3]

Additional context
In the log, the track is being muted and unmuted in a very fast pace:

2022-09-21 10:50:53.884 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackUnmuted
2022-09-21 10:50:53.887 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackMuted
2022-09-21 10:50:53.898 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackUnmuted
2022-09-21 10:50:53.902 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackMuted
2022-09-21 10:50:53.904 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackUnmuted
2022-09-21 10:50:53.913 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackMuted
2022-09-21 10:50:53.956 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackUnmuted
2022-09-21 10:50:53.960 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackMuted
2022-09-21 10:50:53.970 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackUnmuted
2022-09-21 10:50:53.972 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackMuted
2022-09-21 10:50:53.973 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackUnmuted
2022-09-21 10:50:54.026 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackMuted
2022-09-21 10:50:54.047 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackUnmuted
2022-09-21 10:50:54.056 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackMuted
2022-09-21 10:50:54.056 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackUnmuted
2022-09-21 10:50:54.060 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackMuted
2022-09-21 10:50:54.062 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackUnmuted
2022-09-21 10:50:54.073 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackMuted
2022-09-21 10:50:54.091 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackUnmuted
2022-09-21 10:50:54.103 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackMuted
2022-09-21 10:50:54.119 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackUnmuted
2022-09-21 10:50:54.128 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackMuted
2022-09-21 10:50:54.130 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackUnmuted
2022-09-21 10:50:54.142 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackMuted
2022-09-21 10:50:54.160 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackUnmuted
2022-09-21 10:50:54.172 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackMuted
2022-09-21 10:50:54.187 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackUnmuted
2022-09-21 10:50:54.194 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackMuted
2022-09-21 10:50:54.204 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackUnmuted
2022-09-21 10:50:54.222 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackMuted
2022-09-21 10:50:54.231 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackUnmuted
2022-09-21 10:50:54.242 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackMuted
2022-09-21 10:50:54.256 11241-11241/com.nabla.sdk.playground.dev I/ViewRootImpl@d127fd3[VideoCallActivity]: ViewPostIme pointer 0
2022-09-21 10:50:54.265 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackUnmuted
2022-09-21 10:50:54.269 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackMuted
2022-09-21 10:50:54.278 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackUnmuted
2022-09-21 10:50:54.292 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackMuted
2022-09-21 10:50:54.302 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackUnmuted
2022-09-21 10:50:54.308 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackMuted
2022-09-21 10:50:54.308 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackUnmuted
2022-09-21 10:50:54.311 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackMuted
2022-09-21 10:50:54.325 11241-11241/com.nabla.sdk.playground.dev D/Nabla-SDK-VideoCall: new event in room 0501eaf8-9e8a-4240-a8c8-01a066485312: TrackUnmuted

Using the camera await trick from #145 when switching off the camera fix the issue.

sometimes no participant video displayed for the new joining participant

publication source: on certain devices the CAMERA track is returned as UNKNOWN
Step to reproduce:

  • connect two devices (tested with huawei p40 lite and lenovo tab M10 HD) in the same room with camera ON and log the value of publication.source before the condition:
if (publication.source == Track.Source.CAMERA) {
      setupVideoIfNeeded(track, viewBinding)
} 

the latest device that join the call has no video participant track in the recyclerView

Failed to transform 'C:\Users\Administrator\.gradle\caches\modules-2\files-2.1\org.bouncycastle\bcprov-jdk15on\1.68\46a080368d38b428d237a59458f9bc915222894d\bcprov-jdk15on-1.68.jar' using Jetifier. Reason: IllegalArgumentException, message: Unsupported class file major version 59. (Run with --stacktrace for more details.)

Android Studio:4.0.2
jdk:1.8
gradle:7.0.2

When I generate release apk of sample app,the console send mistake "Failed to transform 'C:\Users\Administrator.gradle\caches\modules-2\files-2.1\org.bouncycastle\bcprov-jdk15on\1.68\46a080368d38b428d237a59458f9bc915222894d\bcprov-jdk15on-1.68.jar' using Jetifier. Reason: IllegalArgumentException, message: Unsupported class file major version 59. (Run with --stacktrace for more details.)"

and how to solve this,Thank you

kotlin.UninitializedPropertyAccessException: subscriber has not been initialized yet.

Reported on slack:
https://livekit-users.slack.com/archives/C01KVTJH6BX/p1657183108142129

Fatal Exception: kotlin.UninitializedPropertyAccessException: subscriber has not been initialized yet.
       at io.livekit.android.room.RTCEngine.getSubscriber$livekit_android_sdk_release(RTCEngine.kt:99)
       at io.livekit.android.room.RTCEngine$reconnect$job$1.invokeSuspend(RTCEngine.kt:385)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
       at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
       at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
       at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
       at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:749)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)

AudioRecord: start() status -38

I run the sample app is normal in Android device,but in my project is not work. Only the video stream works, the audio stream cannot be published, always show red mute icon , I got a log message is AudioRecord: start() status -38, do you known what this means?


 //本地音频配置
            val localAudioTrackOptions = LocalAudioTrackOptions(
                noiseSuppression = true,//噪音处理
                echoCancellation = true,//回声消除
                autoGainControl = true,//自动增益
                highPassFilter = true,//高音过滤
                typingNoiseDetection = true,//打字噪音检测
            )
//            发布音频配置
            val audioTrackPublishOptions = AudioTrackPublishDefaults(
                dtx = true,
            )

            //本地视频配置
            val videoTrackCaptureDefaults = LocalVideoTrackOptions(
                position = CameraPosition.BACK,//默认的前后摄像头
            )
            //发布视频配置
            val videoTrackPublishDefaults = VideoTrackPublishDefaults(
                videoEncoding = VideoPreset169.QHD.encoding,//发布给对方的清晰度
            )

            Log.e("livekit","开始连接rtc")
            room = LiveKit.connect(
                context,
                url,
                token,
                roomOptions = RoomOptions(
                    adaptiveStream = true,
                    dynacast = true,
                    audioTrackCaptureDefaults = localAudioTrackOptions,
                    videoTrackCaptureDefaults = videoTrackCaptureDefaults,
//                    audioTrackPublishDefaults = audioTrackPublishOptions,
//                    videoTrackPublishDefaults = videoTrackPublishDefaults,
                ),
            )

            // Create and publish audio/video tracks
            val localParticipant = room!!.localParticipant
            localParticipant.setMicrophoneEnabled(true)
            localParticipant.setCameraEnabled(true)

Problem with calls via cellular network

There are two Android devices:

  • A – connected via Wi-Fi
  • B – connected via cellular network (4G)

A calls B via LiveKit. After both users enter the room, A does not see the video track from B, and B does not see the video track from A. After a while, the video from B becomes visible on side A, but with very poor quality. At the same time, messages about the status of the microphone and camera are transmitted between the devices. Next, an error occurs on the B side:

E/SignalClient: websocket failure: null java.io.EOFException at 
    okio.RealBufferedSource.require(RealBufferedSource.kt:199) at 
    okio.RealBufferedSource.readByte(RealBufferedSource.kt:209) at 
    okhttp3.internal.ws.WebSocketReader.readHeader(WebSocketReader.kt:119) at 
    okhttp3.internal.ws.WebSocketReader.processNextFrame(WebSocketReader.kt:102) at 
    okhttp3.internal.ws.RealWebSocket.loopReader(RealWebSocket.kt:293) at 
    okhttp3.internal.ws.RealWebSocket$connect$1.onResponse(RealWebSocket.kt:195) at 
    okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519) at 
    java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at 
    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at 
    java.lang.Thread.run(Thread.java:764)

After the error occurs, there are several attempts to restore the connection, after which the web socket is closed. During all attempts, the participants do not see each other.

The same problem occurs when A and B both call from a cellular network (regardless of the mobile operator used).

The problem was discovered in an application made based on a demo “sample-app” provided in the repository. For both demo applications, the problem persists.

The problem occurred on many Android devices with API level 28 and higher from different manufacturers. On iOS devices in the same situation, the problem is not observed.

The attached files contain logs recorded when connecting devices via LiveKit.

Note: RoomEvent.ActiveSpeakersChanged, RoomEvent.ConnectionQualityChanged and ParticipantEvent.SpeakingChanged were not logged.

Logs from device A (call initiator, connected via Wi-Fi):
livekit_log_full_user_a.txt - full logs
livekit_log_events_user_a.txt - room and participant events and websocket errors

Logs from device B (call receiver, connected via cellular network):
livekit_log_full_user_b.txt - full logs
livekit_log_events_user_b.txt - room and participant events and websocket errors

client-sdk-android version: 1.1.0 (the problem was also in 1.0.1 and 1.0.2-SHAPSHOT)
livekit version: 1.1.0

Room connection code:

val room = LiveKit.create(
    appContext = application,
    options = RoomOptions(
        adaptiveStream = true,
        dynacast = true,
    ),
)    
room.connect(
     Constants.Url.LIVEKIT,
     token,
)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.