Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ import io.getstream.video.android.core.Call
import io.getstream.video.android.core.RealtimeConnection
import io.getstream.video.android.core.call.state.ChooseLayout
import io.getstream.video.android.core.model.PreferredVideoResolution
import io.getstream.video.android.core.pip.PictureInPictureConfiguration
import io.getstream.video.android.core.utils.isEnabled
import io.getstream.video.android.filters.video.BlurredBackgroundVideoFilter
import io.getstream.video.android.filters.video.VirtualBackgroundVideoFilter
Expand Down Expand Up @@ -145,6 +146,7 @@ import kotlinx.coroutines.launch
fun CallScreen(
call: Call,
showDebugOptions: Boolean = false,
pictureInPictureConfiguration: PictureInPictureConfiguration? = null,
onCallDisconnected: () -> Unit = {},
onUserLeaveCall: () -> Unit = {},
) {
Expand Down Expand Up @@ -316,7 +318,8 @@ fun CallScreen(
),
call = call,
layout = layout,
enableInPictureInPicture = true,
pictureInPictureConfiguration = pictureInPictureConfiguration
?: PictureInPictureConfiguration(true),
enableDiagnostics = BuildConfig.DEBUG || StreamBuildFlavorUtil.isDevelopment,
onCallAction = {
when (it) {
Expand Down Expand Up @@ -833,6 +836,29 @@ fun CallScreen(
}
}

@Deprecated(
"Use CallScreen with pictureInPictureConfiguration argument",
ReplaceWith(
"CallScreen(call, showDebugOptions, pictureInPictureConfiguration, onCallDisconnected, onUserLeaveCall)",
),
)
@OptIn(FlowPreview::class)
@Composable
fun CallScreen(
call: Call,
showDebugOptions: Boolean = false,
onCallDisconnected: () -> Unit = {},
onUserLeaveCall: () -> Unit = {},
) {
CallScreen(
call,
showDebugOptions,
PictureInPictureConfiguration(true),
onCallDisconnected,
onUserLeaveCall,
)
}

/**
* Executes the transcription APIs based on the current transcription state and settings.
*
Expand Down
25 changes: 25 additions & 0 deletions stream-video-android-core/api/stream-video-android-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -12227,6 +12227,31 @@ public abstract interface class io/getstream/video/android/core/permission/andro
public abstract fun checkAndroidPermissionsGroup (Landroid/content/Context;Lio/getstream/video/android/core/Call;)Lkotlin/Pair;
}

public final class io/getstream/video/android/core/pip/PictureInPictureConfiguration : android/os/Parcelable {
public static final field CREATOR Landroid/os/Parcelable$Creator;
public fun <init> (ZZ)V
public synthetic fun <init> (ZZILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Z
public final fun component2 ()Z
public final fun copy (ZZ)Lio/getstream/video/android/core/pip/PictureInPictureConfiguration;
public static synthetic fun copy$default (Lio/getstream/video/android/core/pip/PictureInPictureConfiguration;ZZILjava/lang/Object;)Lio/getstream/video/android/core/pip/PictureInPictureConfiguration;
public fun describeContents ()I
public fun equals (Ljava/lang/Object;)Z
public final fun getAutoEnterEnabled ()Z
public final fun getEnable ()Z
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
public fun writeToParcel (Landroid/os/Parcel;I)V
}

public final class io/getstream/video/android/core/pip/PictureInPictureConfiguration$Creator : android/os/Parcelable$Creator {
public fun <init> ()V
public final fun createFromParcel (Landroid/os/Parcel;)Lio/getstream/video/android/core/pip/PictureInPictureConfiguration;
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public final fun newArray (I)[Lio/getstream/video/android/core/pip/PictureInPictureConfiguration;
public synthetic fun newArray (I)[Ljava/lang/Object;
}

public final class io/getstream/video/android/core/socket/ErrorResponse : java/lang/Throwable {
public static final field Companion Lio/getstream/video/android/core/socket/ErrorResponse$Companion;
public fun <init> ()V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ import io.getstream.webrtc.android.ui.VideoTextureViewRenderer
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2014-2024 Stream.io Inc. All rights reserved.
*
* Licensed under the Stream License;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://github.com/GetStream/stream-video-android/blob/main/LICENSE
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.getstream.video.android.core.pip

import android.os.Parcelable
import kotlinx.parcelize.Parcelize

/**
* Configuration for controlling Picture-in-Picture (PiP) behavior within a call UI.
*
* @property enable
* Indicates whether Picture-in-Picture mode should be enabled for this call.
* When `true`, the SDK will handle entering PiP mode automatically when appropriate
* (for example, when the user navigates away from the app during an active call).
*
* @property autoEnterEnabled
* Determines whether to call [android.app.PictureInPictureParams.Builder.setAutoEnterEnabled]
* when configuring the PiP parameters. When `true`, the system automatically enters PiP mode
* when the user presses the home button or performs an equivalent action. Set this to `false`
* if you prefer to manually control when PiP mode should be entered.
*/
@Parcelize
public data class PictureInPictureConfiguration(
val enable: Boolean,
val autoEnterEnabled: Boolean = true,
) : Parcelable
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
public final class io/getstream/video/android/compose/lifecycle/MediaPiPLifecycleKt {
public static final fun MediaPiPLifecycle (Lio/getstream/video/android/core/Call;Lio/getstream/video/android/core/pip/PictureInPictureConfiguration;Landroidx/compose/runtime/Composer;II)V
public static final fun MediaPiPLifecycle (Lio/getstream/video/android/core/Call;ZLandroidx/compose/runtime/Composer;II)V
}

Expand Down Expand Up @@ -447,6 +448,7 @@ public final class io/getstream/video/android/compose/ui/components/audio/AudioR
}

public final class io/getstream/video/android/compose/ui/components/audio/AudioRoomContentKt {
public static final fun AudioRoomContent (Landroidx/compose/ui/Modifier;Lio/getstream/video/android/core/Call;ZLio/getstream/video/android/compose/permission/VideoPermissionsState;Ljava/lang/String;Lkotlin/jvm/functions/Function3;Lio/getstream/video/android/compose/ui/components/audio/AudioRendererStyle;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lio/getstream/video/android/core/pip/PictureInPictureConfiguration;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;III)V
public static final fun AudioRoomContent (Landroidx/compose/ui/Modifier;Lio/getstream/video/android/core/Call;ZLio/getstream/video/android/compose/permission/VideoPermissionsState;Ljava/lang/String;Lkotlin/jvm/functions/Function3;Lio/getstream/video/android/compose/ui/components/audio/AudioRendererStyle;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;ZLkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;III)V
}

Expand Down Expand Up @@ -476,10 +478,12 @@ public final class io/getstream/video/android/compose/ui/components/audio/Compos
public final class io/getstream/video/android/compose/ui/components/audio/ComposableSingletons$AudioRoomContentKt {
public static final field INSTANCE Lio/getstream/video/android/compose/ui/components/audio/ComposableSingletons$AudioRoomContentKt;
public static field lambda-1 Lkotlin/jvm/functions/Function4;
public static field lambda-2 Lkotlin/jvm/functions/Function2;
public static field lambda-2 Lkotlin/jvm/functions/Function4;
public static field lambda-3 Lkotlin/jvm/functions/Function2;
public fun <init> ()V
public final fun getLambda-1$stream_video_android_ui_compose_release ()Lkotlin/jvm/functions/Function4;
public final fun getLambda-2$stream_video_android_ui_compose_release ()Lkotlin/jvm/functions/Function2;
public final fun getLambda-2$stream_video_android_ui_compose_release ()Lkotlin/jvm/functions/Function4;
public final fun getLambda-3$stream_video_android_ui_compose_release ()Lkotlin/jvm/functions/Function2;
}

public final class io/getstream/video/android/compose/ui/components/audio/ComposableSingletons$ParticipantAudioKt {
Expand Down Expand Up @@ -1053,6 +1057,7 @@ public final class io/getstream/video/android/compose/ui/components/call/activec
}

public final class io/getstream/video/android/compose/ui/components/call/activecall/CallContentKt {
public static final fun CallContent (Lio/getstream/video/android/core/Call;Landroidx/compose/ui/Modifier;Lio/getstream/video/android/compose/ui/components/call/renderer/LayoutType;Lio/getstream/video/android/compose/permission/VideoPermissionsState;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Lio/getstream/video/android/compose/ui/components/call/renderer/VideoRendererStyle;Lkotlin/jvm/functions/Function6;Lkotlin/jvm/functions/Function5;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lio/getstream/video/android/core/pip/PictureInPictureConfiguration;Lkotlin/jvm/functions/Function3;ZLkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;III)V
public static final fun CallContent (Lio/getstream/video/android/core/Call;Landroidx/compose/ui/Modifier;Lio/getstream/video/android/compose/ui/components/call/renderer/LayoutType;Lio/getstream/video/android/compose/permission/VideoPermissionsState;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Lio/getstream/video/android/compose/ui/components/call/renderer/VideoRendererStyle;Lkotlin/jvm/functions/Function6;Lkotlin/jvm/functions/Function5;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;ZLkotlin/jvm/functions/Function3;ZLkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;III)V
}

Expand All @@ -1068,18 +1073,26 @@ public final class io/getstream/video/android/compose/ui/components/call/activec
public final class io/getstream/video/android/compose/ui/components/call/activecall/ComposableSingletons$CallContentKt {
public static final field INSTANCE Lio/getstream/video/android/compose/ui/components/call/activecall/ComposableSingletons$CallContentKt;
public static field lambda-1 Lkotlin/jvm/functions/Function6;
public static field lambda-10 Lkotlin/jvm/functions/Function2;
public static field lambda-2 Lkotlin/jvm/functions/Function3;
public static field lambda-3 Lkotlin/jvm/functions/Function3;
public static field lambda-4 Lkotlin/jvm/functions/Function3;
public static field lambda-5 Lkotlin/jvm/functions/Function2;
public static field lambda-6 Lkotlin/jvm/functions/Function2;
public static field lambda-5 Lkotlin/jvm/functions/Function6;
public static field lambda-6 Lkotlin/jvm/functions/Function3;
public static field lambda-7 Lkotlin/jvm/functions/Function3;
public static field lambda-8 Lkotlin/jvm/functions/Function3;
public static field lambda-9 Lkotlin/jvm/functions/Function2;
public fun <init> ()V
public final fun getLambda-1$stream_video_android_ui_compose_release ()Lkotlin/jvm/functions/Function6;
public final fun getLambda-10$stream_video_android_ui_compose_release ()Lkotlin/jvm/functions/Function2;
public final fun getLambda-2$stream_video_android_ui_compose_release ()Lkotlin/jvm/functions/Function3;
public final fun getLambda-3$stream_video_android_ui_compose_release ()Lkotlin/jvm/functions/Function3;
public final fun getLambda-4$stream_video_android_ui_compose_release ()Lkotlin/jvm/functions/Function3;
public final fun getLambda-5$stream_video_android_ui_compose_release ()Lkotlin/jvm/functions/Function2;
public final fun getLambda-6$stream_video_android_ui_compose_release ()Lkotlin/jvm/functions/Function2;
public final fun getLambda-5$stream_video_android_ui_compose_release ()Lkotlin/jvm/functions/Function6;
public final fun getLambda-6$stream_video_android_ui_compose_release ()Lkotlin/jvm/functions/Function3;
public final fun getLambda-7$stream_video_android_ui_compose_release ()Lkotlin/jvm/functions/Function3;
public final fun getLambda-8$stream_video_android_ui_compose_release ()Lkotlin/jvm/functions/Function3;
public final fun getLambda-9$stream_video_android_ui_compose_release ()Lkotlin/jvm/functions/Function2;
}

public final class io/getstream/video/android/compose/ui/components/call/activecall/internal/ComposableSingletons$InviteUsersDialogKt {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import io.getstream.video.android.compose.pip.enterPictureInPicture
import io.getstream.video.android.compose.pip.findActivity
import io.getstream.video.android.compose.pip.isInPictureInPictureMode
import io.getstream.video.android.core.Call
import io.getstream.video.android.core.pip.PictureInPictureConfiguration

/**
* Register a call media lifecycle that controls camera and microphone depending on lifecycles.
Expand All @@ -44,7 +45,8 @@ import io.getstream.video.android.core.Call
@Composable
public fun MediaPiPLifecycle(
call: Call,
enableInPictureInPicture: Boolean = false,
pictureInPictureConfiguration: PictureInPictureConfiguration =
PictureInPictureConfiguration(true),
) {
val context = LocalContext.current
val lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current
Expand All @@ -64,7 +66,7 @@ public fun MediaPiPLifecycle(
override fun onActivityResumed(activity: Activity) {
if (activity == currentActivity) {
val isInPictureInPicture = context.isInPictureInPictureMode
if (!isInPictureInPicture && !enableInPictureInPicture) {
if (!isInPictureInPicture && !pictureInPictureConfiguration.enable) {
call.camera.resume(fromUser = false)
call.microphone.resume(fromUser = false)
}
Expand All @@ -74,13 +76,17 @@ public fun MediaPiPLifecycle(
override fun onActivityPaused(activity: Activity) {
if (activity == currentActivity) {
val isInPictureInPicture = context.isInPictureInPictureMode
if (!isInPictureInPicture && !enableInPictureInPicture) {
if (!isInPictureInPicture && !pictureInPictureConfiguration.enable) {
call.camera.pause(fromUser = false)
call.microphone.pause(fromUser = false)
} else if (!isInPictureInPicture) {
Handler(Looper.getMainLooper()).post {
try {
enterPictureInPicture(context = context, call = call)
enterPictureInPicture(
context = context,
call = call,
pictureInPictureConfiguration,
)
} catch (e: Exception) {
StreamLog.d("MediaPiPLifecycle") { e.stackTraceToString() }
}
Expand All @@ -103,3 +109,15 @@ public fun MediaPiPLifecycle(
}
}
}

@Deprecated(
"Use MediaPiPLifecycle with pictureInPictureConfiguration",
ReplaceWith("MediaPiPLifecycle(call, pictureInPictureConfiguration"),
)
@Composable
public fun MediaPiPLifecycle(
call: Call,
enableInPictureInPicture: Boolean = false,
) {
MediaPiPLifecycle(call, PictureInPictureConfiguration(enableInPictureInPicture))
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,14 @@ import androidx.compose.ui.platform.LocalContext
import androidx.core.app.PictureInPictureModeChangedInfo
import androidx.core.util.Consumer
import io.getstream.video.android.core.Call
import io.getstream.video.android.core.pip.PictureInPictureConfiguration

@Suppress("DEPRECATION")
internal fun enterPictureInPicture(context: Context, call: Call) {
internal fun enterPictureInPicture(
context: Context,
call: Call,
pictureInPictureConfiguration: PictureInPictureConfiguration,
) {
if (context.packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val currentOrientation = context.resources.configuration.orientation
Expand All @@ -52,8 +57,12 @@ internal fun enterPictureInPicture(context: Context, call: Call) {

val params = PictureInPictureParams.Builder()
params.setAspectRatio(aspect).apply {
var defaultAutoEnterEnabled = true
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
defaultAutoEnterEnabled = pictureInPictureConfiguration.autoEnterEnabled
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
setAutoEnterEnabled(true)
setAutoEnterEnabled(defaultAutoEnterEnabled)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
setTitle("Video Player")
Expand Down
Loading