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

Android, Android 8.0 (API düzeyi 26) sürümünden itibaren etkinliklerin başlatılmasına izin verir. pencere içinde pencere (PIP) moduna girer. PiP, çoğunlukla özel bir çoklu pencere modudur Video oynatma için kullanılır. Kullanıcının videoyu sabitlenmiş küçük bir pencerede izlemesini sağlar uygulamalar arasında gezinirken veya içeriklere göz atarken ekranın bir köşesine ana ekrana.

PiP, kullanıcılara en iyi deneyimi sunmak için Android 7.0'da kullanıma sunulan çoklu pencere API'lerinden yararlanır. sabitlenmiş video yer paylaşımı penceresi. Uygulamanıza PIP eklemek için PIP'yi destekleyen etkinliklere gidin, etkinliğinizi gerektiğinde PiP moduna geçirin ve etkinlik olduğunda kullanıcı arayüzü öğelerinin gizli olduğundan ve video oynatmanın devam ettiğinden emin olun. PiP modunda.

PIP penceresi, ekranın en üst katmanında, sisteme bakacağız.

PiP, şu sürümü çalıştıran uyumlu Android TV OS cihazlarda da desteklenir: Android 14 (API düzeyi 34) veya sonraki sürümler. Birçok benzerlik olsa da kullanırken dikkat edilmesi gereken diğer hususlar TV'de PiP.

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 şunu da yapabilir:

  • Tam ekran açma/kapatma düğmesini, kapatma düğmesini, hatta ve uygulamanızın sağladığı özel işlemler (örneğin, kontrollerinde bulunur).

  • Mevcut PiP boyutu ile maksimum boyut arasında geçiş yapmak için pencereye iki kez dokunun veya minimum PiP boyutu (örneğin, ekranı kaplayan bir pencereye iki kez dokunma) en aza indiriyor ve tersi de geçerli.

  • Pencereyi sol veya sağ kenara sürükleyerek güvenceye alın. Güvenli Arama'yı pencerede, saklanan pencerenin görünür bölümüne dokunun veya pencereyi sürükleyin.

  • İki parmağınızla yakınlaştırıp uzaklaştırarak PiP penceresini yeniden boyutlandırın.

Uygulamanız, mevcut etkinliğin PiP moduna gireceği zamanı kontrol eder. Aşağıda bazı örnekler verilmiştir: örnekler:

  • Kullanıcı ana sayfa düğmesine dokunduğunda veya ekranı kaydırdığında bir etkinlik PiP moduna girebilir ana ekrana. Google Haritalar, Google Haritalar'ı kullanırken yol tarifini Kullanıcı aynı anda başka bir etkinlik yürütüyor.

  • Uygulamanız, kullanıcı geri döndüğünde videoyu PiP moduna taşıyabilir diğer içeriklere göz atın.

  • Kullanıcı bir videonun sonunu izlerken uygulamanız bir videoyu PiP moduna geçirebiliyor. bölümü. Ana ekranda tanıtım veya özet görüntüleniyor Serideki bir sonraki bölümle ilgili bilgiler.

  • Uygulamanız, kullanıcıların ödeme yaparken ek içerikleri sıraya almaları için bir yöntem sağlayabilir. bir video izlerler. Ana mod açıkken video, PiP modunda oynatılmaya devam eder. içerik seçim etkinliği görüntülenir.

PiP desteğini bildirme

Sistem, varsayılan olarak uygulamalar için PiP'yi otomatik olarak desteklemez. Şunu istiyorsanız: PIP'yi desteklemesi için aşağıdaki adımları izleyerek video etkinliğinizi manifest dosyanıza kaydedin: android:supportsPictureInPicture, true olarak ayarlanıyor. Ayrıca, düzen yapılandırma değişikliklerini işlemesi PiP modu geçişleri sırasında düzen değişiklikleri olduğunda yeniden başlat.

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

Etkinliğinizi PIP olarak değiştirme

Android 12 sürümünden itibaren etkinliğinizi PiP moduna geçirmek için setAutoEnterEnabled işaretini true olarak ayarlayın. Bu ayarla, bir etkinlik gerek kalmadan gerektiği şekilde PiP moduna geçer. onUserLeaveHint içinde enterPictureInPictureMode(). Bu da ek bir avantaj olarak nitelendirilir. Ayrıntılar için PiP moduna daha akıcı bir şekilde geçiş yapılmasını sağlıyor.

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

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;
    }
    ...
}

Bunun yerine bir etkinliği PiP moduna geçiren bir mantık eklemek isteyebilirsiniz. görebilirsiniz. Örneğin, aşağıdaki koşullar söz konusu olduğunda Google Haritalar PiP moduna geçer: Kullanıcı, uygulama gezinirken ana sayfa veya son kullanılanlar düğmesine bastığında. Şunları yapabilirsiniz: geçersiz kılarak bu destek kaydını yakalayın onUserLeaveHint():

Kotlin

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

Java

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

Önerilir: Kullanıcılara şık bir PIP geçiş deneyimi sunun

