Pencere içinde pencere (PiP) özelliğini kullanarak video ekleme

"Oluştur" yöntemini deneyin
Jetpack Compose, Android için önerilen kullanıcı arayüzü araç setidir. Oluşturma'da pencere içinde pencere özelliğini nasıl destekleyeceğinizi öğrenin.

Android 8.0 (API düzeyi 26) sürümünden itibaren Android, etkinliklerin pencere içinde pencere (PIP) modunda başlatılmasına izin verir. PiP, çoğunlukla video oynatmak için kullanılan özel bir çok pencere modudur. Kullanıcıların uygulamalar arasında geçiş yaparken veya ana ekrandaki içeriklere göz atarken ekranın bir köşesine sabitlenmiş küçük bir pencerede video izlemesine olanak tanır.

PiP, sabitlenmiş video yer paylaşımı penceresini sağlamak için Android 7.0'da kullanıma sunulan çok pencereli API'lerden yararlanır. Uygulamanıza PiP eklemek için PiP'yi destekleyen etkinliklerinizi kaydetmeniz, etkinliğinizi gerektiğinde PiP moduna geçirmeniz ve etkinlik PiP modundayken kullanıcı arayüzü öğelerinin gizlendiğinden ve video oynatmanın devam ettiğinden emin olmanız gerekir.

PiP penceresi, ekranın en üst katmanında, sistem tarafından seçilen bir köşede görünür.

PiP, Android 14 (API düzeyi 34) veya sonraki sürümleri çalıştıran uyumlu Android TV OS cihazlarda da desteklenir. Birçok benzerlik olsa da TV'de PiP kullanırken dikkate alınması gereken başka noktalar da vardır.

Kullanıcılar PiP penceresiyle nasıl etkileşim kurabilir?

Kullanıcılar, PiP penceresini başka bir konuma sürükleyebilir. Android 12'den itibaren kullanıcılar şunları da yapabilir:

  • Tam ekran açma/kapatma düğmesi, kapat düğmesi, ayarlar düğmesi ve uygulamanız tarafından sağlanan özel işlemleri (ör. oynatma kontrolleri) görüntülemek için pencereye tek dokunun.

  • Mevcut PiP boyutu ile maksimum veya minimum PiP boyutu arasında geçiş yapmak için pencereye iki kez dokunun. Örneğin, ekranı kaplayacak şekilde büyütülmüş bir pencereye iki kez dokunduğunuzda pencere simge durumuna küçültülür. Bunun tersi de geçerlidir.

  • Pencereyi sol veya sağ kenara sürükleyerek gizleyin. Pencereyi gizleme modundan çıkarmak için gizlenen pencerenin görünür kısmına dokunun veya pencereyi dışarı sürükleyin.

  • İki parmağınızı yakınlaştırmak veya uzaklaştırmak için kullanarak PiP penceresini yeniden boyutlandırın.

Mevcut etkinliğin PiP moduna ne zaman gireceğini uygulamanız kontrol eder. Aşağıda birkaç örnek verilmiştir:

  • Kullanıcı ana sayfa düğmesine dokunduğunda veya ekranı yukarı kaydırarak ana sayfaya dokunduğunda bir etkinlik PiP moduna girebilir. Kullanıcı aynı anda başka bir etkinlik yürütürken Google Haritalar bu şekilde yol tarifini göstermeye devam eder.

  • Kullanıcı videodan geri dönüp diğer içeriklere göz atarken uygulamanız videoyu PiP moduna geçirebilir.

  • Uygulamanız, kullanıcı bir içeriğin sonunu izlerken videoyu PiP moduna geçirebilir. Ana ekranda, dizinin bir sonraki bölümüyle ilgili tanıtım veya özet bilgileri gösterilir.

  • Uygulamanız, kullanıcıların video izlerken ek içerikleri sıraya eklemelerine olanak tanıyabilir. Video, PiP modunda oynatılmaya devam ederken ana ekranda bir içerik seçme etkinliği gösterilir.

PIP desteğini bildirme

