Siapkan aplikasi untuk PiP

Dalam tag aktivitas di file AndroidManifest.xml, lakukan hal berikut:

  1. Tambahkan supportsPictureInPicture dan setel ke true untuk menyatakan bahwa Anda akan menggunakan picture-in-picture (PiP) di aplikasi.
  2. Tambahkan configChanges dan tetapkan ke orientation|screenLayout|screenSize|smallestScreenSize untuk menentukan bahwa aktivitas Anda menangani perubahan konfigurasi tata letak. Dengan cara ini, aktivitas Anda tidak diluncurkan kembali saat perubahan tata letak terjadi selama transisi mode PiP.
<activity
    android:name=".SnippetsActivity"
    android:exported="true"
    android:supportsPictureInPicture="true"
    android:configChanges="orientation|screenLayout|screenSize|smallestScreenSize"
    android:theme="@style/Theme.Snippets">

Dalam kode Compose Anda, lakukan hal berikut:

  1. Tambahkan ekstensi ini di Context. Anda akan menggunakan ekstensi ini beberapa kali di seluruh panduan untuk mengakses aktivitas.
    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")
    }

Menambahkan PiP saat keluar dari aplikasi untuk perangkat sebelum Android 12

Untuk menambahkan PiP untuk pra-Android 12, gunakan addOnUserLeaveHintProvider. Ikuti langkah-langkah berikut untuk menambahkan PiP untuk perangkat sebelum Android 12:

  1. Tambahkan gerbang versi sehingga kode ini hanya dapat diakses di versi O hingga R.
  2. Gunakan DisposableEffect dengan Context sebagai kunci.
  3. Di dalam DisposableEffect, tentukan perilaku saat onUserLeaveHintProvider dipicu menggunakan lambda. Di lambda, panggil enterPictureInPictureMode() pada findActivity() dan teruskan PictureInPictureParams.Builder().build().
  4. Tambahkan addOnUserLeaveHintListener menggunakan findActivity() dan teruskan lambda.
  5. Di onDispose, tambahkan removeOnUserLeaveHintListener menggunakan findActivity() dan teruskan 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")
}

Menambahkan PiP di aplikasi cuti untuk perangkat yang menjalankan Android 12 dan yang lebih baru

Setelah Android 12, PictureInPictureParams.Builder ditambahkan melalui pengubah yang diteruskan ke pemutar video aplikasi.

  1. Buat modifier dan panggil onGloballyPositioned di dalamnya. Koordinat tata letak akan digunakan pada langkah selanjutnya.
  2. Buat variabel untuk PictureInPictureParams.Builder().
  3. Tambahkan pernyataan if untuk memeriksa apakah SDK adalah S atau yang lebih baru. Jika ya, tambahkan setAutoEnterEnabled ke builder dan tetapkan ke true untuk memasuki mode PiP saat menggeser. Hal ini memberikan animasi yang lebih lancar daripada melalui enterPictureInPictureMode.
  4. Gunakan findActivity() untuk menelepon setPictureInPictureParams(). Panggil build() di builder dan teruskan.

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)

Gunakan setAspectRatio untuk menetapkan rasio aspek jendela PiP

Untuk menyetel rasio aspek jendela PiP, Anda dapat memilih rasio aspek tertentu atau menggunakan lebar dan tinggi ukuran video pemutar. Jika Anda menggunakan pemutar media3, periksa apakah pemutar tidak null dan ukuran video pemutar tidak sama dengan VideoSize.UNKNOWN sebelum menyetel rasio aspek.

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)

Jika Anda menggunakan pemutar kustom, tetapkan rasio aspek pada tinggi dan lebar pemutar menggunakan sintaksis khusus untuk pemutar Anda. Perlu diketahui bahwa jika pemutar Anda mengubah ukuran selama inisialisasi, jika berada di luar batas valid rasio aspek yang dapat digunakan, aplikasi Anda akan error. Anda mungkin perlu menambahkan pemeriksaan di sekitar waktu rasio aspek dapat dihitung, mirip dengan cara yang dilakukan untuk pemutar media3.