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

Android, Android 8.0 (API düzeyi 26) sürümünden itibaren etkinliklerin pencere içinde pencere (PiP) modunda başlatılmasına olanak tanır. PiP, çoğunlukla video oynatma için kullanılan özel bir çoklu pencere modu türüdür. Kullanıcının uygulamalar arasında gezinirken veya ana ekrandaki içeriklere göz atarken ekranın bir köşesine sabitlenmiş küçük bir pencerede video izlemesini sağlar.

PiP, sabitlenmiş video yer paylaşımı penceresini sağlamak için Android 7.0'da kullanıma sunulan çoklu pencere API'lerinden yararlanır. Uygulamanıza PiP eklemek için PiP'yi destekleyen etkinliklerinizi kaydetmeniz, gerektiğinde etkinliğinizi PiP moduna geçirmeniz ve kullanıcı arayüzü öğelerinin gizli olduğundan ve etkinlik PiP modundayken 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 olmakla birlikte, 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 şu işlemleri de yapabilir:

  • Tam ekran açma/kapatma düğmesini, kapat düğmesini, ayarlar düğmesini ve uygulamanızın sağladığı özel işlemleri (örneğin, oynatma kontrolleri) görüntülemek için pencereye bir kez dokunun.

  • Mevcut PiP boyutu ile maksimum veya minimum PiP boyutu arasında geçiş yapmak için pencereye iki kez dokunun. Örneğin, ekranı kaplayan bir pencereye iki kez dokunduğunuzda pencere en aza iner, tam tersi de geçerlidir.

  • Pencereyi sol veya sağ kenara sürükleyerek güvenceye alın. Pencereyi serbest bırakmak için, saklanan pencerenin görünür bölümüne dokunun veya pencereyi dışarı 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 birkaç örnek verilmiştir:

  • Kullanıcı ana sayfa düğmesine dokunduğunda veya ekranı yukarı kaydırarak ana sayfaya gittiğinde 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.

  • Uygulamanız, kullanıcı başka içeriklere göz atmak için videodan geri döndüğünde videoyu PiP moduna taşıyabilir.

  • Kullanıcı, içeriğin sonunu izlerken uygulamanız videoyu PiP moduna geçirebilir. Ana ekranda, serinin bir sonraki bölümüyle ilgili tanıtım amaçlı veya özet bilgiler görüntülenir.

  • Uygulamanız, kullanıcıların video izlerken ek içerikleri sıraya almaları için bir yöntem sunabilir. 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 öğesini 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 olarak değiştirme

Android 12 sürümünden itibaren setAutoEnterEnabled işaretini true olarak ayarlayarak etkinliğinizi PiP moduna geçirebilirsiniz. Bu ayar etkinleştirildiğinde bir etkinlik, onUserLeaveHint içinde açıkça enterPictureInPictureMode() çağrısı yapmak zorunda kalmadan gerektiğinde otomatik olarak PiP moduna geçer. Bu uygulamanın, çok daha sorunsuz geçişler sağlaması gibi bir avantajı da var. Ayrıntılar için Hareketle gezinmeden PiP moduna geçişleri daha akıcı hale getirme bölümünü inceleyin.

Android 11 veya önceki sürümleri hedefliyorsanız bir etkinliğin PiP moduna geçmesi 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;
    }
    ...
}

Arka plana gitmek yerine bir etkinliği PiP moduna geçiren bir mantık eklemek isteyebilirsiniz. Örneğin, kullanıcı uygulama gezinirken ana sayfa veya son kullanılanlar düğmesine basarsa Google Haritalar 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();
    }
}

Önerilir: Kullanıcılara şık 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. Bunu yaptığınızda, bu değişiklikler herhangi bir ek çalışma gerektirmeden katlanabilir cihazlar ve tabletler gibi büyük ekranlara otomatik olarak ölçeklenir.

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 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