Sistem, varsayılan olarak uygulamalar için PiP'yi otomatik olarak desteklemez. Uygulamanızda PiP'yi desteklemek istiyorsanız android:supportsPictureInPicture değerini true olarak ayarlayarak video etkinliğinizi manifest dosyanıza kaydedin. Ayrıca, PiP modu geçişleri sırasında düzen değişiklikleri olduğunda etkinliğinizin yeniden başlatılmaması için etkinliğinizin düzen yapılandırma değişikliklerini işlemesi gerektiğini de belirtin.

<activity android:name="VideoActivity"
    android:supportsPictureInPicture="true"
    android:configChanges=
        "screenSize|smallestScreenSize|screenLayout|orientation"
    ...

Etkinliğinizi PIP'e geçirme

Android 12'den itibaren setAutoEnterEnabled işaretini true olarak ayarlayarak etkinliğinizi PiP moduna geçirebilirsiniz. Bu ayar sayesinde, bir etkinlik onUserLeaveHint içinde enterPictureInPictureMode() çağrılmasına gerek kalmadan gerektiğinde otomatik olarak PiP moduna geçer. Bu, çok daha sorunsuz geçişler sağlamanın ek avantajını da sunar. Ayrıntılar için Hareketle gezinme sırasında PiP moduna geçişleri daha sorunsuz hale getirme başlıklı makaleyi inceleyin.

Android 11 veya önceki sürümleri hedefliyorsanız bir etkinliğin PiP moduna geçmek için enterPictureInPictureMode() çağrısı yapması gerekir. Örneğin, aşağıdaki kod, kullanıcı uygulamanın kullanıcı arayüzünde özel bir düğmeyi tıkladığında etkinliği PiP moduna geçirir:

Kotlin

override fun onActionClicked(action: Action) {
    if (action.id.toInt() == R.id.lb_control_picture_in_picture) {
        activity?.enterPictureInPictureMode()
        return
    }
}

Java

@Override
public void onActionClicked(Action action) {
    if (action.getId() == R.id.lb_control_picture_in_picture) {
        getActivity().enterPictureInPictureMode();
        return;
    }
    ...
}

Bir etkinliği arka plana taşımak yerine PiP moduna geçiren mantık ekleyebilirsiniz. Örneğin, Google Haritalar uygulamada gezinme sırasında kullanıcı ana sayfa veya son aramalar düğmesine basarsa PIP moduna geçer. onUserLeaveHint() değerini geçersiz kılarak bu destek kaydını yakalayabilirsiniz:

Kotlin

override fun onUserLeaveHint() {
    if (iWantToBeInPipModeNow()) {
        enterPictureInPictureMode()
    }
}

Java

@Override
public void onUserLeaveHint () {
    if (iWantToBeInPipModeNow()) {
        enterPictureInPictureMode();
    }
}

Önerilen: Kullanıcılara kusursuz bir PiP geçiş deneyimi sunun

Android 12'de tam ekran ile PiP pencereleri arasındaki animasyonlu geçişlere önemli görünüm geliştirmeler eklendi. Geçerli tüm değişiklikleri uygulamanızı önemle tavsiye ederiz. Bu değişiklikleri yaptıktan sonra, başka bir işlem yapmanıza gerek kalmadan katlanabilir cihazlar ve tabletler gibi büyük ekranlara otomatik olarak ölçeklendirilir.

Uygulamanız geçerli güncellemeleri içermiyorsa PiP geçişleri çalışmaya devam eder, ancak animasyonlar daha az iyidir. Örneğin, tam ekrandan PiP moduna geçiş, geçiş sırasında PiP penceresinin geçiş tamamlandığında yeniden görünmeden önce kaybolmasına neden olabilir.

Bu değişiklikler aşağıdakileri kapsar.

  • Hareketle gezinme modundan PIP moduna geçişi daha sorunsuz hale getirme
  • PiP moduna girmek ve bu moddan çıkmak için uygun bir sourceRectHint ayarlanıyor
  • Video olmayan içerik için sorunsuz yeniden boyutlandırmayı devre dışı bırakma

Sorunsuz bir geçiş deneyimi sunmak için Android Kotlin PictureInPicture örneğine göz atın.

