Konfigurowanie funkcji PIP w aplikacji

W tagu aktywności pliku AndroidManifest.xml wykonaj te czynności:

  1. Dodaj supportsPictureInPicture i ustaw wartość true, aby zadeklarować, że będziesz używać funkcji obraz w obrazie w swojej aplikacji.
  2. Dodaj configChanges i ustaw wartość orientation|screenLayout|screenSize|smallestScreenSize, aby określić, że aktywność obsługuje zmiany konfiguracji układu. Dzięki temu aktywność nie uruchamia się ponownie, gdy podczas przechodzenia do trybu obrazu w obrazie zmienia się układ.
<activity
    android:name=".SnippetsActivity"
    android:exported="true"
    android:supportsPictureInPicture="true"
    android:configChanges="orientation|screenLayout|screenSize|smallestScreenSize"
    android:theme="@style/Theme.Snippets">

W kodzie Compose wykonaj te czynności:

  1. Dodaj to rozszerzenie na urządzeniu Context. Będziesz używać tego rozszerzenia wielokrotnie w trakcie korzystania z przewodnika, aby uzyskać dostęp do aktywności.
    internal fun Context.findActivity(): ComponentActivity {
        var context = this
        while (context is ContextWrapper) {
            if (context is ComponentActivity) return context
            context = context.baseContext
        }
        throw IllegalStateException("Picture in picture should be called in the context of an Activity")
    }

Dodawanie obrazu w obrazie po opuszczeniu aplikacji na urządzeniach z Androidem w wersji starszej niż 12

Aby dodać obraz w obrazie na urządzeniach z Androidem w wersji starszej niż 12, użyj addOnUserLeaveHintProvider. Aby dodać obraz w obrazie na urządzeniach z Androidem w wersji starszej niż 12, wykonaj te czynności:

  1. Dodaj bramkę wersji, aby ten kod był dostępny tylko w wersjach od O do R.
  2. Użyj DisposableEffect z kluczem Context.
  3. Wewnątrz DisposableEffect zdefiniuj zachowanie, gdy onUserLeaveHintProvider jest wywoływany za pomocą funkcji lambda. W wyrażeniu lambda wywołaj enterPictureInPictureMode() na findActivity() i przekaż PictureInPictureParams.Builder().build().
  4. Dodaj addOnUserLeaveHintListener za pomocą findActivity() i przekaż lambdę.
  5. W pliku onDispose dodaj removeOnUserLeaveHintListener za pomocą findActivity() i przekaż wyrażenie lambda.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
    Build.VERSION.SDK_INT < Build.VERSION_CODES.S
) {
    val context = LocalContext.current
    DisposableEffect(context) {
        val onUserLeaveBehavior = Runnable {
            context.findActivity()
                .enterPictureInPictureMode(PictureInPictureParams.Builder().build())
        }
        context.findActivity().addOnUserLeaveHintListener(
            onUserLeaveBehavior
        )
        onDispose {
            context.findActivity().removeOnUserLeaveHintListener(
                onUserLeaveBehavior
            )
        }
    }
} else {
    Log.i("PiP info", "API does not support PiP")
}

Dodawanie PiP po opuszczeniu aplikacji na urządzeniach z Androidem 12 lub nowszym

W Androidzie 12 i nowszych PictureInPictureParams.Builder jest dodawany za pomocą modyfikatora przekazywanego do odtwarzacza wideo aplikacji.

  1. Utwórz modifier i wywołaj na nim onGloballyPositioned. Współrzędne układu będą używane w późniejszym kroku.
  2. Utwórz zmienną dla PictureInPictureParams.Builder().
  3. Dodaj instrukcję if, aby sprawdzić, czy pakiet SDK jest w wersji S lub nowszej. Jeśli tak, dodaj do kreatora setAutoEnterEnabled i ustaw wartość true, aby po przesunięciu palcem włączyć tryb obrazu w obrazie. Zapewnia to płynniejszą animację niż w przypadku enterPictureInPictureMode.
  4. Użyj numeru findActivity(), aby zadzwonić do: setPictureInPictureParams(). Zadzwoń do: build() na numer builder i przekaż.

val pipModifier = modifier.onGloballyPositioned { layoutCoordinates ->
    val builder = PictureInPictureParams.Builder()

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        builder.setAutoEnterEnabled(true)
    }
    context.findActivity().setPictureInPictureParams(builder.build())
}
VideoPlayer(pipModifier)

Użyj setAspectRatio, aby ustawić format obrazu okna obrazu w obrazie

Aby ustawić format obrazu okna PiP, możesz wybrać konkretny format obrazu lub użyć szerokości i wysokości rozmiaru filmu w odtwarzaczu. Jeśli używasz odtwarzacza media3, przed ustawieniem formatu obrazu sprawdź, czy odtwarzacz nie ma wartości null i czy rozmiar filmu w odtwarzaczu nie jest równy VideoSize.UNKNOWN.

val context = LocalContext.current

val pipModifier = modifier.onGloballyPositioned { layoutCoordinates ->
    val builder = PictureInPictureParams.Builder()
    if (shouldEnterPipMode && player != null && player.videoSize != VideoSize.UNKNOWN) {
        val sourceRect = layoutCoordinates.boundsInWindow().toAndroidRectF().toRect()
        builder.setSourceRectHint(sourceRect)
        builder.setAspectRatio(
            Rational(player.videoSize.width, player.videoSize.height)
        )
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        builder.setAutoEnterEnabled(shouldEnterPipMode)
    }
    context.findActivity().setPictureInPictureParams(builder.build())
}

VideoPlayer(pipModifier)

Jeśli używasz odtwarzacza niestandardowego, ustaw format obrazu na wysokość i szerokość odtwarzacza, używając składni właściwej dla Twojego odtwarzacza. Pamiętaj, że jeśli podczas inicjowania odtwarzacz zmieni rozmiar i wyjdzie poza prawidłowe granice formatu obrazu, aplikacja ulegnie awarii. Może być konieczne dodanie kontroli dotyczących tego, kiedy można obliczyć format obrazu, podobnie jak w przypadku odtwarzacza media3.