पिक्चर में पिक्चर (पीआईपी) Jetpack लाइब्रेरी, Android ऐप्लिकेशन डेवलपर को पीआईपी की सुविधा लागू करने के लिए, एक आसान और बेहतर तरीका उपलब्ध कराती है. खास तौर पर, मीडिया चलाने, वीडियो कम्यूनिकेशन, और नेविगेशन ऐप्लिकेशन के लिए. यह लाइब्रेरी, एक यूनिफ़ाइड एपीआई उपलब्ध कराती है. इससे छोटे-मोटे बदलाव वाले कोड और ऐप्लिकेशन में मौजूद आम गड़बड़ियों को दूर करने में मदद मिलती है. साथ ही, PiP मोड में उपयोगकर्ता अनुभव की क्वालिटी को बेहतर बनाने में मदद मिलती है.
पीआईपी Jetpack लाइब्रेरी, मौजूदा पीआईपी एपीआई को बेहतर बनाती है. इसके लिए, यह Android ईकोसिस्टम में मौजूद कई मुख्य समस्याओं और गड़बड़ियों को ठीक करती है:
- ओएस फ़्रैगमेंटेशन: यह लाइब्रेरी, Android के अलग-अलग वर्शन में पीआईपी एपीआई कॉल के अंतर को अपने-आप मैनेज करती है. जैसे, Android 12 से पहले
enterPictureInPictureModeऔर इसके बादisAutoEnterEnabledका इस्तेमाल करना. इससे डेवलपर को वर्शन के अंतर को मैनेज करने की ज़रूरत नहीं पड़ती. - पीआईपी के गलत पैरामीटर: यह पीआईपी के पैरामीटर को सही तरीके से सेट करने के लिए, एक यूनिफ़ाइड सलूशन उपलब्ध कराता है. उदाहरण के लिए,
setSourceRectHint, ताकि मीडिया चलाने के दौरान अच्छी क्वालिटी वाले ऐनिमेशन आसानी से बनाए जा सकें. - पीआईपी मोड की स्थिति के लिए यूनिफ़ाइड कॉलबैक: यह
onPictureInPictureModeChangedऔरonPictureInPictureUiStateChangedको एक ही यूनिफ़ाइड कॉलबैक इंटरफ़ेस (PictureInPictureDelegate.OnPictureInPictureEventListener) में जोड़ता है. इससे, स्थिति और यूज़र इंटरफ़ेस (यूआई) को आसानी से मैनेज किया जा सकता है. - छोटे-मोटे बदलाव वाले कोड को कम करना: लाइब्रेरी, बार-बार इस्तेमाल होने वाले छोटे-मोटे बदलाव वाले कोड की संख्या को कम करती है. इसके लिए, वह सामान्य इस्तेमाल के उदाहरणों के लिए, पहले से तय किए गए
RemoteActionsके सेट उपलब्ध कराती है. जैसे, प्लेबैक कंट्रोल और वीडियो कॉल की कार्रवाइयां. - आने वाले समय के लिए तैयार रहना: पीआईपी की अन्य सुविधाएं, Jetpack लाइब्रेरी के ज़रिए उपलब्ध कराई जाती हैं. इससे, इस सुविधा को अपनाने वाले लोगों को बिना किसी मेहनत के या कम से कम मेहनत में अतिरिक्त सुविधाएं ऐक्सेस करने का मौका मिलता है.
माइग्रेशन वर्कफ़्लो
ऐप्लिकेशन के इस्तेमाल के उदाहरण की कैटगरी और लेगसी पीआईपी लॉजिक की पहचान करें:
कैटगरी: वीडियो चलाना, नेविगेशन या वीडियो कॉल.
पहचान करने के लिए लेगसी पीआईपी लॉजिक:
onUserLeaveHintsetAutoEnterEnabledonPictureInPictureModeChangedonPictureInPictureUiStateChangedsetPictureInPictureParams.
2. AndroidManifest कॉन्फ़िगरेशन
पक्का करें कि पीआईपी मोड में जाने वाली ऐक्टिविटी, AndroidManifest.xml में सहायता का एलान करती हो. साथ ही, इसमें ज़रूरी configChanges शामिल हो, ताकि ऐप्लिकेशन को बार-बार रीस्टार्ट न करना पड़े:
<activity
android:name="VideoActivity" android:supportsPictureInPicture="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation">
</activity>
3. एनवायरमेंट सेटअप
build.gradle में ज़रूरी डिपेंडेंसी जोड़ें:
dependencies {
implementation("androidx.core:core:1.18.0")
implementation("androidx.activity:activity:1.13.0")
implementation("androidx.core:core-pip:1.0.0-alpha02") }
डिपेंडेंसी के लिए, AndroidX लाइब्रेरी के सबसे नए वर्शन का इस्तेमाल करें. इस बारे में जानकारी पाने के लिए, रिलीज़ पेज पर जाएं.
4. टेंप्लेट चुनना और उसे शुरू करना
ऐप्लिकेशन के इस्तेमाल के हिसाब से, सबसे सही टेंप्लेट चुनें:
- नेविगेशन और वीडियो कॉल:
BasicPictureInPicture; आम तौर पर, साइज़ बदलने की सुविधा काम नहीं करती. साथ ही, आपको सोर्स रेक्ट हिंट की ज़रूरत नहीं होती. - वीडियो प्लेबैक:
VideoPlaybackPictureInPicture; सोर्स रेक्ट हिंट के लिए प्लेयर व्यू की सीमाओं को अपने-आप ट्रैक करता है और डिफ़ॉल्ट रूप से, साइज़ बदलने की सुविधा को चालू करता है.
Jetpack लाइब्रेरी को इस्तेमाल करने के लिए, अपने मौजूदा कस्टम पीआईपी को Jetpack लाइब्रेरी के एपीआई से बदलें. इस सुविधा को लागू करने की जटिलता और लागत, ऐप्लिकेशन के मौजूदा सेटअप के हिसाब से अलग-अलग होगी.
यहां दिए गए सेक्शन में, पीआईपी के इस्तेमाल के कुछ सामान्य उदाहरणों और इसे लागू करने के ज़रूरी चरणों के बारे में बताया गया है:
नेविगेशन
ऐप्लिकेशन, लाइब्रेरी को नेविगेशन के चालू या बंद होने की जानकारी देता है और आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) सेट करता है. बाकी काम Jetpack लाइब्रेरी करती है.
मुख्य अंतर:
- ऐप्लिकेशन साइड पर, ऑटो-एंटर और लेगसी-एंटर के बीच अंतर करने की ज़रूरत नहीं है.
- कॉलबैक इंटरफ़ेस को एक साथ जोड़ दिया गया है.
- पुराने सिस्टम के साथ काम करने की सुविधा के लिए, नया
PictureInPictureParamsबिल्डर.
वीडियो कॉल
ऐप्लिकेशन, लाइब्रेरी को कॉल के चालू या बंद होने की स्थिति के बारे में बताता है और आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) सेट करता है.
मुख्य अंतर:
- ऐप्लिकेशन साइड पर, ऑटो-एंटर और लेगसी-एंटर के बीच अंतर करने की ज़रूरत नहीं है.
- कॉलबैक इंटरफ़ेस को एक साथ जोड़ दिया गया है.
- पुराने सिस्टम के साथ काम करने की सुविधा के लिए, नया
PictureInPictureParamsबिल्डर. - वीडियो कॉल के लिए स्टैंडर्ड ऐक्शन आइकॉन.
5. कोड माइग्रेशन
- एंट्री लॉजिक: एपीआई के हिसाब से लॉजिक को बदलें. जैसे, Android 12 और इसके बाद के वर्शन के लिए
setAutoEnterEnabledया Android 11 और इससे पहले के वर्शन के लिएonUserLeaveHintकोsetEnabledसे बदलें. जब भी पीआईपी की ज़रूरी शर्तें पूरी करने की स्थिति में बदलाव हो, तब इसे ट्रिगर करें. - कॉलबैक:
onPictureInPictureModeChanged(लेआउट टॉगल करना) औरonPictureInPictureUiStateChanged(ऐनिमेशन/स्टेट) को इवेंट पर आधारित एक कॉलबैकonPictureInPictureEventमें जोड़ें. - कार्रवाइयां और पैरामीटर: जब भी पैरामीटर बदलें, तब टेंप्लेट इंस्टेंस पर
setActionsऔरsetAspectRatioका इस्तेमाल करके उन्हें अपडेट करें.
रेफ़रंस के तौर पर लागू करने के पैटर्न
लागू करने के उदाहरण.
नेविगेशन और वीडियो कॉल
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 */ } } } }
वीडियो प्लेबैक
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() } } } }