Hareketle gezinme modundan PIP moduna geçişleri daha sorunsuz hale getirme

Android 12'den itibaren setAutoEnterEnabled işareti, hareketle gezinme özelliğini kullanarak (ör. tam ekrandan ana ekrana yukarı kaydırırken) PiP modunda video içeriğine geçiş için çok daha akıcı bir animasyon sağlar.

Bu değişikliği yapmak için aşağıdaki adımları tamamlayın ve referans için bu örneğe bakın:

  1. PictureInPictureParams.Builder oluşturmak için setAutoEnterEnabled kullanın:

    Kotlin

    setPictureInPictureParams(PictureInPictureParams.Builder()
        .setAspectRatio(aspectRatio)
        .setSourceRectHint(sourceRectHint)
        .setAutoEnterEnabled(true)
        .build())

    Java

    setPictureInPictureParams(new PictureInPictureParams.Builder()
        .setAspectRatio(aspectRatio)
        .setSourceRectHint(sourceRectHint)
        .setAutoEnterEnabled(true)
        .build());
  2. Güncel PictureInPictureParams ile setPictureInPictureParams'ü erkenden arayın. Uygulama, onUserLeaveHint geri çağırma işlevini beklemez (Android 11'de beklediği gibi).

    Örneğin, en boy oranı değiştirilirse ilk oynatma işleminde ve sonraki oynatma işlemlerinde setPictureInPictureParams işlevini çağırabilirsiniz.

  3. setAutoEnterEnabled(false)'ü yalnızca gerektiğinde arayın. Örneğin, mevcut oynatma duraklatılmış durumdaysa muhtemelen PiP'ye girmek istemezsiniz.

PiP moduna girmek ve bu moddan çıkmak için uygun bir sourceRectHint belirleyin

Android 8.0'da PiP'nin kullanıma sunulmasından itibaren setSourceRectHint, etkinliğin pencere içinde pencere moduna geçişten sonra görünen alanını (ör. bir video oynatıcıdaki video görüntüleme sınırları) belirtiyordu.

Android 12'de sistem, hem PiP moduna girerken hem de bu moddan çıkarken çok daha akıcı bir animasyon uygulamak için sourceRectHint kullanır.

PiP moduna girmek ve moddan çıkmak için sourceRectHint'ü doğru şekilde ayarlamak üzere:

  1. sourceRectHint olarak uygun sınırları kullanarak PictureInPictureParams oluşturun. Video oynatıcıya bir düzen değişikliği dinleyicisi de eklemenizi öneririz:

    Kotlin

    val mOnLayoutChangeListener =
    OnLayoutChangeListener { v: View?, oldLeft: Int,
            oldTop: Int, oldRight: Int, oldBottom: Int, newLeft: Int, newTop:
            Int, newRight: Int, newBottom: Int ->
        val sourceRectHint = Rect()
        mYourVideoView.getGlobalVisibleRect(sourceRectHint)
        val builder = PictureInPictureParams.Builder()
            .setSourceRectHint(sourceRectHint)
        setPictureInPictureParams(builder.build())
    }
    
    mYourVideoView.addOnLayoutChangeListener(mOnLayoutChangeListener)

    Java

    private final View.OnLayoutChangeListener mOnLayoutChangeListener =
            (v, oldLeft, oldTop, oldRight, oldBottom, newLeft, newTop, newRight,
            newBottom) -> {
        final Rect sourceRectHint = new Rect();
        mYourVideoView.getGlobalVisibleRect(sourceRectHint);
        final PictureInPictureParams.Builder builder =
            new PictureInPictureParams.Builder()
                .setSourceRectHint(sourceRectHint);
        setPictureInPictureParams(builder.build());
    };
    
    mYourVideoView.addOnLayoutChangeListener(mOnLayoutChangeListener);
  2. Gerekirse sistem çıkış geçişini başlatmadan önce sourceRectHint öğesini güncelleyin. Sistem, PiP modundan çıkmak üzereyken etkinliğin görünüm hiyerarşisi, hedef yapılandırmasına (ör. tam ekran) yerleştirilir. Uygulama, etkinliği algılamak için kök görünümüne veya hedef görünümüne (video oynatıcı görünümü gibi) bir düzen değişikliği işleyici ekleyebilir ve animasyon başlamadan önce sourceRectHint öğesini güncelleyebilir.

    Kotlin

    // Listener is called immediately after the user exits PiP but before animating.
    playerView.addOnLayoutChangeListener { _, left, top, right, bottom,
                        oldLeft, oldTop, oldRight, oldBottom ->
        if (left != oldLeft
            || right != oldRight
            || top != oldTop
            || bottom != oldBottom) {
            // The playerView's bounds changed, update the source hint rect to
            // reflect its new bounds.
            val sourceRectHint = Rect()
            playerView.getGlobalVisibleRect(sourceRectHint)
            setPictureInPictureParams(
                PictureInPictureParams.Builder()
                    .setSourceRectHint(sourceRectHint)
                    .build()
            )
        }
    }

    Java

    // Listener is called right after the user exits PiP but before animating.
    playerView.addOnLayoutChangeListener((v, left, top, right, bottom,
                        oldLeft, oldTop, oldRight, oldBottom) -> {
        if (left != oldLeft
            || right != oldRight
            || top != oldTop
            || bottom != oldBottom) {
            // The playerView's bounds changed, update the source hint rect to
            // reflect its new bounds.
            final Rect sourceRectHint = new Rect();
            playerView.getGlobalVisibleRect(sourceRectHint);
            setPictureInPictureParams(
                new PictureInPictureParams.Builder()
                    .setSourceRectHint(sourceRectHint)
                    .build());
        }
    });

