Pencere içinde pencere (PiP) Jetpack kitaplığı, Android uygulama geliştiricilerine özellikle medya oynatma, görüntülü iletişim ve navigasyon uygulamaları için PiP işlevini uygulamak üzere kolaylaştırılmış ve sağlam bir çözüm sunar. Birleşik bir API sunan kitaplık, ortak metin kodunu ve yaygın uygulama içi hataları ortadan kaldırmaya yardımcı olur ve PiP kullanıcı deneyiminin genel kalitesini artırır.
PiP Jetpack kitaplığı, Android ekosistemindeki bazı önemli zorlukları ve tutarsızlıkları ele alarak mevcut PiP API'lerini kolaylaştırır:
- OS parçalanması: Kitaplık, çeşitli Android sürümlerindeki PiP API çağrılarındaki farklılıkları otomatik olarak yönetir. Örneğin, Android 12'den önce
enterPictureInPictureMode, Android 12'den sonra iseisAutoEnterEnabledkullanılır. Bu sayede geliştiricilerin sürüm farklılıklarını yönetmesi gerekmez. - Yanlış PiP parametreleri: Medya oynatma sırasında sorunsuz ve yüksek kaliteli animasyonlar oluşturmak için PiP parametrelerini (ör.
setSourceRectHint) doğru şekilde ayarlamaya yönelik birleşik bir çözüm sunar. - Birleştirilmiş PiP durumu geri çağırmaları: Durum ve kullanıcı arayüzü yönetimini basitleştirmek için
onPictureInPictureModeChangedveonPictureInPictureUiStateChanged'yı tek bir birleştirilmiş geri çağırma arayüzünde (PictureInPictureDelegate.OnPictureInPictureEventListener) birleştirir. - Ortak metin kodu azaltma: Kitaplık, oynatma kontrolleri ve görüntülü görüşme işlemleri gibi yaygın kullanım alanları için önceden tanımlanmış
RemoteActionskümeleri sunarak tekrarlayan ortak metin kodu miktarını azaltır. - Geleceğe hazırlık: Diğer PiP özellikleri Jetpack kitaplığı üzerinden sunulur. Bu sayede kullanıcılar, ek işlevlere minimum çabayla veya hiç çaba harcamadan erişebilir.
Taşıma İş Akışı
Uygulamanın kullanım alanı kategorisini ve eski PiP mantığını belirleyin:
Kategoriler: Video Oynatma, Navigasyon veya Görüntülü Görüşme.
Tanımlanacak Eski PiP Mantığı:
onUserLeaveHintsetAutoEnterEnabledonPictureInPictureModeChangedonPictureInPictureUiStateChangedsetPictureInPictureParams.
2. AndroidManifest Yapılandırması
PiP'ye giren etkinliğin, gereksiz yeniden başlatmaları önlemek için gerekli configChanges ile AndroidManifest.xml içinde desteği beyan ettiğinden emin olun:
<activity
android:name="VideoActivity" android:supportsPictureInPicture="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation">
</activity>
3. Ortam Kurulumu
Gerekli bağımlılıkları build.gradle dosyasına ekleyin:
dependencies {
implementation("androidx.core:core:1.18.0")
implementation("androidx.activity:activity:1.13.0")
implementation("androidx.core:core-pip:1.0.0-alpha02") }
Bağımlılıklar için en son AndroidX kitaplıklarını kullanın ve bu bilgi için sürümler sayfasına bakın.
4. Şablon seçimi ve başlatma
Uygulamanın kullanım alanına en uygun uygulama şablonunu seçin:
- Navigasyon ve görüntülü görüşme:
BasicPictureInPicture; sorunsuz yeniden boyutlandırma genellikle desteklenmez ve kaynak dikdörtgen ipucuna ihtiyacınız yoktur. - Video oynatma:
VideoPlaybackPictureInPicture; kaynak dikdörtgen ipucu için oynatıcı görünüm sınırlarını otomatik olarak izler ve varsayılan olarak sorunsuz yeniden boyutlandırmayı etkinleştirir.
Jetpack kitaplığını kullanmak için mevcut özel PiP uygulamanızı Jetpack kitaplığı API'leriyle değiştirin. Geçişin karmaşıklığı ve maliyeti, uygulamanın mevcut uygulamasına göre değişiklik gösterir.
Aşağıdaki bölümlerde, PiP'nin tipik kullanım alanlarından bazıları ve gerekli uygulama adımları açıklanmaktadır:
Gezinme
Uygulama, kitaplığa navigasyonun etkin veya etkin olmayan durumunu bildirir ve en boy oranını ayarlar. Gerisini Jetpack kitaplığı halleder.
Temel farklar:
- Uygulama tarafında otomatik giriş ile eski giriş arasında ayrım yapılmasına gerek yoktur.
- Geri çağırma arayüzleri birleştirildi.
- Geriye dönük uyumluluk için yeni
PictureInPictureParamsoluşturucu.
Görüntülü Görüşme
Uygulama, kitaplığa çağrının etkin veya etkin olmayan durumu hakkında bilgi verir ve en boy oranını ayarlar.
Temel farklar:
- Uygulama tarafında otomatik giriş ile eski giriş arasında ayrım yapılmasına gerek yoktur.
- Geri çağırma arayüzleri birleştirildi.
- Geriye dönük uyumluluk için yeni
PictureInPictureParamsoluşturucu. - Görüntülü görüşme için standartlaştırılmış işlem simgeleri.
5. Kod Taşıma
- Giriş mantığı: Android 12 ve sonraki sürümler için
setAutoEnterEnabledveya Android 11 ve önceki sürümler içinonUserLeaveHintgibi API'ye özel mantığısetEnabledile değiştirin. PiP uygunluk durumu değiştiğinde bunu tetikleyin. - Geri çağırmalar:
onPictureInPictureModeChanged(düzen değiştirme) veonPictureInPictureUiStateChanged(animasyon/durumlar) etkinliklerini birleştirerek tek bir etkinlik tabanlı geri çağırmaonPictureInPictureEventoluşturun. - İşlemler ve Parametreler: Şablon örneğindeki parametreleri, her değiştiğinde
setActionsvesetAspectRatiokullanarak güncelleyin.
Referans Uygulama Modelleri
Uygulama örnekleri.
Navigasyon ve Görüntülü Görüşme
class NavOrVideoCallJpipActivity : ComponentActivity(), PictureInPictureDelegate.OnPictureInPictureEventListener { private lateinit var pictureInPictureImpl: BasicPictureInPicture override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) pictureInPictureImpl = BasicPictureInPicture(this) // BasicPictureInPicture is ideal for Navigation and Video call use cases. pictureInPictureImpl.addOnPictureInPictureEventListener( ContextCompat.getMainExecutor(this), this ) setContent { } } override fun onPictureInPictureEvent( event: PictureInPictureDelegate.Event, config: Configuration? ) { when (event) { PictureInPictureDelegate.Event.ENTERED -> { /* Toggle to PiP layout */ } PictureInPictureDelegate.Event.EXITED -> { /* Toggle to Full-screen layout */ } PictureInPictureDelegate.Event.STASHED -> { /* Optional: PiP is stashed */ } PictureInPictureDelegate.Event.UNSTASHED -> { /* Optional: PiP is unstashed */ } } } }
Video Oynatma
class VideoPlaybackJpipActivity : ComponentActivity(), PictureInPictureDelegate.OnPictureInPictureEventListener { private lateinit var pictureInPictureImpl: VideoPlaybackPictureInPicture override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) pictureInPictureImpl = VideoPlaybackPictureInPicture(this) pictureInPictureImpl.addOnPictureInPictureEventListener( ContextCompat.getMainExecutor(this), this ) setContent { ContentScreen(pictureInPictureImpl) } } override fun onPictureInPictureEvent( event: PictureInPictureDelegate.Event, config: Configuration? ) { when (event) { PictureInPictureDelegate.Event.ENTER_ANIMATION_START -> { /* Hide overlays */ } PictureInPictureDelegate.Event.ENTER_ANIMATION_END -> { /* Animation finished */ } PictureInPictureDelegate.Event.ENTERED -> { /* Switch to PiP layout */ } PictureInPictureDelegate.Event.STASHED -> { /* PiP stashed */ } PictureInPictureDelegate.Event.UNSTASHED -> { /* PiP unstashed */ } PictureInPictureDelegate.Event.EXITED -> { /* Return to full-screen */ } } } @Composable fun ContentScreen(pipController: VideoPlaybackPictureInPicture) { DisposableEffect(pipController) { onDispose { pipController.close() } } } }