Android 12, animasyonlu geçişlere önemli görünüm iyileştirmeleri ekledi tam ekran ve PiP pencereler arasında. Tüm reklam gruplarını geçerli değişiklikler; bir kez yaptıktan sonra bu değişiklikler otomatik olarak katlanabilir cihazlar ve tabletler gibi büyük ekranlara sığdır.

Uygulamanız geçerli güncellemeleri içermiyorsa PiP geçişleri yine de işlevsel ancak animasyonların daha az özenli olması. Örneğin, yeni bir projenin başlangıcında sırasında PiP penceresinin kaybolmasına neden olabilir. tekrar görünmeden önce geçiş yapmanızı öneririz.

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

  • Hareketle gezinmeden PiP moduna daha kolay geçiş yapma
  • 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

Daha fazla bilgi için Android Kotlin PictureInPicture örneği referans olarak kullanabilirsiniz.

Hareketle gezinmeden PiP moduna daha kolay geçiş yapın

Android 12'den itibaren setAutoEnterEnabled işareti çok fazla bilgi sağlar. PiP modunda hareket kullanarak video içeriğine geçiş için daha akıcı animasyon navigasyon (örneğin, tam ekrandan ana sayfaya yukarı kaydırdığınızda)

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

  1. setAutoEnterEnabled işlevini kullanarak PictureInPictureParams.Builder:

    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 bilgiler için setPictureInPictureParams numaralı telefonu arayın PictureInPictureParams erken. Uygulama, onUserLeaveHint geri çağırma (Android 11'de olduğu gibi).

    Örneğin, setPictureInPictureParams numaralı telefonu en boy oranı değiştirilirse ilk oynatma ve sonraki oynatmalar.

  3. setAutoEnterEnabled(false) numaralı telefonu yalnızca gerekli olduğunda arayın. Örneğin, mevcut oynatma duraklatılmış bir moddaysa muhtemelen PIP'ye girmek istemezsiniz durumu.

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

Android 8.0'da PIP'nin kullanıma sunulmasından itibaren setSourceRectHint geçişten sonra görülebilen etkinlik alanını Pencere içinde pencere: Örneğin, video oynatıcıda video görüntüleme sınırları.

Android 12 ile sistem çok daha akıcı bir deneyim sunmak için sourceRectHint kullanır. ve PiP moduna girerken ve bu moddan çıkarken animasyon otomatik olarak gösterilir.

PiP moduna girmek ve PiP modundan çıkmak üzere sourceRectHint politikasını doğru şekilde ayarlamak için:

  1. PictureInPictureParams oluşturma sourceRectHint olarak doğru sınırlar kullanılmalıdır. Belgenize bir video oynatıcı için düzen değişikliği dinleyicisi:

    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 sistemsourceRectHint tekrar kullanılamaz. Sistem PiP modundan çıkmak üzereyken etkinlik görünüm hiyerarşisi, hedef yapılandırmasına uygulanır (örneğin, tam ekran). Uygulama, kök görünümüne bir düzen değişikliği işleyici ekleyebilir veya hedef görünümü (ör. video oynatıcı görünümü) kullanabilirsiniz. animasyon başlamadan önce sourceRectHint değerini güncelleyin.

    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());
        }
    });
    
    
ziyaret edin.

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

Android 12, setSeamlessResizeEnabled işaretini ekler. Bu işaret, PiP'de video olmayan içeriği yeniden boyutlandırırken daha yumuşak geçiş animasyonu penceresini kapatın. Önceden, video olmayan içeriği bir PiP penceresinde yeniden boyutlandırmak, rahatsız edici görsel eserler.

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 PiP moduna girdiğinde veya PiP modundan çıktığında sistem Activity.onPictureInPictureModeChanged() veya Fragment.onPictureInPictureModeChanged().

Etkinliğin kullanıcı arayüzü öğelerini yeniden çizmek için bu geri çağırmaları geçersiz kılmanız gerekir. Sakla PiP modunda etkinliğinizin küçük bir pencerede gösterileceğini unutmayın. Kullanıcılar şunları yapamaz: PiP modundayken uygulamanızın kullanıcı arayüzü öğeleriyle ve kullanıcı arayüzü öğelerinin görülmesi zor olabilir. Şunlarla video oynatma etkinlikleri: en iyi kullanıcı deneyimini sağlar.

Uygulamanızın PiP için özel işlemler sağlaması gerekiyorsa Ekleme kontrolleriyle ilgili daha fazla bilgiyi bu sayfada bulabilirsiniz. etkinlik PiP'ye girer ve etkinliğiniz tam ekran olduğunda bunları geri yükler tekrar:

Kotlin

override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean,
                                           newConfig: Configuration) {
    if (isInPictureInPictureMode) {
        // Hide the full-screen UI (controls, etc.) while in PiP mode.
    } else {
        // Restore the full-screen UI.
    }
}

Java

@Override
public void onPictureInPictureModeChanged (boolean isInPictureInPictureMode, Configuration newConfig) {
    if (isInPictureInPictureMode) {
        // Hide the full-screen UI (controls, etc.) while in PiP mode.
    } else {
        // Restore the full-screen UI.
        ...
    }
}