Video olmayan içerik için sorunsuz yeniden boyutlandırmayı devre dışı bırak

Android 12'de, PiP penceresindeki video dışı içerikler yeniden boyutlandırıldığında çok daha yumuşak bir geçiş animasyonu sağlayan setSeamlessResizeEnabled işareti eklendi. Daha önce, PiP penceresindeki video dışı içeriğin boyutunu değiştirmek rahatsız edici görsel kusurlara neden olabiliyordu.

Video olmayan içerik için sorunsuz yeniden boyutlandırmayı devre dışı bırakmak üzere:

Kotlin

setPictureInPictureParams(PictureInPictureParams.Builder()
    .setSeamlessResizeEnabled(false)
    .build())

Java

setPictureInPictureParams(new PictureInPictureParams.Builder()
    .setSeamlessResizeEnabled(false)
    .build());

PiP sırasında kullanıcı arayüzünü işleme

Etkinlik, Pencere İçinde Pencere (PiP) moduna girdiğinde veya bu moddan çıktığında sistem Activity.onPictureInPictureModeChanged() veya Fragment.onPictureInPictureModeChanged() çağrısı yapar.

Android 15'te, PiP moduna girerken daha da sorunsuz bir geçiş sağlayan değişiklikler sunuluyor. Bu, ana kullanıcı arayüzlerinin üzerine yerleştirilmiş kullanıcı arayüzü öğelerine sahip ve PiP'ye geçen uygulamalar için yararlıdır.

Geliştiriciler, yer paylaşımlı kullanıcı arayüzü öğelerinin görünürlüğünü açıp kapatan mantığı tanımlamak için onPictureInPictureModeChanged() geri çağırma yöntemini kullanır. Bu geri çağırma işlevi, PiP'ye girme veya çıkma animasyonu tamamlandığında tetiklenir. PictureInPictureUiState sınıfı, Android 15'ten itibaren yeni bir durum içeriyor.

Bu yeni kullanıcı arayüzü durumunda, Android 15'i hedefleyen uygulamalar, PiP animasyonu başlar başlamaz Activity#onPictureInPictureUiStateChanged() geri çağırma işlevinin isTransitioningToPip() ile çağrıldığını gözlemler. PiP modundayken uygulamayla alakalı olmayan birçok kullanıcı arayüzü öğesi bulunur. Örneğin; öneriler, yakında çıkacak videolar, puanlar ve başlıklar gibi bilgileri içeren görünümler veya düzen. Uygulama PiP moduna girdiğinde bu kullanıcı arayüzü öğelerini gizlemek için onPictureInPictureUiStateChanged() geri arama işlevini kullanın. Uygulama, PiP penceresinden tam ekran moduna geçtiğinde aşağıdaki örneklerde gösterildiği gibi bu öğeleri göstermek için onPictureInPictureModeChanged() geri çağırma işlevini kullanın:

Kotlin

override fun onPictureInPictureUiStateChanged(pipState: PictureInPictureUiState) {
        if (pipState.isTransitioningToPip()) {
          // Hide UI elements.
        }
    }

Java

@Override
public void onPictureInPictureUiStateChanged(PictureInPictureUiState pipState) {
        if (pipState.isTransitioningToPip()) {
          // Hide UI elements.
        }
    }

Kotlin

override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean) {
        if (isInPictureInPictureMode) {
          // Unhide UI elements.
        }
    }

Java

@Override
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
        if (isInPictureInPictureMode) {
          // Unhide UI elements.
        }
    }

Alakasız kullanıcı arayüzü öğelerinin (PIP penceresi için) bu hızlı görünürlük açma/kapatma düğmesi, daha akıcı ve titremeyen bir PiP giriş animasyonu sağlar.

Etkinliğin kullanıcı arayüzü öğelerini yeniden çizmek için bu geri çağırma işlevlerini geçersiz kılın. PiP modunda etkinliğinizin küçük bir pencerede gösterildiğini unutmayın. Uygulama PiP modundayken kullanıcılar uygulamanızın kullanıcı arayüzü öğeleriyle etkileşimde bulunamaz ve küçük kullanıcı arayüzü öğelerinin ayrıntılarını görmek zor olabilir. Minimum kullanıcı arayüzüyle video oynatma etkinlikleri, en iyi kullanıcı deneyimini sağlar.

Uygulamanızın PiP için özel işlemler sağlaması gerekiyorsa bu sayfadaki Denetimler ekleme bölümüne bakın. Etkinliğiniz PiP'ye girmeden önce diğer kullanıcı arayüzü öğelerini kaldırın ve etkinliğiniz tekrar tam ekran olduğunda bunları geri yükleyin.

Kontrol ekle

PiP penceresi, kullanıcı pencerenin menüsünü açtığında (mobil cihazda pencereye dokunarak veya TV uzaktan kumandasından menüyü seçerek) kontrolleri gösterebilir.

Bir uygulamanın etkin bir medya oturumu varsa oynatma, duraklatma, sonraki ve önceki kontroller gösterilir.

Ayrıca, PiP moduna girmeden önce PictureInPictureParams.Builder.setActions() ile PictureInPictureParams derleyerek de özel işlemleri açıkça belirtebilirsiniz. enterPictureInPictureMode(android.app.PictureInPictureParams) veya setPictureInPictureParams(android.app.PictureInPictureParams) kullanarak PiP moduna girdiğinizde parametreleri iletebilirsiniz. Dikkatli olun. getMaxNumPictureInPictureActions()'den fazla ekleme yapmaya çalışırsanız yalnızca maksimum sayıda ekleme yapabilirsiniz.

PiP modundayken video oynatmaya devam etme

Etkinliğiniz PiP'ye geçtiğinde sistem, etkinliği duraklatılmış duruma yerleştirir ve etkinliğin onPause() yöntemini çağırır. Video oynatma duraklatılmamalıdır. PiP moduna geçilirken etkinlik duraklatılırsa video oynatmaya devam edin.

Android 7.0 ve sonraki sürümlerde, sistem onStop() ve onStart() adlı etkinliği çağırdığında video oynatmayı duraklatmanız ve devam ettirmeniz gerekir. Böylece, uygulamanızın onPause() ürününde PiP modunda olup olmadığını kontrol etmek zorunda kalmaz ve açıkça oynatmaya devam edebilirsiniz.

setAutoEnterEnabled işaretini true olarak ayarlamadıysanız ve onPause() uygulamanızda oynatmayı duraklatmanız gerekiyorsa isInPictureInPictureMode()'i çağırarak PiP modunu kontrol edin ve oynatmayı uygun şekilde yönetin. Örnek:

Kotlin