Sorunsuz bir geçiş deneyimi sunmak için referans olarak Android Kotlin PictureInPicture örneğine bakın.

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

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 URL'sini 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. setPictureInPictureParams numaralı telefonu, güncel bilgiler için PictureInPictureParams erkenden arayın. Uygulama, Android 11'de olduğu gibi onUserLeaveHint geri çağırmasını beklemez.

    Örneğin, en boy oranı değişirse ilk oynatmada ve sonraki oynatmada setPictureInPictureParams yöntemini çağırmak isteyebilirsiniz.

  3. setAutoEnterEnabled(false) numaralı telefonu yalnızca gerekli olduğunda 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 ayarlayın

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

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

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

  1. Uygun sınırları sourceRectHint olarak 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 güncellemesi yapın. 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, video olmayan içerikleri PiP penceresinde yeniden boyutlandırırken çok daha yumuşak bir geçiş animasyonu sağlayan setSeamlessResizeEnabled işaretini ekler. Önceden, video olmayan içeriği bir PiP penceresinde yeniden boyutlandırmak, rahatsız edici görsel yapılar oluşturabiliyordu.

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() özelliğini çağırır.

Etkinliğin kullanıcı arayüzü öğelerini yeniden çizmek için bu geri çağırmaları geçersiz kılmanız gerekir. PiP modunda etkinliğinizin küçük bir pencerede gösterileceğini unutmayın. Uygulamanız 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 Kontrol 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 tam ekran haline geldiğinde tekrar geri yükleyin:

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 (mobil cihazda pencereye dokunarak veya TV uzaktan kumandasından menüyü seçerek) kontrolleri gösterebilir.

Bir uygulamada etkin medya oturumu varsa oynatma, duraklatma, sonraki ve önceki kontroller görünür.

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() değerinden daha fazla ekleme yapmaya çalışırsanız yalnızca maksimum sayıyı alırsınız.

PIP'deyken video oynatmaya devam ediliyor

Etkinliğiniz PiP'ye geçtiğinde sistem, etkinliği duraklatılmış duruma yerleştirir ve etkinliğin onPause() yöntemini çağırır. Videoyu 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() komutunu çağırarak PiP modunu kontrol edin ve oynatma işlemini uygun şekilde gerçekleştirin. Ö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 çıkıp tekrar tam ekran moduna geçtiğinde, sistem etkinliğinizi devam ettirir ve onResume() yönteminizi çağırır.

PiP için tek bir oynatma etkinliği kullan

Bir kullanıcı, uygulamanızda ana ekranda içeriğe göz atarken yeni bir video seçebilir. Bu sırada video oynatma etkinliği PiP modunda olabilir. 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 cihazlarda devre dışı bırakılmış olabilir. 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. PIP sırasında kullanıcı arayüzünü kullanma bölümünde açıklandığı gibi etkinliğinizin PiP moduna girdiği zamanı izleyin ve kullanıcı arayüzü öğelerini gizleyin.

Bir etkinlik PiP modundayken varsayılan olarak giriş odağını almaz. 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 penceresinde video oynatma, müzik çalar veya sesli arama uygulaması gibi başka bir uygulamayla ses parazitine neden olabilir. Bu durumu önlemek için videoyu oynatmaya başladığınızda ses odağını isteyin ve Ses Odaklılığını Yönetme bölümünde açıklandığı şekilde ses odağı değişikliği bildirimlerini işleme alın. 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 popüler etkinliklerin pencere içinde pencere moduna girdiğini unutmayın. Çok pencereli cihazlar gibi bazı durumlarda, aşağıdaki etkinliğin artık PiP etkinliğiyle birlikte gösterilmesi ve tekrar görünür hale gelmesi mümkündür. Bu durumu uygun şekilde ele almanız gerekir. Buna, onResume() veya onPause() geri araması alma gibi işlemler de dahildir. 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

Android'de yazılmış örnek bir uygulamayı indirmek için Pencere İçinde Pencere Örneği'ne bakın. Kotlin ile yazılmış örnek bir uygulamayı indirmek için Android PictureInPicture Sample (Kotlin) sayfasına göz atın.