Kontrol ekle

PiP penceresi, kullanıcı pencerenin menüsünü açtığında kontroller gösterebilir (kullanıcının mobil cihazda pencereye dokunmak veya TV'den menüyü seçmek uzaktan kontrol edin.)

Bir uygulamanın etkin medyası varsa oturum açın, ardından oynatın, duraklat, sonraki ve önceki kontrolleri görünür.

İsterseniz PictureInPictureParams şununla: PictureInPictureParams.Builder.setActions() PiP moduna girmeden önce ve enterPictureInPictureMode(android.app.PictureInPictureParams) veya setPictureInPictureParams(android.app.PictureInPictureParams) Dikkatli olun. Daha fazla eklemeye çalışırsanız getMaxNumPictureInPictureActions(), yalnızca maksimum sayıda bulunur.

PIP'deyken video oynatmaya devam ediliyor

Etkinliğiniz PIP olarak değiştiğinde sistem, etkinliği duraklatılmış etkinliğe ilişkin onPause() yöntemini kullanabilirsiniz. Video oynatmanın duraklatılmaması gerekir. Bunun yerine, ilgili etkinlik PiP moduna geçilirken duraklatıldı.

Android 7.0 ve sonraki sürümlerde, sistem, etkinliğinizin onStop() ve onStart(). Böylece, onPause() ve benzer uygulamalarda uygulamanızın PiP modunda olup olmadığını kontrol etmek zorunda kalmazsınız devam ettirebilir.

setAutoEnterEnabled işaretini true olarak ayarlamadıysanız ve şunu yapmanız gerekiyorsa: onPause() uygulamanızda oynatmayı duraklatın, PiP modunu kontrol etmek için isInPictureInPictureMode() ve oynatmayı uygun şekilde işleyin. Ö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 tekrar tam ekran moduna geçtiğinde sistem etkinliğinize devam eder ve onResume() yöntemini kullanabilirsiniz.

PiP için tek bir oynatma etkinliği kullan

Uygulamanızda, içeriklerinize göz atan bir kullanıcı yeni bir video seçebilir. ana ekranda görebilirsiniz. Yeni videoyu oynat tam ekran modunda gösterilen mevcut oynatma etkinliğinde kullanıcının kafasını karıştırabilecek yeni bir aktivitedir.

Video oynatma istekleri için tek bir etkinliğin kullanıldığından ve değiştirildiğinden emin olmak için Gerektiğinde PiP moduna geçer veya bu moddan çıkar, etkinliğin android:launchMode ayarını Manifest dosyanızdaki singleTask:

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

Etkinliğinizde, onNewIntent() ve yeni videoyu işlerken mevcut video oynatmayı durdurmanız gerekir.

En iyi uygulamalar

PiP, RAM'i düşük cihazlarda devre dışı bırakılmış olabilir. Uygulamanız PIP kullanmadan önce mevcut olup olmadığını kontrol etmek için şu numarayı arayın: hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE).

PiP, tam ekran video oynatan etkinlikler için tasarlanmıştır. işlem varsa video içeriği dışında hiçbir şey göstermeyin. İzleme zamanı: Kullanıcı arayüzünü kullanma konusunda açıklandığı gibi etkinliğiniz PiP moduna girebilir ve kullanıcı arayüzü öğelerini gizler. kullanıma sunuyoruz.

Bir etkinlik PiP modundayken varsayılan olarak giriş odağını almaz. Alıcı: PiP modundayken giriş etkinliklerini al, MediaSession.setCallback(). setCallback() uygulamasını kullanma hakkında daha fazla bilgi için bkz. Ne Çalıyor? uygulamasını görüntüleme kartı.

Uygulamanız PiP modundayken PiP penceresindeki video oynatma sese neden olabilir müzik çalar uygulaması veya sesli arama uygulaması gibi başka bir uygulamayla parazit. Bunu önlemek için videoyu oynatmaya başladığınızda ses odağı isteyin ve Sesi Yönetme bölümünde açıklandığı üzere ses odağı değişikliği bildirimleri Odak. Bildirim alırsanız video oynatmayı duraklatabilir veya durdurabilirsiniz.

Uygulamanız PIP'ye girmek üzereyken yalnızca en önemli etkinliklerin girildiğine dikkat edin pencere içinde pencere özelliği var. Çok pencereli cihazlarda olduğu gibi bazı durumlarda aşağıdaki etkinlikler artık gösterilir ve yan yana tekrar görünür hale gelir PiP etkinliği. Bu durumu, onResume() veya onPause() geri araması alınıyor. Aynı zamanda Kullanıcının etkinlikle etkileşime girmesi olasılığı yüksektir. Örneğin yeni web sitesi PiP modunda gösterilen video listesi etkinliği ve video oynatma etkinliği, Kullanıcı listeden yeni bir video seçebilir ve PiP etkinliğinin güncellenmesi gerekir. buna göre hazırlar.

Ek örnek kod

Kotlin dilinde yazılmış örnek bir uygulama indirmek için bkz. Android PictureInPicture Sample (Kotlin).