override fun onPause() {
    super.onPause()
    // If called while in PiP mode, do not pause playback.
    if (isInPictureInPictureMode) {
        // Continue playback.
    } else {
        // Use existing playback logic for paused activity behavior.
    }
}

Java

@Override
public void onPause() {
    // If called while in PiP mode, do not pause playback.
    if (isInPictureInPictureMode()) {
        // Continue playback.
        ...
    } else {
        // Use existing playback logic for paused activity behavior.
        ...
    }
}

Etkinliğiniz PiP modundan tam ekran moduna geri döndüğünde sistem etkinliğinizi devam ettirir ve onResume() yönteminizi çağırır.

PiP için tek bir oynatma etkinliği kullanma

Uygulamanızda, bir video oynatma etkinliği PiP modundayken kullanıcı ana ekranda içeriklere göz atarken yeni bir video seçebilir. Kullanıcının kafasını karıştırabilecek yeni bir etkinlik başlatmak yerine, yeni videoyu mevcut oynatma etkinliğinde tam ekran modunda oynatın.

Video oynatma isteklerinde tek bir etkinliğin kullanıldığından ve gerektiğinde PiP moduna geçildiğinden veya bu moddan çıktığından emin olmak için manifest dosyanızda etkinliğin android:launchMode değerini singleTask olarak ayarlayın:

<activity android:name="VideoActivity"
    ...
    android:supportsPictureInPicture="true"
    android:launchMode="singleTask"
    ...

Etkinliğinizde, onNewIntent() etiketini geçersiz kılıp yeni videoyu işleyin ve gerekirse mevcut video oynatmalarını durdurun.

En iyi uygulamalar

PiP, RAM'i düşük olan cihazlarda devre dışı bırakılabilir. Uygulamanız PiP'yi kullanmadan önce hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE) numaralı telefonu arayarak bu özelliğin kullanılıp kullanılamadığını kontrol edin.

PiP, tam ekran video oynatan etkinlikler için tasarlanmıştır. Etkinliğinizi PiP moduna geçirirken video içeriği dışında hiçbir şey göstermekten kaçının. Etkinliğinizin PiP moduna ne zaman girdiğini izleyin ve PiP sırasında kullanıcı arayüzünü yönetme bölümünde açıklandığı gibi kullanıcı arayüzü öğelerini gizleyin.

Bir etkinlik PiP modundayken varsayılan olarak giriş odağına alınmaz. PiP modundayken giriş etkinliklerini almak için MediaSession.setCallback() işlevini kullanın. setCallback() kullanımı hakkında daha fazla bilgi için Ne Çalıyor? kartı görüntüleme bölümüne bakın.

Uygulamanız PiP modundayken PiP penceresindeki video oynatımı, müzik çalar veya sesli arama uygulaması gibi başka bir uygulamada ses parazitine neden olabilir. Bunu önlemek için videoyu oynatmaya başladığınızda ses odağını isteyin ve Ses Odağını Yönetme bölümünde açıklandığı gibi ses odağı değişikliği bildirimlerini işleyin. PiP modundayken ses odağı kaybıyla ilgili bildirim alırsanız video oynatmayı duraklatın veya durdurun.

Uygulamanız PiP'ye girmek üzereyken yalnızca en üstteki etkinliğin PiP'ye girdiğini unutmayın. Çok pencereli cihazlar gibi bazı durumlarda, PiP etkinliğinin yanında aşağıdaki etkinliğin gösterilmesi ve tekrar görünür hale gelmesi mümkündür. Aşağıdaki onResume() veya onPause() geri çağırma etkinliği de dahil olmak üzere bu destek kaydını uygun şekilde ele almanız gerekir. Kullanıcı bu etkinlikle etkileşime geçebilir. Örneğin, PiP modunda gösterilen bir video listesi etkinliğiniz ve video oynatma etkinliğiniz varsa kullanıcı listeden yeni bir video seçebilir. PiP etkinliği buna göre güncellenir.

Ek örnek kod

Kotlin ile yazılmış örnek bir uygulamayı indirmek için Android PictureInPicture Sample (Kotlin) sayfasına göz atın.