Uygulamanızı PiP için ayarlama

AndroidManifest.xml dosyanızın etkinlik etiketinde aşağıdakileri yapın:

  1. Uygulamanızda pencere içinde pencere (PIP) özelliğini kullanacağınızı beyan etmek için supportsPictureInPicture öğesini ekleyip true olarak ayarlayın.
  2. Etkinliğinizin düzen yapılandırması değişikliklerini işlediğini belirtmek için configChanges öğesini ekleyin ve orientation|screenLayout|screenSize|smallestScreenSize olarak ayarlayın. Bu sayede, PiP modu geçişleri sırasında düzen değişiklikleri olduğunda etkinliğiniz yeniden başlatılmaz.
<activity
    android:name=".SnippetsActivity"
    android:exported="true"
    android:supportsPictureInPicture="true"
    android:configChanges="orientation|screenLayout|screenSize|smallestScreenSize"
    android:theme="@style/Theme.Snippets">

Compose kodunuzda aşağıdakileri yapın:

  1. Bu uzantıyı Context cihazına ekleyin. Etkinliğe erişmek için rehber boyunca bu uzantıyı birkaç kez kullanacaksınız.
    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")
    }

Android 12 öncesi sürümler için uygulamadan çıkarken PiP ekleme

Android 12'den önceki sürümlerde PiP eklemek için addOnUserLeaveHintProvider kullanın. Android 12 öncesi sürümlerde PiP eklemek için aşağıdaki adımları uygulayın:

  1. Bu koda yalnızca O ile R arasındaki sürümlerde erişilebilmesi için bir sürüm geçidi ekleyin.
  2. Anahtar olarak Context ile bir DisposableEffect kullanın.
  3. DisposableEffect içinde, lambda kullanarak onUserLeaveHintProvider tetiklendiğinde gerçekleşecek davranışı tanımlayın. Lambda'da, findActivity() üzerinde enterPictureInPictureMode() işlevini çağırın ve PictureInPictureParams.Builder().build() değerini iletin.
  4. findActivity() kullanarak addOnUserLeaveHintListener ekleyin ve lambda'yı iletin.
  5. onDispose içinde, findActivity() kullanarak removeOnUserLeaveHintListener ekleyin ve lambda'yı iletin.

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")
}

Android 12'den sonraki sürümler için uygulamadan çıkıldığında PiP ekleme

Android 12'den sonra PictureInPictureParams.Builder, uygulamanın video oynatıcısına iletilen bir değiştirici aracılığıyla eklenir.

  1. Bir modifier oluşturun ve bu nesnede onGloballyPositioned yöntemini çağırın. Düzen koordinatları sonraki bir adımda kullanılacaktır.
  2. PictureInPictureParams.Builder() için bir değişken oluşturun.
  3. SDK'nın S veya daha yeni bir sürüm olup olmadığını kontrol etmek için bir if ifadesi ekleyin. Bu durumda, oluşturucuya setAutoEnterEnabled ekleyin ve kaydırma hareketiyle PiP moduna girmek için bu özelliği true olarak ayarlayın. Bu, enterPictureInPictureMode üzerinden geçiş yapmaktan daha akıcı bir animasyon sağlar.
  4. setPictureInPictureParams() numarasını aramak için findActivity() numarasını kullanın. builder üzerinden build() numarasını arayın ve telefonu verin.

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)

PiP penceresinin en boy oranını ayarlamak için setAspectRatio kullanın.

Pencere içinde pencere penceresinin en boy oranını ayarlamak için belirli bir en boy oranı seçebilir veya oynatıcının video boyutunun genişliğini ve yüksekliğini kullanabilirsiniz. Media3 oynatıcı kullanıyorsanız en boy oranını ayarlamadan önce oynatıcının boş olmadığından ve oynatıcının video boyutunun VideoSize.UNKNOWN değerine eşit olmadığından emin olun.

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)

Özel bir oynatıcı kullanıyorsanız oynatıcınızın söz dizimini kullanarak oynatıcının yüksekliği ve genişliği için en boy oranını ayarlayın. Oynatıcınız başlatma sırasında yeniden boyutlandırılırsa ve en boy oranının geçerli sınırlarının dışına çıkarsa uygulamanız kilitlenir. Media3 oynatıcıda olduğu gibi, en boy oranının ne zaman hesaplanabileceğiyle ilgili kontroller eklemeniz gerekebilir.