ऐक्टिविटी एम्बेड करने की सुविधा, बड़ी स्क्रीन वाले डिवाइसों पर ऐप्लिकेशन को ऑप्टिमाइज़ करती है. इसके लिए, यह सुविधा किसी ऐप्लिकेशन की टास्क विंडो को दो ऐक्टिविटी या एक ही ऐक्टिविटी के दो इंस्टेंस के बीच बांट देती है.
अगर आपके ऐप्लिकेशन में कई गतिविधियां शामिल हैं, तो गतिविधि एम्बेड करने की सुविधा का इस्तेमाल करके, टैबलेट, फ़ोल्ड किए जा सकने वाले डिवाइसों, और ChromeOS डिवाइसों पर लोगों को बेहतर अनुभव दिया जा सकता है.
गतिविधि को एम्बेड करने के लिए, कोड को फिर से लिखने की ज़रूरत नहीं होती. आपके पास यह तय करने का विकल्प होता है कि आपका ऐप्लिकेशन, अपनी गतिविधियों को कैसे दिखाएगा. जैसे, अगल-बगल या एक के ऊपर एक. इसके लिए, एक्सएमएल कॉन्फ़िगरेशन फ़ाइल बनाएं या Jetpack WindowManager एपीआई कॉल करें.
छोटी स्क्रीन के लिए, सहायता अपने-आप चालू रहती है. जब आपका ऐप्लिकेशन छोटी स्क्रीन वाले डिवाइस पर होता है, तो ऐक्टिविटी एक के ऊपर एक स्टैक की जाती हैं. बड़ी स्क्रीन पर, गतिविधियां अगल-बगल दिखती हैं. सिस्टम, आपके बनाए गए कॉन्फ़िगरेशन के आधार पर प्रज़ेंटेशन तय करता है. इसके लिए, ब्रांचिंग लॉजिक की ज़रूरत नहीं होती.
डिवाइस को घुमाने पर भी, गतिविधि एम्बेड करने की सुविधा काम करती है. साथ ही, यह फ़ोल्ड किए जा सकने वाले डिवाइसों पर भी आसानी से काम करती है. डिवाइस को फ़ोल्ड और अनफ़ोल्ड करने पर, गतिविधियों को स्टैक और अनस्टैक किया जा सकता है.
ऐक्टिविटी एम्बेड करने की सुविधा, Android 12L (एपीआई लेवल 32) और इसके बाद के वर्शन पर काम करने वाले ज़्यादातर बड़ी स्क्रीन वाले डिवाइसों पर उपलब्ध है.
टास्क की विंडो को स्प्लिट करना
ऐक्टिविटी एम्बेड करने की सुविधा, ऐप्लिकेशन की टास्क विंडो को दो कंटेनर में बांटती है: प्राइमरी और सेकंडरी. कंटेनर में, मुख्य गतिविधि या कंटेनर में पहले से मौजूद अन्य गतिविधियों से लॉन्च की गई गतिविधियां होती हैं.
ऐक्टिविटी लॉन्च होने पर, उन्हें सेकंडरी कंटेनर में स्टैक किया जाता है. साथ ही, छोटी स्क्रीन पर सेकंडरी कंटेनर को प्राइमरी कंटेनर के ऊपर स्टैक किया जाता है. इसलिए, ऐक्टिविटी स्टैक करने और वापस जाने की सुविधा, आपके ऐप्लिकेशन में पहले से मौजूद ऐक्टिविटी के क्रम के हिसाब से काम करती है.
गतिविधि एम्बेड करने की सुविधा की मदद से, गतिविधियों को अलग-अलग तरीकों से दिखाया जा सकता है. आपका ऐप्लिकेशन, टास्क विंडो को स्प्लिट कर सकता है. इसके लिए, दो गतिविधियों को एक साथ साइड-बाय-साइड या एक के ऊपर एक लॉन्च किया जा सकता है:
टास्क विंडो में पूरी जगह घेरने वाली गतिविधि को स्प्लिट किया जा सकता है. इसके लिए, साथ में एक नई गतिविधि लॉन्च करें:
स्प्लिट मोड में पहले से मौजूद और टास्क विंडो शेयर करने वाली गतिविधियां, इन तरीकों से अन्य गतिविधियां लॉन्च कर सकती हैं:
किसी अन्य गतिविधि के ऊपर मौजूद साइड में:
चौथी इमेज. ऐक्टिविटी A, ऐक्टिविटी B के ऊपर साइड में ऐक्टिविटी C शुरू करती है. साइड में ले जाएं और स्प्लिट को साइड में ले जाकर, पिछली मुख्य गतिविधि को छिपाएं:
पांचवीं इमेज. गतिविधि B, गतिविधि C को साइड में शुरू करती है और स्प्लिट को साइड में ले जाती है. ऐक्टिविटी को सबसे ऊपर लॉन्च करें. इसका मतलब है कि उसे उसी ऐक्टिविटी स्टैक में लॉन्च करें:
छठी इमेज. गतिविधि B, गतिविधि C को बिना किसी अतिरिक्त इंटेंट फ़्लैग के शुरू करती है. उसी टास्क में, किसी ऐक्टिविटी को फ़ुल विंडो में लॉन्च करने के लिए:
इमेज 7. गतिविधि A या गतिविधि B, गतिविधि C शुरू करती है. यह गतिविधि, टास्क विंडो को भर देती है.
पिछले पेज पर वापस जाने की सुविधा
स्प्लिट टास्क विंडो की स्थिति में, अलग-अलग तरह के ऐप्लिकेशन के लिए, वापस जाने के अलग-अलग नियम हो सकते हैं. ये नियम, गतिविधियों के बीच की निर्भरता या उपयोगकर्ताओं के वापस जाने के इवेंट को ट्रिगर करने के तरीके पर निर्भर करते हैं. उदाहरण के लिए:
- एक साथ वापस जाना: अगर गतिविधियां एक-दूसरे से जुड़ी हैं और एक को दूसरी के बिना नहीं दिखाया जाना चाहिए, तो दोनों को पूरा करने के लिए, वापस जाने के नेविगेशन को कॉन्फ़िगर किया जा सकता है.
- अलग-अलग काम करना: अगर गतिविधियां पूरी तरह से अलग-अलग हैं, तो किसी गतिविधि पर वापस जाने से, टास्क विंडो में मौजूद दूसरी गतिविधि की स्थिति पर कोई असर नहीं पड़ता.
बटन नेविगेशन का इस्तेमाल करते समय, बैक इवेंट को फ़ोकस की गई पिछली ऐक्टिविटी पर भेजा जाता है.
जेस्चर वाले नेविगेशन के लिए:
Android 14 (एपीआई लेवल 34) और इससे पहले के वर्शन — बैक इवेंट उस गतिविधि को भेजा जाता है जहां जेस्चर हुआ था. जब उपयोगकर्ता स्क्रीन की बाईं ओर से स्वाइप करते हैं, तो 'वापस जाएं' इवेंट, स्प्लिट विंडो के बाईं ओर मौजूद गतिविधि को भेजा जाता है. जब उपयोगकर्ता स्क्रीन की दाईं ओर से स्वाइप करते हैं, तो 'वापस जाएं' इवेंट, दाईं ओर के पैनल में मौजूद गतिविधि को भेजा जाता है.
Android 15 (एपीआई लेवल 35) और उसके बाद के वर्शन
एक ही ऐप्लिकेशन में कई गतिविधियां होने पर, यह जेस्चर सबसे ऊपर वाली गतिविधि को बंद कर देता है. इससे कोई फ़र्क़ नहीं पड़ता कि आपने किस दिशा में स्वाइप किया है. इससे आपको एक जैसा अनुभव मिलता है.
जब अलग-अलग ऐप्लिकेशन की दो ऐक्टिविटी (ओवरले) शामिल होती हैं, तो वापस जाने का इवेंट, फ़ोकस में मौजूद आखिरी ऐक्टिविटी पर रीडायरेक्ट होता है. यह बटन नेविगेशन के व्यवहार के मुताबिक होता है.
मल्टी-पैन लेआउट
Jetpack WindowManager की मदद से, Android 12L (एपीआई लेवल 32) या इसके बाद के वर्शन वाले बड़े स्क्रीन डिवाइसों पर, मल्टी-पैन लेआउट में ऐक्टिविटी एम्बेड की जा सकती है. साथ ही, इसे प्लैटफ़ॉर्म के पुराने वर्शन वाले कुछ डिवाइसों पर भी इस्तेमाल किया जा सकता है. मौजूदा ऐप्लिकेशन, फ़्रैगमेंट या व्यू-आधारित लेआउट के बजाय कई गतिविधियों पर आधारित होते हैं. जैसे, SlidingPaneLayout. ये ऐप्लिकेशन, सोर्स कोड को बदले बिना बड़ी स्क्रीन पर बेहतर उपयोगकर्ता अनुभव दे सकते हैं.
इसका एक सामान्य उदाहरण, लिस्ट-डिटेल स्प्लिट है. बेहतर क्वालिटी की प्रज़ेंटेशन के लिए, सिस्टम सूची वाली गतिविधि शुरू करता है. इसके बाद, ऐप्लिकेशन तुरंत जानकारी वाली गतिविधि शुरू करता है. ट्रांज़िशन सिस्टम, दोनों गतिविधियों के ड्रॉ होने तक इंतज़ार करता है. इसके बाद, उन्हें एक साथ दिखाता है. उपयोगकर्ता को, दोनों गतिविधियां एक साथ लॉन्च होती हुई दिखती हैं.
स्प्लिट किए गए एट्रिब्यूट
यह तय किया जा सकता है कि स्प्लिट कंटेनर के बीच टास्क विंडो को किस अनुपात में बांटा जाए. साथ ही, यह भी तय किया जा सकता है कि कंटेनर एक-दूसरे के हिसाब से कैसे लेआउट किए जाएं.
एक्सएमएल कॉन्फ़िगरेशन फ़ाइल में तय किए गए नियमों के लिए, इन एट्रिब्यूट को सेट करें:
splitRatio: कंटेनर के डाइमेंशन सेट करता है. वैल्यू, ओपन इंटरवल (0.0, 1.0) में फ़्लोटिंग पॉइंट नंबर होती है.splitLayoutDirection: इससे पता चलता है कि स्प्लिट कंटेनर एक-दूसरे के हिसाब से कैसे लेआउट किए गए हैं. वैल्यू में ये शामिल हैं:ltr: बाएं से दाएंrtl: दाएं से बाएंlocale:ltrयाrtlमें से किसी एक को, स्थान-भाषा की सेटिंग के हिसाब से तय किया जाता है
उदाहरणों के लिए, एक्सएमएल कॉन्फ़िगरेशन सेक्शन देखें.
WindowManager API का इस्तेमाल करके बनाए गए नियमों के लिए, SplitAttributes.Builder की मदद से SplitAttributes ऑब्जेक्ट बनाएं. इसके बाद, बिल्डर के इन तरीकों को कॉल करें:
setSplitType(): स्प्लिट कंटेनर के साइज़ सेट करता है. मान्य आर्ग्युमेंट के लिए,SplitAttributes.SplitTypeदेखें. इसमेंSplitAttributes.SplitType.ratio()तरीका भी शामिल है.setLayoutDirection(): इससे कंटेनर का लेआउट सेट किया जाता है. संभावित वैल्यू के लिए,SplitAttributes.LayoutDirectionदेखें.
उदाहरणों के लिए, WindowManager API सेक्शन देखें.
स्प्लिट ओरिएंटेशन
डिसप्ले के डाइमेंशन और आसपेक्ट रेशियो से यह तय होता है कि गतिविधि एम्बेड करने की सुविधा के स्प्लिट में गतिविधियों को कहां रखा जाए. लैंडस्केप मोड में बड़ी स्क्रीन पर, गतिविधियां अगल-बगल दिखती हैं. पोर्ट्रेट मोड में लंबी स्क्रीन पर या फ़ोल्ड किए जा सकने वाले डिवाइसों पर टेबलटॉप मोड में, गतिविधियां एक के ऊपर एक दिखती हैं.
SplitController
SplitAttributes कैलकुलेटर की मदद से, स्प्लिट ओरिएंटेशन तय किया जा सकता है. कैलकुलेटर, चालू SplitRule के लिए SplitAttributes का हिसाब लगाता है.
डिवाइस की अलग-अलग स्थितियों के लिए, पैरंट कंटेनर को अलग-अलग दिशाओं में बांटने के लिए कैलकुलेटर का इस्तेमाल करें. उदाहरण के लिए:
Kotlin
if (WindowSdkExtensions.getInstance().extensionVersion >= 2) { SplitController.getInstance(this).setSplitAttributesCalculator { params -> val parentConfiguration = params.parentConfiguration val builder = SplitAttributes.Builder() return@setSplitAttributesCalculator if (parentConfiguration.screenWidthDp >= 840) { // Side-by-side dual-pane layout for wide displays. builder .setLayoutDirection(SplitAttributes.LayoutDirection.LOCALE) .build() } else if (parentConfiguration.screenHeightDp >= 600) { // Horizontal split for tall displays. builder .setLayoutDirection(SplitAttributes.LayoutDirection.BOTTOM_TO_TOP) .build() } else { // Fallback to expand the secondary container. builder .setSplitType(SPLIT_TYPE_EXPAND) .build() } } }
Java
if (WindowSdkExtensions.getInstance().getExtensionVersion() >= 2) { SplitController.getInstance(this).setSplitAttributesCalculator(params -> { Configuration parentConfiguration = params.getParentConfiguration(); SplitAttributes.Builder builder = new SplitAttributes.Builder(); if (parentConfiguration.screenWidthDp >= 840) { // Side-by-side dual-pane layout for wide displays. return builder .setLayoutDirection(SplitAttributes.LayoutDirection.LOCALE) .build(); } else if (parentConfiguration.screenHeightDp >= 600) { // Horizontal split for tall displays. return builder .setLayoutDirection(SplitAttributes.LayoutDirection.BOTTOM_TO_TOP) .build(); } else { // Fallback to expand the secondary container. return builder .setSplitType(SplitType.SPLIT_TYPE_EXPAND) .build(); } }); }
फ़ोल्ड किए जा सकने वाले डिवाइसों पर, स्क्रीन को वर्टिकल तौर पर स्प्लिट किया जा सकता है. इसके लिए, डिवाइस को लैंडस्केप मोड में रखें. डिवाइस को पोर्ट्रेट मोड में रखने पर, एक ही ऐक्टिविटी दिखेगी. डिवाइस को टेबलटॉप मोड में रखने पर, स्क्रीन को हॉरिज़ॉन्टल तौर पर स्प्लिट किया जा सकता है:
Kotlin
if (WindowSdkExtensions.getInstance().extensionVersion >= 2) { SplitController.getInstance(this).setSplitAttributesCalculator { params -> val tag = params.splitRuleTag val parentWindowMetrics = params.parentWindowMetrics val parentConfiguration = params.parentConfiguration val foldingFeatures = params.parentWindowLayoutInfo.displayFeatures.filterIsInstance<FoldingFeature>() val feature = if (foldingFeatures.size == 1) foldingFeatures[0] else null val builder = SplitAttributes.Builder() builder.setSplitType(SPLIT_TYPE_HINGE) return@setSplitAttributesCalculator if (feature?.isSeparating == true) { // Horizontal split for tabletop posture. builder .setSplitType(SPLIT_TYPE_HINGE) .setLayoutDirection( if (feature.orientation == FoldingFeature.Orientation.HORIZONTAL) { SplitAttributes.LayoutDirection.BOTTOM_TO_TOP } else { SplitAttributes.LayoutDirection.LOCALE } ) .build() } else if (parentConfiguration.screenWidthDp >= 840) { // Side-by-side dual-pane layout for wide displays. builder .setLayoutDirection(SplitAttributes.LayoutDirection.LOCALE) .build() } else { // No split for tall displays. builder .setSplitType(SPLIT_TYPE_EXPAND) .build() } } }
Java
if (WindowSdkExtensions.getInstance().getExtensionVersion() >= 2) { SplitController.getInstance(this).setSplitAttributesCalculator(params -> { String tag = params.getSplitRuleTag(); WindowMetrics parentWindowMetrics = params.getParentWindowMetrics(); Configuration parentConfiguration = params.getParentConfiguration(); List<FoldingFeature> foldingFeatures = params.getParentWindowLayoutInfo().getDisplayFeatures().stream().filter( item -> item instanceof FoldingFeature) .map(item -> (FoldingFeature) item) .collect(Collectors.toList()); FoldingFeature feature = foldingFeatures.size() == 1 ? foldingFeatures.get(0) : null; SplitAttributes.Builder builder = new SplitAttributes.Builder(); builder.setSplitType(SplitType.SPLIT_TYPE_HINGE); if (feature != null && feature.isSeparating()) { // Horizontal slit for tabletop posture. return builder .setSplitType(SplitType.SPLIT_TYPE_HINGE) .setLayoutDirection( feature.getOrientation() == FoldingFeature.Orientation.HORIZONTAL ? SplitAttributes.LayoutDirection.BOTTOM_TO_TOP : SplitAttributes.LayoutDirection.LOCALE) .build(); } else if (parentConfiguration.screenWidthDp >= 840) { // Side-by-side dual-pane layout for wide displays. return builder .setLayoutDirection(SplitAttributes.LayoutDirection.LOCALE) .build(); } else { // No split for tall displays. return builder .setSplitType(SplitType.SPLIT_TYPE_EXPAND) .build(); } }); }
प्लेसहोल्डर
प्लेसहोल्डर गतिविधियां, खाली सेकंडरी गतिविधियां होती हैं. ये गतिविधि के स्प्लिट के एक हिस्से पर कब्जा करती हैं. इन्हें आखिर में ऐसी गतिविधि से बदल दिया जाता है जिसमें कॉन्टेंट शामिल होता है. उदाहरण के लिए, सूची-जानकारी वाले लेआउट में, सूची से कोई आइटम चुने जाने तक, प्लेसहोल्डर ऐक्टिविटी, ऐक्टिविटी स्प्लिट के सेकंडरी साइड पर दिख सकती है. इसके बाद, चुनी गई सूची के आइटम की जानकारी वाली ऐक्टिविटी, प्लेसहोल्डर की जगह ले लेती है.
डिफ़ॉल्ट रूप से, सिस्टम प्लेसहोल्डर सिर्फ़ तब दिखाता है, जब गतिविधि को अलग-अलग हिस्सों में बांटने के लिए काफ़ी जगह हो. डिसप्ले का साइज़ बदलने पर, प्लेसहोल्डर अपने-आप बंद हो जाते हैं. ऐसा तब होता है, जब डिसप्ले की चौड़ाई या ऊंचाई इतनी कम हो जाती है कि स्प्लिट डिसप्ले नहीं किया जा सकता. जगह खाली होने पर, सिस्टम, प्लेसहोल्डर को फिर से शुरू की गई स्थिति के साथ फिर से लॉन्च करता है.
हालांकि, SplitPlaceholderRule या SplitPlaceholder.Builder के setSticky() तरीके के stickyPlaceholder एट्रिब्यूट का इस्तेमाल करके, डिफ़ॉल्ट व्यवहार को बदला जा सकता है. जब एट्रिब्यूट या तरीके से true वैल्यू तय की जाती है, तो सिस्टम, टास्क विंडो में सबसे ऊपर मौजूद गतिविधि के तौर पर प्लेसहोल्डर दिखाता है. ऐसा तब होता है, जब डिसप्ले को दो पैन वाले डिसप्ले से बदलकर एक पैन वाला डिसप्ले कर दिया जाता है. उदाहरण के लिए, स्प्लिट कॉन्फ़िगरेशन देखें.
विंडो के साइज़ में बदलाव
जब डिवाइस के कॉन्फ़िगरेशन में बदलाव होने की वजह से, टास्क विंडो की चौड़ाई कम हो जाती है, तो मल्टी-पैन लेआउट के लिए यह काफ़ी नहीं होती. उदाहरण के लिए, जब बड़ी स्क्रीन वाला फ़ोल्ड किया जा सकने वाला डिवाइस, टैबलेट के साइज़ से फ़ोन के साइज़ में फ़ोल्ड हो जाता है या मल्टी-विंडो मोड में ऐप्लिकेशन विंडो का साइज़ बदल जाता है, तो टास्क विंडो के सेकंडरी पैन में मौजूद नॉन-प्लेसहोल्डर ऐक्टिविटी, प्राइमरी पैन में मौजूद ऐक्टिविटी के ऊपर स्टैक हो जाती हैं.
स्प्लिट के लिए डिसप्ले की चौड़ाई ज़रूरत के मुताबिक होने पर ही, प्लेसहोल्डर गतिविधियां दिखाई जाती हैं. छोटी स्क्रीन पर, प्लेसहोल्डर अपने-आप हट जाता है. जब डिसप्ले एरिया का साइज़ फिर से बड़ा हो जाता है, तब प्लेसहोल्डर फिर से बन जाता है. (प्लेसहोल्डर सेक्शन देखें.)
ऐक्टिविटी स्टैक करने की सुविधा इसलिए उपलब्ध है, क्योंकि WindowManager, सेकंडरी पैन में मौजूद ऐक्टिविटी को प्राइमरी पैन में मौजूद ऐक्टिविटी के ऊपर z-ऑर्डर करता है.
सेकंडरी पैनल में कई गतिविधियां
गतिविधि B, गतिविधि C को बिना किसी अतिरिक्त इंटेंट फ़्लैग के शुरू करती है:

इस वजह से, एक ही टास्क में गतिविधियों का z-ऑर्डर इस तरह से होता है:

इसलिए, छोटी टास्क विंडो में ऐप्लिकेशन, स्टैक में सबसे ऊपर C के साथ एक गतिविधि में छोटा हो जाता है:

छोटी विंडो में वापस जाने पर, एक के ऊपर एक स्टैक की गई गतिविधियों के बीच नेविगेट किया जाता है.
अगर टास्क विंडो के कॉन्फ़िगरेशन को बड़े साइज़ में वापस लाया जाता है, तो एक साथ कई पैन को जगह दी जा सकती है. ऐसे में, गतिविधियां फिर से अगल-बगल दिखती हैं.
एक के ऊपर एक स्प्लिट
ऐक्टिविटी B, ऐक्टिविटी C को साइड में शुरू करती है और स्प्लिट को साइड में ले जाती है:

नतीजा, एक ही टास्क में गतिविधियों का यह z-ऑर्डर है:

टास्क की छोटी विंडो में, ऐप्लिकेशन को एक ही गतिविधि में छोटा कर दिया जाता है. इसमें C सबसे ऊपर होता है:

फ़िक्स्ड-पोर्ट्रेट ओरिएंटेशन
android:screenOrientation मेनिफ़ेस्ट सेटिंग की मदद से, ऐप्लिकेशन को पोर्ट्रेट या लैंडस्केप ओरिएंटेशन में ऐक्टिविटी को सीमित करने की सुविधा मिलती है. टैबलेट और फ़ोल्ड किए जा सकने वाले डिवाइसों जैसी बड़ी स्क्रीन वाले डिवाइसों पर, उपयोगकर्ता अनुभव को बेहतर बनाने के लिए, डिवाइस बनाने वाली कंपनियां (ओईएम) स्क्रीन ओरिएंटेशन के अनुरोधों को अनदेखा कर सकती हैं. साथ ही, लैंडस्केप डिसप्ले पर पोर्ट्रेट ओरिएंटेशन में या पोर्ट्रेट डिसप्ले पर लैंडस्केप ओरिएंटेशन में ऐप्लिकेशन को लेटरबॉक्स कर सकती हैं.
इसी तरह, गतिविधि एम्बेड करने की सुविधा चालू होने पर, ओईएम डिवाइसों को इस तरह से पसंद के मुताबिक बना सकते हैं कि बड़ी स्क्रीन (चौड़ाई ≥ 600 डीपी) पर लैंडस्केप ओरिएंटेशन में, फ़िक्स्ड-पोर्ट्रेट गतिविधियों को लेटरबॉक्स किया जा सके. जब फ़िक्स्ड-पोर्ट्रेट मोड में चल रही कोई ऐक्टिविटी, दूसरी ऐक्टिविटी लॉन्च करती है, तो डिवाइस दोनों ऐक्टिविटी को दो-पैन वाले डिसप्ले में अगल-बगल दिखा सकता है.
अपने ऐप्लिकेशन की मेनिफ़ेस्ट फ़ाइल में हमेशा android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED
प्रॉपर्टी जोड़ें, ताकि डिवाइसों को यह पता चल सके कि आपका ऐप्लिकेशन, गतिविधि एम्बेड करने की सुविधा के साथ काम करता है. इसके लिए, स्प्लिट कॉन्फ़िगरेशन सेक्शन देखें. इसके बाद, ओईएम के हिसाब से बनाए गए डिवाइस यह तय कर सकते हैं कि फ़िक्स्ड पोर्ट्रेट मोड में की जाने वाली गतिविधियों को लेटरबॉक्स करना है या नहीं.
स्प्लिट कॉन्फ़िगरेशन
स्प्लिट के नियमों से, गतिविधि के स्प्लिट कॉन्फ़िगर किए जाते हैं. स्प्लिट करने के नियम, एक्सएमएल कॉन्फ़िगरेशन फ़ाइल में तय किए जाते हैं. इसके अलावा, Jetpack WindowManager API कॉल करके भी ऐसा किया जा सकता है.
दोनों ही मामलों में, आपके ऐप्लिकेशन को WindowManager लाइब्रेरी को ऐक्सेस करना होगा. साथ ही, सिस्टम को यह बताना होगा कि ऐप्लिकेशन ने गतिविधि एम्बेड करने की सुविधा लागू की है.
यह तरीका अपनाएं:
अपने ऐप्लिकेशन के मॉड्यूल-लेवल की
build.gradleफ़ाइल में, WindowManager लाइब्रेरी की नई डिपेंडेंसी जोड़ें. उदाहरण के लिए:implementation 'androidx.window:window:1.1.0-beta02'WindowManager लाइब्रेरी, ऐक्टिविटी एम्बेड करने के लिए ज़रूरी सभी कॉम्पोनेंट उपलब्ध कराती है.
सिस्टम को बताएं कि आपके ऐप्लिकेशन में गतिविधि एम्बेड करने की सुविधा लागू की गई है.
ऐप्लिकेशन मेनिफ़ेस्ट फ़ाइल के <application> एलिमेंट में
android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLEDप्रॉपर्टी जोड़ें और इसकी वैल्यू को 'सही' पर सेट करें. उदाहरण के लिए:<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <application> <property android:name="android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED" android:value="true" /> </application> </manifest>WindowManager के 1.1.0-alpha06 और इसके बाद के वर्शन में, ऐक्टिविटी एम्बेड करने की सुविधा बंद कर दी गई है. हालांकि, अगर प्रॉपर्टी को मेनिफ़ेस्ट में जोड़ा जाता है और उसे true पर सेट किया जाता है, तो इस सुविधा को चालू किया जा सकता है.
इसके अलावा, डिवाइस बनाने वाली कंपनियां इस सेटिंग का इस्तेमाल करके, उन ऐप्लिकेशन के लिए कस्टम सुविधाएं चालू करती हैं जिनमें गतिविधि एम्बेड करने की सुविधा काम करती है. उदाहरण के लिए, डिवाइस लैंडस्केप डिसप्ले पर सिर्फ़ पोर्ट्रेट मोड में काम करने वाली गतिविधि को लेटरबॉक्स कर सकते हैं, ताकि दूसरी गतिविधि शुरू होने पर, दो-पैन लेआउट में ट्रांज़िशन के लिए गतिविधि को ओरिएंट किया जा सके. इसके लिए, फ़िक्स्ड-पोर्ट्रेट ओरिएंटेशन देखें.
एक्सएमएल कॉन्फ़िगरेशन
गतिविधि एम्बेड करने की सुविधा को एक्सएमएल के आधार पर लागू करने के लिए, यह तरीका अपनाएं:
ऐसी एक्सएमएल रिसॉर्स फ़ाइल बनाएं जो ये काम करती हो:
- यह कुकी, उन गतिविधियों के बारे में बताती है जिनमें स्प्लिट शेयर किया जाता है
- स्प्लिट करने के विकल्पों को कॉन्फ़िगर करता है
- कॉन्टेंट उपलब्ध न होने पर, यह कुकी स्प्लिट किए गए कंटेनर के सेकंडरी कंटेनर के लिए प्लेसहोल्डर बनाती है
- यह उन गतिविधियों के बारे में बताता है जिन्हें कभी भी स्प्लिट नहीं किया जाना चाहिए
उदाहरण के लिए:
<!-- main_split_config.xml --> <resources xmlns:window="http://schemas.android.com/apk/res-auto"> <!-- Define a split for the named activities. --> <SplitPairRule window:splitRatio="0.33" window:splitLayoutDirection="locale" window:splitMinWidthDp="840" window:splitMaxAspectRatioInPortrait="alwaysAllow" window:finishPrimaryWithSecondary="never" window:finishSecondaryWithPrimary="always" window:clearTop="false"> <SplitPairFilter window:primaryActivityName=".ListActivity" window:secondaryActivityName=".DetailActivity"/> </SplitPairRule> <!-- Specify a placeholder for the secondary container when content is not available. --> <SplitPlaceholderRule window:placeholderActivityName=".PlaceholderActivity" window:splitRatio="0.33" window:splitLayoutDirection="locale" window:splitMinWidthDp="840" window:splitMaxAspectRatioInPortrait="alwaysAllow" window:stickyPlaceholder="false"> <ActivityFilter window:activityName=".ListActivity"/> </SplitPlaceholderRule> <!-- Define activities that should never be part of a split. Note: Takes precedence over other split rules for the activity named in the rule. --> <ActivityRule window:alwaysExpand="true"> <ActivityFilter window:activityName=".ExpandedActivity"/> </ActivityRule> </resources>कोई इनिशियलाइज़र बनाएं.
WindowManager
RuleControllerकॉम्पोनेंट, एक्सएमएल कॉन्फ़िगरेशन फ़ाइल को पार्स करता है और नियमों को सिस्टम के लिए उपलब्ध कराता है. Jetpack Startup लाइब्रेरीInitializer, ऐप्लिकेशन के चालू होने परRuleControllerको एक्सएमएल फ़ाइल उपलब्ध कराती है, ताकि कोई भी गतिविधि शुरू होने पर नियम लागू हों.इनिशियलाइज़र बनाने के लिए, यह तरीका अपनाएं:
अपने मॉड्यूल-लेवल की
build.gradleफ़ाइल में, Jetpack Startup लाइब्रेरी की नई डिपेंडेंसी जोड़ें. उदाहरण के लिए:implementation 'androidx.startup:startup-runtime:1.1.1'Initializerइंटरफ़ेस को लागू करने वाली क्लास बनाएं.इनिशियलाइज़र,
RuleControllerको स्प्लिट करने के नियम उपलब्ध कराता है. इसके लिए, वहRuleController.parseRules()तरीके को एक्सएमएल कॉन्फ़िगरेशन फ़ाइल (main_split_config.xml) का आईडी पास करता है.Kotlin
class SplitInitializer : Initializer<RuleController> { override fun create(context: Context): RuleController { return RuleController.getInstance(context).apply { setRules(RuleController.parseRules(context, R.xml.main_split_config)) } } override fun dependencies(): List<Class<out Initializer<*>>> { return emptyList() } }
Java
public class SplitInitializer implements Initializer<RuleController> { @NonNull @Override public RuleController create(@NonNull Context context) { RuleController ruleController = RuleController.getInstance(context); ruleController.setRules( RuleController.parseRules(context, R.xml.main_split_config) ); return ruleController; } @NonNull @Override public List<Class<? extends Initializer<?>>> dependencies() { return Collections.emptyList(); } }
नियमों की परिभाषाओं के लिए, कॉन्टेंट देने वाला कोई व्यक्ति या कंपनी बनाएं.
अपनी ऐप्लिकेशन मेनिफ़ेस्ट फ़ाइल में
androidx.startup.InitializationProviderको<provider>के तौर पर जोड़ें. अपनेRuleControllerइनिशियलाइज़रSplitInitializerको लागू करने का रेफ़रंस शामिल करें:<!-- AndroidManifest.xml --> <provider android:name="androidx.startup.InitializationProvider" android:authorities="${applicationId}.androidx-startup" android:exported="false" tools:node="merge"> <!-- Make SplitInitializer discoverable by InitializationProvider. --> <meta-data android:name="${applicationId}.SplitInitializer" android:value="androidx.startup" /> </provider>InitializationProvider, ऐप्लिकेशन केonCreate()तरीके को कॉल करने से पहलेSplitInitializerको ढूंढता है और उसे शुरू करता है. इस वजह से, ऐप्लिकेशन की मुख्य गतिविधि शुरू होने पर, स्प्लिट करने के नियम लागू होते हैं.
WindowManager API
एपीआई कॉल की मदद से, गतिविधि को प्रोग्राम के हिसाब से एम्बेड किया जा सकता है. Application की सबक्लास के onCreate() तरीके में कॉल करें, ताकि यह पक्का किया जा सके कि कोई भी गतिविधि शुरू होने से पहले नियम लागू हो जाएं.
Application
प्रोग्राम के हिसाब से गतिविधि को बांटने के लिए, यह तरीका अपनाएं:
स्प्लिट नियम बनाएं:
एक
SplitPairFilterबनाएं. इससे उन गतिविधियों की पहचान की जा सकेगी जिनमें स्प्लिट शेयर किया गया है:Kotlin
val splitPairFilter = SplitPairFilter( ComponentName(this, ListActivity::class.java), ComponentName(this, DetailActivity::class.java), null )
Java
SplitPairFilter splitPairFilter = new SplitPairFilter( new ComponentName(this, ListActivity.class), new ComponentName(this, DetailActivity.class), null );
फ़िल्टर को फ़िल्टर सेट में जोड़ें:
```Kotlin
val filterSet = setOf(splitPairFilter)
Java
Set<SplitPairFilter> filterSet = new HashSet<>(); filterSet.add(splitPairFilter);
स्प्लिट के लिए लेआउट एट्रिब्यूट बनाएं:
Kotlin
val splitAttributes: SplitAttributes = SplitAttributes.Builder() .setSplitType(SplitAttributes.SplitType.ratio(0.33f)) .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT) .build()
Java
SplitAttributes splitAttributes = new SplitAttributes.Builder() .setSplitType(SplitAttributes.SplitType.ratio(0.33f)) .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT) .build();
SplitAttributes.Builder, लेआउट एट्रिब्यूट वाला ऑब्जेक्ट बनाता है:setSplitType(): इससे यह तय होता है कि उपलब्ध डिसप्ले एरिया को हर गतिविधि कंटेनर के लिए कैसे बांटा जाता है. रेश्यो स्प्लिट टाइप से यह तय होता है कि डिसप्ले के लिए उपलब्ध जगह का कितना हिस्सा प्राइमरी कंटेनर को दिया जाएगा. बाकी हिस्सा सेकंडरी कंटेनर को दिया जाता है.setLayoutDirection(): इससे पता चलता है कि गतिविधि कंटेनर, एक-दूसरे के हिसाब से कैसे व्यवस्थित किए जाते हैं. इसमें प्राइमरी कंटेनर को सबसे पहले रखा जाता है.
SplitPairRuleबनाएं:Kotlin
val splitPairRule = SplitPairRule.Builder(filterSet) .setDefaultSplitAttributes(splitAttributes) .setMinWidthDp(840) .setMinSmallestWidthDp(600) .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f)) .setFinishPrimaryWithSecondary(SplitRule.FinishBehavior.NEVER) .setFinishSecondaryWithPrimary(SplitRule.FinishBehavior.ALWAYS) .setClearTop(false) .build()
Java
SplitPairRule splitPairRule = new SplitPairRule.Builder(filterSet) .setDefaultSplitAttributes(splitAttributes) .setMinWidthDp(840) .setMinSmallestWidthDp(600) .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f)) .setFinishPrimaryWithSecondary(SplitRule.FinishBehavior.NEVER) .setFinishSecondaryWithPrimary(SplitRule.FinishBehavior.ALWAYS) .setClearTop(false) .build();
SplitPairRule.Builderनियम बनाता है और उसे कॉन्फ़िगर करता है:filterSet: इसमें स्प्लिट पेयर फ़िल्टर होते हैं. ये फ़िल्टर, स्प्लिट शेयर करने वाली गतिविधियों की पहचान करके यह तय करते हैं कि नियम कब लागू करना है.setDefaultSplitAttributes(): इससे लेआउट एट्रिब्यूट, नियम पर लागू होते हैं.setMinWidthDp(): यह डिसप्ले की कम से कम चौड़ाई (डेंसिटी‑इंडिपेंडेंट पिक्सल, डीपी में) सेट करता है, जिससे स्प्लिट की सुविधा चालू हो जाती है.setMinSmallestWidthDp(): यह कम से कम वैल्यू (डीपी में) सेट करता है. डिसप्ले के दो डाइमेंशन में से छोटे डाइमेंशन में यह वैल्यू होनी चाहिए, ताकि डिवाइस के ओरिएंटेशन से कोई फ़र्क़ न पड़े और स्प्लिट मोड चालू हो सके.setMaxAspectRatioInPortrait(): पोर्ट्रेट ओरिएंटेशन में, डिसप्ले के ऐसेट रेशियो (ऊंचाई:चौड़ाई) की ज़्यादा से ज़्यादा वैल्यू सेट करता है जिसके लिए गतिविधि के स्प्लिट दिखाए जाते हैं. अगर पोर्ट्रेट डिसप्ले का आसपेक्ट रेशियो, ज़्यादा से ज़्यादा आसपेक्ट रेशियो से ज़्यादा है, तो डिसप्ले की चौड़ाई कुछ भी हो, स्प्लिट डिसप्ले की सुविधा काम नहीं करेगी. ध्यान दें: डिफ़ॉल्ट वैल्यू 1.4 होती है. इससे ज़्यादातर टैबलेट पर, पोर्ट्रेट मोड में टास्क विंडो पूरी तरह से भर जाती है.SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULTऔरsetMaxAspectRatioInLandscape()भी देखें. लैंडस्केप के लिए डिफ़ॉल्ट वैल्यूALWAYS_ALLOWहै.setFinishPrimaryWithSecondary(): इससे यह तय होता है कि सेकंडरी कंटेनर में मौजूद सभी गतिविधियों को पूरा करने से, प्राइमरी कंटेनर में मौजूद गतिविधियों पर क्या असर पड़ता है.NEVERसे पता चलता है कि सेकंडरी कंटेनर में मौजूद सभी गतिविधियां पूरी होने पर, सिस्टम को मुख्य गतिविधियां पूरी नहीं करनी चाहिए (गतिविधियां पूरी करना देखें).setFinishSecondaryWithPrimary(): इससे यह तय होता है कि प्राइमरी कंटेनर में मौजूद सभी गतिविधियों को पूरा करने से, सेकंडरी कंटेनर में मौजूद गतिविधियों पर क्या असर पड़ता है.ALWAYSसे पता चलता है कि जब प्राइमरी कंटेनर में मौजूद सभी गतिविधियां पूरी हो जाती हैं, तब सिस्टम को हमेशा सेकंडरी कंटेनर में मौजूद गतिविधियों को पूरा करना चाहिए. इसके बारे में जानने के लिए, गतिविधियां पूरी करना लेख पढ़ें.setClearTop(): इससे यह तय होता है कि कंटेनर में नई गतिविधि शुरू होने पर, सेकंडरी कंटेनर में मौजूद सभी गतिविधियां पूरी हो गई हैं या नहीं.falseवैल्यू से पता चलता है कि नई गतिविधियां, पहले से ही सेकंडरी कंटेनर में मौजूद गतिविधियों के ऊपर स्टैक की जाती हैं.
WindowManager
RuleControllerका सिंगलटन इंस्टेंस पाएं और यह नियम जोड़ें:Kotlin
val ruleController = RuleController.getInstance(this) ruleController.addRule(splitPairRule)
Java
RuleController ruleController = RuleController.getInstance(this); ruleController.addRule(splitPairRule);
कॉन्टेंट उपलब्ध न होने पर, सेकंडरी कंटेनर के लिए प्लेसहोल्डर बनाएं:
एक ऐसा
ActivityFilterबनाएं जो उस गतिविधि की पहचान करे जिसके साथ प्लेसहोल्डर, टास्क विंडो को बांटता है:Kotlin
val placeholderActivityFilter = ActivityFilter( ComponentName(this, ListActivity::class.java), null )
Java
ActivityFilter placeholderActivityFilter = new ActivityFilter( new ComponentName(this, ListActivity.class), null );
फ़िल्टर को फ़िल्टर सेट में जोड़ें:
Kotlin
val placeholderActivityFilterSet = setOf(placeholderActivityFilter)
Java
Set<ActivityFilter> placeholderActivityFilterSet = new HashSet<>(); placeholderActivityFilterSet.add(placeholderActivityFilter);
SplitPlaceholderRuleबनाएं:Kotlin
val splitPlaceholderRule = SplitPlaceholderRule.Builder( placeholderActivityFilterSet, Intent(context, PlaceholderActivity::class.java) ).setDefaultSplitAttributes(splitAttributes) .setMinWidthDp(840) .setMinSmallestWidthDp(600) .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f)) .setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ALWAYS) .setSticky(false) .build()
Java
SplitPlaceholderRule splitPlaceholderRule = new SplitPlaceholderRule.Builder( placeholderActivityFilterSet, new Intent(this, PlaceholderActivity.class) ).setDefaultSplitAttributes(splitAttributes) .setMinWidthDp(840) .setMinSmallestWidthDp(600) .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f)) .setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ALWAYS) .setSticky(false) .build();
SplitPlaceholderRule.Builderनियम बनाता है और उसे कॉन्फ़िगर करता है:placeholderActivityFilterSet: इसमें गतिविधि के फ़िल्टर होते हैं. इनसे यह तय होता है कि नियम कब लागू करना है. इसके लिए, उन गतिविधियों की पहचान की जाती है जिनसे प्लेसहोल्डर गतिविधि जुड़ी होती है.Intent: इससे प्लेसहोल्डर गतिविधि के लॉन्च होने के बारे में पता चलता है.setDefaultSplitAttributes(): इससे लेआउट एट्रिब्यूट, नियम पर लागू होते हैं.setMinWidthDp(): यह डिसप्ले की कम से कम चौड़ाई (डेंसिटी-इंडिपेंडेंट पिक्सल, डीपी में) सेट करता है जिससे स्प्लिट करने की अनुमति मिलती है.setMinSmallestWidthDp(): यह डिसप्ले के दोनों डाइमेंशन में से छोटे डाइमेंशन के लिए, कम से कम वैल्यू (डीपी में) सेट करता है. इससे डिवाइस के ओरिएंटेशन से कोई फ़र्क़ नहीं पड़ता.setMaxAspectRatioInPortrait(): इससे पोर्ट्रेट ओरिएंटेशन में, डिसप्ले के ज़्यादा से ज़्यादा आसपेक्ट रेशियो (ऊंचाई:चौड़ाई) को सेट किया जाता है. इस आसपेक्ट रेशियो में, गतिविधि के स्प्लिट दिखाए जाते हैं. ध्यान दें: डिफ़ॉल्ट वैल्यू 1.4 होती है. इससे ज़्यादातर टैबलेट पर, टास्क विंडो में पोर्ट्रेट ओरिएंटेशन में गतिविधियां दिखती हैं.SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULTऔरsetMaxAspectRatioInLandscape()भी देखें. लैंडस्केप के लिए डिफ़ॉल्ट वैल्यूALWAYS_ALLOWहै.setFinishPrimaryWithPlaceholder(): इससे यह तय होता है कि प्लेसहोल्डर गतिविधि पूरी होने पर, प्राइमरी कंटेनर में मौजूद गतिविधियों पर क्या असर पड़ेगा. ALWAYS से पता चलता है कि जब प्लेसहोल्डर खत्म हो जाए, तो सिस्टम को प्राइमरी कंटेनर में मौजूद गतिविधियों को हमेशा पूरा करना चाहिए (गतिविधियां पूरी करना देखें).setSticky(): इससे यह तय होता है कि जब स्प्लिट स्क्रीन में प्लेसहोल्डर पहली बार दिखेगा, तब छोटी स्क्रीन पर प्लेसहोल्डर ऐक्टिविटी, ऐक्टिविटी स्टैक में सबसे ऊपर दिखेगी या नहीं. इसके लिए, स्प्लिट स्क्रीन की चौड़ाई कम से कम ज़रूरी चौड़ाई के बराबर होनी चाहिए.
नियम को WindowManager
RuleControllerमें जोड़ें:Kotlin
ruleController.addRule(splitPlaceholderRule)
Java
ruleController.addRule(splitPlaceholderRule);
उन गतिविधियों के बारे में बताएं जिन्हें कभी भी स्प्लिट नहीं किया जाना चाहिए:
ऐसी
ActivityFilterबनाएं जो ऐसी ऐक्टिविटी की पहचान करे जिसे हमेशा टास्क डिसप्ले एरिया के पूरे हिस्से पर दिखाना चाहिए:Kotlin
val expandedActivityFilter = ActivityFilter( ComponentName(this, ExpandedActivity::class.java), null )
Java
ActivityFilter expandedActivityFilter = new ActivityFilter( new ComponentName(this, ExpandedActivity.class), null );
फ़िल्टर को फ़िल्टर सेट में जोड़ें:
Kotlin
val expandedActivityFilterSet = setOf(expandedActivityFilter)
Java
Set<ActivityFilter> expandedActivityFilterSet = new HashSet<>(); expandedActivityFilterSet.add(expandedActivityFilter);
ActivityRuleबनाएं:Kotlin
val activityRule = ActivityRule.Builder(expandedActivityFilterSet) .setAlwaysExpand(true) .build()
Java
ActivityRule activityRule = new ActivityRule.Builder( expandedActivityFilterSet ).setAlwaysExpand(true) .build();
ActivityRule.Builderनियम बनाता है और उसे कॉन्फ़िगर करता है:expandedActivityFilterSet: इसमें गतिविधि के फ़िल्टर होते हैं. इनकी मदद से यह तय किया जाता है कि नियम कब लागू करना है. इसके लिए, उन गतिविधियों की पहचान की जाती है जिन्हें आपको स्प्लिट से हटाना है.setAlwaysExpand(): इससे यह तय होता है कि गतिविधि को पूरे टास्क विंडो में दिखाना है या नहीं.
नियम को WindowManager
RuleControllerमें जोड़ें:Kotlin
ruleController.addRule(activityRule)
Java
ruleController.addRule(activityRule);
अलग-अलग ऐप्लिकेशन में एम्बेड करना
Android 13 (एपीआई लेवल 33) और उसके बाद के वर्शन पर, ऐप्लिकेशन अन्य ऐप्लिकेशन से ऐक्टिविटी एम्बेड कर सकते हैं. क्रॉस‑ऐप्लिकेशन या क्रॉस‑यूआईडी ऐक्टिविटी एम्बेड करने की सुविधा की मदद से, एक से ज़्यादा Android ऐप्लिकेशन की ऐक्टिविटी को विज़ुअल तौर पर इंटिग्रेट किया जा सकता है. सिस्टम, होस्ट ऐप्लिकेशन की ऐक्टिविटी और किसी दूसरे ऐप्लिकेशन से एम्बेड की गई ऐक्टिविटी को स्क्रीन पर अगल-बगल या ऊपर और नीचे दिखाता है. यह ठीक उसी तरह होता है जैसे किसी एक ऐप्लिकेशन की ऐक्टिविटी को एम्बेड किया जाता है.
उदाहरण के लिए, Settings ऐप्लिकेशन, WallpaperPicker ऐप्लिकेशन से वॉलपेपर चुनने की सुविधा को एम्बेड कर सकता है:
ट्रस्ट मॉडल
होस्ट प्रोसेस, अन्य ऐप्लिकेशन से एम्बेड की गई गतिविधियों को फिर से तय कर सकती हैं. जैसे, एम्बेड की गई गतिविधियों का साइज़, पोज़िशन, काटना, और पारदर्शिता. नुकसान पहुंचाने वाले होस्ट, इस सुविधा का इस्तेमाल करके लोगों को गुमराह कर सकते हैं. साथ ही, क्लिकजैकिंग या यूज़र इंटरफ़ेस (यूआई) को नुकसान पहुंचाने वाले अन्य हमले कर सकते हैं.
क्रॉस-ऐप्लिकेशन गतिविधि एम्बेड करने की सुविधा का गलत इस्तेमाल रोकने के लिए, Android को यह ज़रूरी है कि ऐप्लिकेशन, अपनी गतिविधियों को एम्बेड करने की अनुमति देने के लिए ऑप्ट-इन करें. ऐप्लिकेशन, होस्ट को भरोसेमंद या गैर-भरोसेमंद के तौर पर मार्क कर सकते हैं.
भरोसेमंद होस्ट
अगर आपको अन्य ऐप्लिकेशन को अपने ऐप्लिकेशन की गतिविधियों को एम्बेड करने और उनके प्रज़ेंटेशन को पूरी तरह से कंट्रोल करने की अनुमति देनी है, तो अपने ऐप्लिकेशन की मेनिफ़ेस्ट फ़ाइल के <activity> या <application> एलिमेंट के android:knownActivityEmbeddingCerts एट्रिब्यूट में, होस्ट ऐप्लिकेशन का SHA-256 सर्टिफ़िकेट डालें.
android:knownActivityEmbeddingCerts की वैल्यू को स्ट्रिंग के तौर पर सेट करें:
<activity
android:name=".MyEmbeddableActivity"
android:knownActivityEmbeddingCerts="@string/known_host_certificate_digest"
... />
या, एक से ज़्यादा सर्टिफ़िकेट तय करने के लिए, स्ट्रिंग की एक कैटगरी:
<activity
android:name=".MyEmbeddableActivity"
android:knownActivityEmbeddingCerts="@array/known_host_certificate_digests"
... />
जो इस तरह के किसी संसाधन को रेफ़रंस करता है:
<resources>
<string-array name="known_host_certificate_digests">
<item>cert1</item>
<item>cert2</item>
...
</string-array>
</resources>
ऐप्लिकेशन के मालिक, Gradle
signingReport टास्क चलाकर SHA सर्टिफ़िकेट डाइजेस्ट पा सकते हैं. सर्टिफ़िकेट डाइजेस्ट, SHA-256 फ़िंगरप्रिंट होता है. इसमें कोलन नहीं होते. ज़्यादा जानकारी के लिए, हस्ताक्षर की रिपोर्ट जनरेट करना और अपने क्लाइंट की पुष्टि करना लेख पढ़ें.
ऐसे होस्ट जिन पर भरोसा नहीं किया जा सकता
किसी भी ऐप्लिकेशन को अपने ऐप्लिकेशन की गतिविधियों को एम्बेड करने और उनके प्रज़ेंटेशन को कंट्रोल करने की अनुमति देने के लिए, ऐप्लिकेशन मेनिफ़ेस्ट में <activity> या <application> एलिमेंट में android:allowUntrustedActivityEmbedding एट्रिब्यूट तय करें. उदाहरण के लिए:
<activity
android:name=".MyEmbeddableActivity"
android:allowUntrustedActivityEmbedding="true"
... />
इस एट्रिब्यूट की डिफ़ॉल्ट वैल्यू false होती है. इससे, क्रॉस-ऐप्लिकेशन गतिविधि को एम्बेड करने से रोका जाता है.
पुष्टि करने का कस्टम तरीका
भरोसेमंद न होने वाली गतिविधि को एम्बेड करने से जुड़े जोखिमों को कम करने के लिए, पुष्टि करने का कस्टम तरीका बनाएं. इससे होस्ट की पहचान की पुष्टि की जा सकेगी. अगर आपको होस्ट के सर्टिफ़िकेट के बारे में पता है, तो पुष्टि करने के लिए androidx.security.app.authenticator लाइब्रेरी का इस्तेमाल करें. अगर होस्ट आपकी गतिविधि को एम्बेड करने के बाद पुष्टि करता है, तो आपके पास असली कॉन्टेंट दिखाने का विकल्प होता है. अगर ऐसा नहीं है, तो उपयोगकर्ता को बताएं कि कार्रवाई की अनुमति नहीं दी गई है और कॉन्टेंट को ब्लॉक करें.
Jetpack WindowManager लाइब्रेरी से ActivityEmbeddingController#isActivityEmbedded() तरीके का इस्तेमाल करके यह पता लगाएं कि कोई होस्ट आपकी गतिविधि को एम्बेड कर रहा है या नहीं. उदाहरण के लिए:
Kotlin
fun isActivityEmbedded(activity: Activity): Boolean { return ActivityEmbeddingController.getInstance(this).isActivityEmbedded(activity) }
Java
boolean isActivityEmbedded(Activity activity) { return ActivityEmbeddingController.getInstance(context).isActivityEmbedded(activity); }
कम से कम साइज़ से जुड़ी पाबंदी
Android सिस्टम, ऐप्लिकेशन मेनिफ़ेस्ट <layout> एलिमेंट में बताई गई कम से कम ऊंचाई और चौड़ाई को एम्बेड की गई गतिविधियों पर लागू करता है. अगर कोई ऐप्लिकेशन कम से कम ऊंचाई और चौड़ाई तय नहीं करता है, तो सिस्टम की डिफ़ॉल्ट वैल्यू लागू होती हैं (sw220dp).
अगर होस्ट, एम्बेड किए गए कंटेनर का साइज़ कम से कम साइज़ से छोटा करने की कोशिश करता है, तो एम्बेड किया गया कंटेनर, टास्क की पूरी जगह पर फैल जाता है.
<activity-alias>
भरोसेमंद या गैर-भरोसेमंद गतिविधि एम्बेड करने के लिए, <activity-alias> एलिमेंट के साथ काम करने के लिए, android:knownActivityEmbeddingCerts या android:allowUntrustedActivityEmbedding को टारगेट गतिविधि पर लागू किया जाना चाहिए, न कि एलियास पर. सिस्टम सर्वर पर सुरक्षा की पुष्टि करने वाली नीति, टारगेट पर सेट किए गए फ़्लैग पर आधारित होती है, न कि एलियास पर.
होस्ट ऐप्लिकेशन
होस्ट ऐप्लिकेशन, क्रॉस-ऐप्लिकेशन गतिविधि को उसी तरह एम्बेड करते हैं जिस तरह वे सिंगल-ऐप्लिकेशन गतिविधि को एम्बेड करते हैं. SplitPairRule और
SplitPairFilter या ActivityRule और ActivityFilter ऑब्जेक्ट, एम्बेड की गई गतिविधियों और टास्क विंडो के स्प्लिट के बारे में बताते हैं. स्प्लिट के नियमों को एक्सएमएल में स्टैटिक तौर पर या Jetpack WindowManager API कॉल का इस्तेमाल करके रनटाइम में तय किया जाता है.
अगर कोई होस्ट ऐप्लिकेशन, ऐसी गतिविधि को एम्बेड करने की कोशिश करता है जिसने क्रॉस-ऐप्लिकेशन एम्बेडिंग के लिए ऑप्ट-इन नहीं किया है, तो गतिविधि पूरे टास्क बाउंड को कवर कर लेती है. इसलिए, होस्ट ऐप्लिकेशन को यह पता होना चाहिए कि टारगेट की गई गतिविधियों में, क्रॉस-ऐप्लिकेशन एम्बेडिंग की अनुमति है या नहीं.
अगर एम्बेड की गई कोई गतिविधि, उसी टास्क में नई गतिविधि शुरू करती है और नई गतिविधि ने क्रॉस-ऐप्लिकेशन एम्बेडिंग के लिए ऑप्ट-इन नहीं किया है, तो गतिविधि, एम्बेड किए गए कंटेनर में ओवरले करने के बजाय, पूरे टास्क बाउंड को कवर करती है.
होस्ट ऐप्लिकेशन, बिना किसी पाबंदी के अपनी गतिविधियां एम्बेड कर सकता है. हालांकि, ऐसा तब तक किया जा सकता है, जब तक गतिविधियां एक ही टास्क में लॉन्च होती हैं.
स्प्लिट के उदाहरण
फ़ुल विंडो से स्प्लिट स्क्रीन मोड चालू करना
रीफ़ैक्टरिंग की ज़रूरत नहीं है. स्प्लिट के लिए कॉन्फ़िगरेशन को स्टैटिक तौर पर या रनटाइम पर तय किया जा सकता है. इसके बाद, बिना किसी अतिरिक्त पैरामीटर के Context#startActivity() को कॉल किया जा सकता है.
<SplitPairRule>
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>
डिफ़ॉल्ट रूप से स्प्लिट किया गया
जब किसी ऐप्लिकेशन के लैंडिंग पेज को बड़ी स्क्रीन पर दो कंटेनर में बांटने के लिए डिज़ाइन किया जाता है, तो उपयोगकर्ता अनुभव सबसे अच्छा तब होता है, जब दोनों गतिविधियां एक साथ बनाई और दिखाई जाती हैं. हालांकि, जब तक उपयोगकर्ता प्राइमरी कंटेनर में मौजूद ऐक्टिविटी से इंटरैक्ट नहीं करता, तब तक स्प्लिट किए गए कॉन्टेंट का सेकंडरी कंटेनर उपलब्ध नहीं हो सकता. उदाहरण के लिए, उपयोगकर्ता ने नेविगेशन मेन्यू से कोई आइटम चुना. स्प्लिट किए गए लेआउट के सेकंडरी कंटेनर में कॉन्टेंट दिखने तक, प्लेसहोल्डर गतिविधि से खाली जगह को भरा जा सकता है. इसके बारे में जानने के लिए, प्लेसहोल्डर सेक्शन देखें.
प्लेसहोल्डर के साथ स्प्लिट बनाने के लिए, एक प्लेसहोल्डर बनाएं और उसे मुख्य गतिविधि से असोसिएट करें:
<SplitPlaceholderRule
window:placeholderActivityName=".PlaceholderActivity">
<ActivityFilter
window:activityName=".MainActivity"/>
</SplitPlaceholderRule>
डीप लिंक स्प्लिट
जब किसी ऐप्लिकेशन को इंटेंट मिलता है, तो टारगेट ऐक्टिविटी को ऐक्टिविटी स्प्लिट के दूसरे हिस्से के तौर पर दिखाया जा सकता है. उदाहरण के लिए, सूची में मौजूद किसी आइटम के बारे में जानकारी वाली स्क्रीन दिखाने का अनुरोध. छोटी स्क्रीन पर, टास्क की पूरी विंडो में जानकारी दिखती है. वहीं, बड़े डिवाइसों पर यह जानकारी सूची के बगल में दिखती है.
लॉन्च करने का अनुरोध मुख्य गतिविधि पर भेजा जाना चाहिए. साथ ही, टारगेट की जानकारी वाली गतिविधि को स्प्लिट स्क्रीन में लॉन्च किया जाना चाहिए. सिस्टम, डिसप्ले की चौड़ाई के हिसाब से, सही प्रज़ेंटेशन अपने-आप चुनता है. जैसे, स्टैक किया गया या अगल-बगल.
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) RuleController.getInstance(this) .addRule(SplitPairRule.Builder(filterSet).build()) startActivity(Intent(this, DetailActivity::class.java)) }
Java
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); RuleController.getInstance(this) .addRule(new SplitPairRule.Builder(filterSet).build()); startActivity(new Intent(this, DetailActivity.class)); }
बैक नेविगेशन स्टैक में, डीप लिंक डेस्टिनेशन ही ऐसी गतिविधि हो सकती है जो उपयोगकर्ता के लिए उपलब्ध होनी चाहिए. साथ ही, आपको जानकारी वाली गतिविधि को खारिज करने और सिर्फ़ मुख्य गतिविधि को छोड़ने से बचना चाहिए:


इसके बजाय, finishPrimaryWithSecondary एट्रिब्यूट का इस्तेमाल करके, दोनों गतिविधियों को एक साथ पूरा किया जा सकता है:
<SplitPairRule
window:finishPrimaryWithSecondary="always">
<SplitPairFilter
window:primaryActivityName=".ListActivity"
window:secondaryActivityName=".DetailActivity"/>
</SplitPairRule>
कॉन्फ़िगरेशन एट्रिब्यूट सेक्शन देखें.
स्प्लिट कंटेनर में कई गतिविधियां
स्प्लिट कंटेनर में एक साथ कई गतिविधियां जोड़ने से, उपयोगकर्ताओं को ज़्यादा जानकारी वाला कॉन्टेंट ऐक्सेस करने में मदद मिलती है. उदाहरण के लिए, लिस्ट-डिटेल स्प्लिट के साथ, उपयोगकर्ता को सब-डिटेल सेक्शन में जाना पड़ सकता है. हालांकि, वह प्राइमरी ऐक्टिविटी को चालू रखता है:
Kotlin
class DetailActivity : AppCompatActivity() { fun onOpenSubdetail() { startActivity(Intent(this, SubdetailActivity::class.java)) } }
Java
public class DetailActivity extends AppCompatActivity { void onOpenSubdetail() { startActivity(new Intent(this, SubdetailActivity.class)); } }
ज़्यादा जानकारी वाली गतिविधि के ऊपर, कम जानकारी वाली गतिविधि दिखती है. इससे ज़्यादा जानकारी वाली गतिविधि छिप जाती है:

इसके बाद, उपयोगकर्ता स्टैक में वापस जाकर, जानकारी के पिछले लेवल पर वापस जा सकता है:
जब एक ही सेकंडरी कंटेनर में मौजूद किसी गतिविधि से अन्य गतिविधियां लॉन्च की जाती हैं, तो वे एक-दूसरे के ऊपर स्टैक हो जाती हैं. यह डिफ़ॉल्ट व्यवहार है. स्प्लिट स्क्रीन मोड में चालू प्राइमरी कंटेनर से लॉन्च की गई गतिविधियां भी, गतिविधि स्टैक में सबसे ऊपर मौजूद सेकंडरी कंटेनर में दिखती हैं.
नए टास्क में की गई गतिविधियां
जब स्प्लिट टास्क विंडो में मौजूद गतिविधियां, किसी नए टास्क में गतिविधियां शुरू करती हैं, तो नया टास्क, स्प्लिट किए गए टास्क से अलग होता है. साथ ही, यह फ़ुल विंडो में दिखता है. 'हाल ही के' स्क्रीन पर दो टास्क दिख रहे हैं: स्प्लिट स्क्रीन में मौजूद टास्क और नया टास्क.
गतिविधि बदलना
सेकंडरी कंटेनर स्टैक में ऐक्टिविटी बदली जा सकती हैं. उदाहरण के लिए, जब टॉप-लेवल नेविगेशन के लिए प्राइमरी ऐक्टिविटी का इस्तेमाल किया जाता है और सेकंडरी ऐक्टिविटी, चुना गया डेस्टिनेशन होती है. टॉप-लेवल नेविगेशन से हर आइटम चुनने पर, सेकंडरी कंटेनर में नई गतिविधि शुरू होनी चाहिए. साथ ही, पहले से मौजूद गतिविधि या गतिविधियों को हटा देना चाहिए.
अगर नेविगेशन का विकल्प बदलने पर, ऐप्लिकेशन सेकंडरी कंटेनर में गतिविधि पूरी नहीं करता है, तो स्प्लिट स्क्रीन बंद होने पर (जब डिवाइस को फ़ोल्ड किया जाता है), वापस जाने का नेविगेशन भ्रमित करने वाला हो सकता है. उदाहरण के लिए, अगर आपके पास प्राइमरी पैन में कोई मेन्यू है और सेकंडरी पैन में स्क्रीन A और B स्टैक की गई हैं, तो जब उपयोगकर्ता फ़ोन को फ़ोल्ड करता है, तो B, A के ऊपर होता है और A, मेन्यू के ऊपर होता है. जब उपयोगकर्ता B से वापस जाता है, तो मेन्यू की जगह A दिखता है.
ऐसे मामलों में, स्क्रीन A को बैक स्टैक से हटाना ज़रूरी है.

स्प्लिट स्क्रीन पर पहले से मौजूद किसी कंटेनर के बगल में नया कंटेनर लॉन्च करने पर, डिफ़ॉल्ट रूप से नए सेकंडरी कंटेनर सबसे ऊपर दिखते हैं. साथ ही, पुराने कंटेनर बैक स्टैक में बने रहते हैं. clearTop का इस्तेमाल करके, स्प्लिट को कॉन्फ़िगर किया जा सकता है, ताकि पिछले सेकंडरी कंटेनर को मिटाया जा सके. साथ ही, नई गतिविधियों को सामान्य तरीके से लॉन्च किया जा सके.
<SplitPairRule
window:clearTop="true">
<SplitPairFilter
window:primaryActivityName=".Menu"
window:secondaryActivityName=".ScreenA"/>
<SplitPairFilter
window:primaryActivityName=".Menu"
window:secondaryActivityName=".ScreenB"/>
</SplitPairRule>
Kotlin
inner class MenuActivity : AppCompatActivity() { fun onMenuItemSelected(selectedMenuItem: Int) { startActivity(Intent(this, classForItem(selectedMenuItem))) } }
Java
public class MenuActivity extends AppCompatActivity{ void onMenuItemSelected(int selectedMenuItem) { startActivity(new Intent(this, classForItem(selectedMenuItem))); } }
इसके अलावा, एक ही सेकंडरी गतिविधि का इस्तेमाल करें. साथ ही, प्राइमरी (मेन्यू) गतिविधि से ऐसे नए इंटेंट भेजें जो एक ही इंस्टेंस में हल हो जाएं. हालांकि, इससे सेकंडरी कंटेनर में कोई स्थिति ट्रिगर हो या यूज़र इंटरफ़ेस (यूआई) अपडेट हो.
एक से ज़्यादा स्प्लिट
ऐप्लिकेशन, साइड में अतिरिक्त गतिविधियां लॉन्च करके, कई लेवल वाला डीप नेविगेशन उपलब्ध करा सकते हैं.
जब किसी सेकंडरी कंटेनर में मौजूद कोई ऐक्टिविटी, साइड में नई ऐक्टिविटी लॉन्च करती है, तो मौजूदा स्प्लिट के ऊपर एक नया स्प्लिट बन जाता है.
बैक स्टैक में वे सभी गतिविधियां शामिल होती हैं जिन्हें पहले खोला गया था. इसलिए, उपयोगकर्ता C को पूरा करने के बाद A/B स्प्लिट पर जा सकते हैं.

नया स्प्लिट बनाने के लिए, मौजूदा सेकंडरी कंटेनर से नई गतिविधि को साइड में लॉन्च करें. A/B और B/C, दोनों स्प्लिट के लिए कॉन्फ़िगरेशन का एलान करें. साथ ही, B से C गतिविधि को सामान्य तौर पर लॉन्च करें:
<SplitPairRule>
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
<SplitPairFilter
window:primaryActivityName=".B"
window:secondaryActivityName=".C"/>
</SplitPairRule>
Kotlin
class B : AppCompatActivity() { fun onOpenC() { startActivity(Intent(this, C::class.java)) } }
Java
public class B extends AppCompatActivity{ void onOpenC() { startActivity(new Intent(this, C.class)); } }
स्प्लिट की स्थिति में होने वाले बदलावों पर प्रतिक्रिया करना
किसी ऐप्लिकेशन में अलग-अलग ऐक्टिविटी के लिए, ऐसे यूज़र इंटरफ़ेस (यूआई) एलिमेंट हो सकते हैं जो एक ही फ़ंक्शन को पूरा करते हैं. उदाहरण के लिए, एक ऐसा कंट्रोल जो खाता सेटिंग वाली विंडो खोलता है.
अगर दो ऐसी गतिविधियों को स्प्लिट किया गया है जिनमें एक ही यूज़र इंटरफ़ेस (यूआई) एलिमेंट मौजूद है, तो दोनों गतिविधियों में उस एलिमेंट को दिखाना ज़रूरी नहीं है. इससे उपयोगकर्ता भ्रमित भी हो सकते हैं.
यह जानने के लिए कि गतिविधियां कब स्प्लिट होती हैं, SplitController.splitInfoList फ़्लो देखें या स्प्लिट की स्थिति में बदलावों के लिए, SplitControllerCallbackAdapter के साथ लिसनर रजिस्टर करें. इसके बाद,
यूज़र इंटरफ़ेस (यूआई) में इसके मुताबिक बदलाव करें:
Kotlin
val layout = layoutInflater.inflate(R.layout.activity_main, null) val view = layout.findViewById<View>(R.id.infoButton) lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { splitController.splitInfoList(this@SplitDeviceActivity) // The activity instance. .collect { list -> view.visibility = if (list.isEmpty()) View.VISIBLE else View.GONE } } }
Java
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); new SplitControllerCallbackAdapter(SplitController.getInstance(this)) .addSplitListener( this, Runnable::run, splitInfoList -> { View layout = getLayoutInflater().inflate(R.layout.activity_main, null); layout.findViewById(R.id.infoButton).setVisibility( splitInfoList.isEmpty() ? View.VISIBLE : View.GONE); }); }
कोरूटीन को लाइफ़साइकल की किसी भी स्थिति में लॉन्च किया जा सकता है. हालांकि, आम तौर पर इन्हें STARTED स्थिति में लॉन्च किया जाता है, ताकि संसाधनों को बचाया जा सके. ज़्यादा जानकारी के लिए, लाइफ़साइकल के बारे में जानकारी रखने वाले कॉम्पोनेंट के साथ Kotlin कोरूटीन का इस्तेमाल करना लेख पढ़ें.
कॉलबैक, लाइफ़साइकल की किसी भी स्थिति में किए जा सकते हैं. इसमें गतिविधि के रुकने की स्थिति भी शामिल है. आम तौर पर, श्रोताओं को onStart() में रजिस्टर किया जाना चाहिए और onStop() में अनरजिस्टर किया जाना चाहिए.
फ़ुल-विंडो मोडल
कुछ गतिविधियां, उपयोगकर्ताओं को ऐप्लिकेशन से इंटरैक्ट करने से तब तक रोकती हैं, जब तक कोई तय कार्रवाई नहीं की जाती. उदाहरण के लिए, लॉगिन स्क्रीन गतिविधि, नीति की पुष्टि करने वाली स्क्रीन या गड़बड़ी का मैसेज. स्प्लिट स्क्रीन में, मोडल गतिविधियों को दिखने से रोकना चाहिए.
एक्सपैंड कॉन्फ़िगरेशन का इस्तेमाल करके, किसी गतिविधि को हमेशा टास्क विंडो भरने के लिए मजबूर किया जा सकता है:
<ActivityRule
window:alwaysExpand="true">
<ActivityFilter
window:activityName=".FullWidthActivity"/>
</ActivityRule>
गतिविधियां पूरी करना
उपयोगकर्ता, डिसप्ले के किनारे से स्वाइप करके, स्प्लिट स्क्रीन के दोनों हिस्सों में मौजूद गतिविधियों को पूरा कर सकते हैं:
अगर डिवाइस को जेस्चर नेविगेशन के बजाय, 'वापस जाएं' बटन का इस्तेमाल करने के लिए सेट अप किया गया है, तो इनपुट को फ़ोकस की गई गतिविधि पर भेजा जाता है. यह वह गतिविधि होती है जिसे आखिरी बार छुआ गया था या लॉन्च किया गया था.
किसी कंटेनर में सभी गतिविधियां पूरी करने का असर, दूसरे कंटेनर पर पड़ता है. यह स्प्लिट कॉन्फ़िगरेशन पर निर्भर करता है.
कॉन्फ़िगरेशन एट्रिब्यूट
स्प्लिट पेयर के नियम वाले एट्रिब्यूट तय किए जा सकते हैं. इससे यह कॉन्फ़िगर किया जा सकता है कि स्प्लिट के एक हिस्से में सभी गतिविधियां पूरी होने पर, स्प्लिट के दूसरे हिस्से की गतिविधियों पर क्या असर पड़ेगा. ये एट्रिब्यूट हैं:
window:finishPrimaryWithSecondary— सेकंडरी कंटेनर में सभी गतिविधियां पूरी करने से, प्राइमरी कंटेनर में मौजूद गतिविधियों पर क्या असर पड़ता हैwindow:finishSecondaryWithPrimary— प्राइमरी कंटेनर में सभी गतिविधियां पूरी करने से, सेकंडरी कंटेनर में मौजूद गतिविधियों पर क्या असर पड़ता है
इन एट्रिब्यूट की संभावित वैल्यू ये हैं:
always— इससे जुड़ी गतिविधियों को हमेशा कंटेनर में पूरा करेंnever— इससे जुड़ी गतिविधियों को कभी भी बंद नहीं किया जाताadjacent— जब दो कंटेनर एक-दूसरे के बगल में दिख रहे हों, तब उनसे जुड़ी गतिविधियों को पूरा करें. हालांकि, जब दो कंटेनर एक के ऊपर एक रखे गए हों, तब ऐसा न करें
उदाहरण के लिए:
<SplitPairRule
<!-- Do not finish primary container activities when all secondary container activities finish. -->
window:finishPrimaryWithSecondary="never"
<!-- Finish secondary container activities when all primary container activities finish. -->
window:finishSecondaryWithPrimary="always">
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>
डिफ़ॉल्ट कॉन्फ़िगरेशन
स्प्लिट किए गए किसी कंटेनर में मौजूद सभी गतिविधियां पूरी होने पर, बाकी कंटेनर पूरी विंडो पर दिखता है:
<SplitPairRule>
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>


साथ मिलकर गतिविधियां पूरी करना
सेकंडरी कंटेनर में मौजूद सभी गतिविधियां पूरी होने पर, प्राइमरी कंटेनर में मौजूद गतिविधियां अपने-आप पूरी हो जाएं:
<SplitPairRule
window:finishPrimaryWithSecondary="always">
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>


प्राइमरी कंटेनर में मौजूद सभी गतिविधियां पूरी होने पर, सेकंडरी कंटेनर में मौजूद गतिविधियां अपने-आप पूरी हो जाएं:
<SplitPairRule
window:finishSecondaryWithPrimary="always">
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>


जब प्राइमरी या सेकंडरी कंटेनर में मौजूद सभी गतिविधियां पूरी हो जाती हैं, तब एक साथ गतिविधियां पूरी करें:
<SplitPairRule
window:finishPrimaryWithSecondary="always"
window:finishSecondaryWithPrimary="always">
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>


कंटेनर में एक साथ कई गतिविधियां पूरी करना
अगर स्प्लिट कंटेनर में कई गतिविधियां स्टैक की गई हैं, तो स्टैक में सबसे नीचे मौजूद गतिविधि को पूरा करने से, सबसे ऊपर मौजूद गतिविधियां अपने-आप पूरी नहीं हो जाती हैं.
उदाहरण के लिए, अगर दो गतिविधियां सेकंडरी कंटेनर में हैं, तो B के ऊपर C:

स्प्लिट का कॉन्फ़िगरेशन, गतिविधियों A और B के कॉन्फ़िगरेशन से तय होता है:
<SplitPairRule>
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>
सबसे ऊपर मौजूद ऐप्लिकेशन को बंद करने पर, स्प्लिट स्क्रीन बंद नहीं होती.

सेकंडरी कंटेनर की सबसे नीचे वाली (रूट) गतिविधि को पूरा करने से, उसके ऊपर की गतिविधियां नहीं हटती हैं. इसलिए, स्प्लिट स्क्रीन मोड भी बना रहता है.

साथ मिलकर गतिविधियां पूरी करने से जुड़े अन्य नियमों को भी लागू किया जाता है. जैसे, मुख्य गतिविधि के साथ-साथ दूसरी गतिविधि को भी पूरा करना:
<SplitPairRule
window:finishSecondaryWithPrimary="always">
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>

अगर स्प्लिट को इस तरह कॉन्फ़िगर किया गया है कि प्राइमरी और सेकंडरी, दोनों एक साथ खत्म हों, तो:
<SplitPairRule
window:finishPrimaryWithSecondary="always"
window:finishSecondaryWithPrimary="always">
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>



रनटाइम के दौरान स्प्लिट प्रॉपर्टी बदलना
चालू और दिखने वाले स्प्लिट की प्रॉपर्टी नहीं बदली जा सकतीं. स्प्लिट के नियमों में बदलाव करने से, अतिरिक्त गतिविधि लॉन्च और नए कंटेनर पर असर पड़ता है. हालांकि, इससे मौजूदा और चालू स्प्लिट पर कोई असर नहीं पड़ता.
चालू स्प्लिट की प्रॉपर्टी बदलने के लिए, स्प्लिट में की जा रही साइड ऐक्टिविटी या ऐक्टिविटी पूरी करें. इसके बाद, नए कॉन्फ़िगरेशन के साथ फिर से साइड ऐक्टिविटी लॉन्च करें.
डाइनैमिक स्प्लिट प्रॉपर्टी
Android 15 (एपीआई लेवल 35) और इसके बाद के वर्शन पर, Jetpack WindowManager 1.4 और इसके बाद के वर्शन काम करते हैं. इनमें डाइनैमिक सुविधाएं मिलती हैं. इनकी मदद से, ऐक्टिविटी एम्बेड करने की सुविधा के स्प्लिट को कॉन्फ़िगर किया जा सकता है. जैसे:
- पैन का बड़ा होना: इंटरैक्टिव और ड्रैग किए जा सकने वाले डिवाइडर की मदद से, उपयोगकर्ता स्प्लिट प्रज़ेंटेशन में पैन का साइज़ बदल सकते हैं.
- ऐक्टिविटी स्टैक पिन करना: उपयोगकर्ता किसी एक कंटेनर में कॉन्टेंट पिन कर सकते हैं. साथ ही, एक कंटेनर में नेविगेशन को दूसरे कंटेनर में नेविगेशन से अलग कर सकते हैं.
- डायलॉग फ़ुल-स्क्रीन डिम: डायलॉग दिखाते समय, ऐप्लिकेशन यह तय कर सकते हैं कि पूरी टास्क विंडो को डिम करना है या सिर्फ़ उस कंटेनर को जिसने डायलॉग खोला है.
पैनल को बड़ा करना
पैन को बड़ा करने की सुविधा की मदद से, उपयोगकर्ता दो पैन वाले लेआउट में, दोनों गतिविधियों के लिए स्क्रीन स्पेस को अडजस्ट कर सकते हैं.
विंडो डिवाइडर के दिखने के तरीके को पसंद के मुताबिक बनाने और डिवाइडर की ड्रैग की जा सकने वाली रेंज सेट करने के लिए, यह तरीका अपनाएं:
DividerAttributesका इंस्टेंस बनानाडिवाइडर एट्रिब्यूट को पसंद के मुताबिक बनाएं:
color: यह ड्रैग किए जा सकने वाले पैनल सेपरेटर का रंग होता है.widthDp: यह ड्रैग किए जा सकने वाले पैन सेपरेटर की चौड़ाई होती है. सिस्टम को डिवाइडर की चौड़ाई तय करने की अनुमति देने के लिए, इसेWIDTH_SYSTEM_DEFAULTपर सेट करें.ड्रैग रेंज: यह स्क्रीन के उस कम से कम प्रतिशत को दिखाता है जिस पर दोनों में से कोई भी पैन दिख सकता है. इसकी वैल्यू 0.33 से 0.66 के बीच हो सकती है. सिस्टम को ड्रैग रेंज तय करने की अनुमति देने के लिए, इसे
DRAG_RANGE_SYSTEM_DEFAULTपर सेट करें.
Kotlin
val splitAttributesBuilder: SplitAttributes.Builder = SplitAttributes.Builder() .setSplitType(SplitAttributes.SplitType.ratio(0.33f)) .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT) if (WindowSdkExtensions.getInstance().extensionVersion >= 6) { splitAttributesBuilder.setDividerAttributes( DividerAttributes.DraggableDividerAttributes.Builder() .setColor(getColor(R.color.divider_color)) .setWidthDp(4) .setDragRange(DividerAttributes.DragRange.DRAG_RANGE_SYSTEM_DEFAULT) .build() ) } val splitAttributes: SplitAttributes = splitAttributesBuilder.build()
Java
SplitAttributes.Builder splitAttributesBuilder = new SplitAttributes.Builder() .setSplitType(SplitAttributes.SplitType.ratio(0.33f)) .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT); if (WindowSdkExtensions.getInstance().getExtensionVersion() >= 6) { splitAttributesBuilder.setDividerAttributes( new DividerAttributes.DraggableDividerAttributes.Builder() .setColor(ContextCompat.getColor(this, R.color.divider_color)) .setWidthDp(4) .setDragRange(DividerAttributes.DragRange.DRAG_RANGE_SYSTEM_DEFAULT) .build() ); } SplitAttributes _splitAttributes = splitAttributesBuilder.build();
ऐक्टिविटी स्टैक को पिन करना
ऐक्टिविटी स्टैक पिन करने की सुविधा की मदद से, उपयोगकर्ता स्प्लिट की गई किसी एक विंडो को पिन कर सकते हैं. इससे, ऐक्टिविटी उसी तरह बनी रहती है जिस तरह वह पहले थी. साथ ही, उपयोगकर्ता दूसरी विंडो में नेविगेट कर पाते हैं. ऐक्टिविटी स्टैक पिन करने की सुविधा से, एक साथ कई काम करने का बेहतर अनुभव मिलता है.
अपने ऐप्लिकेशन में ऐक्टिविटी स्टैक पिन करने की सुविधा चालू करने के लिए, यह तरीका अपनाएं:
आपको जिस गतिविधि को पिन करना है उसकी लेआउट फ़ाइल में एक बटन जोड़ें. उदाहरण के लिए, सूची-जानकारी वाले लेआउट की जानकारी वाली गतिविधि:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/detailActivity" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/white" tools:context=".DetailActivity"> <TextView android:id="@+id/textViewItemDetail" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="36sp" android:textColor="@color/obsidian" app:layout_constraintBottom_toTopOf="@id/pinButton" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <androidx.appcompat.widget.AppCompatButton android:id="@+id/pinButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/pin_this_activity" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/textViewItemDetail"/> </androidx.constraintlayout.widget.ConstraintLayout>ऐक्टिविटी के
onCreate()तरीके में, बटन पर onclick लिसनर सेट करें:Kotlin
val pinButton: Button = findViewById(R.id.pinButton) pinButton.setOnClickListener { val splitAttributes: SplitAttributes = SplitAttributes.Builder() .setSplitType(SplitAttributes.SplitType.ratio(0.66f)) .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT) .build() val pinSplitRule = SplitPinRule.Builder() .setSticky(true) .setDefaultSplitAttributes(splitAttributes) .build() SplitController.getInstance(applicationContext) .pinTopActivityStack(taskId, pinSplitRule) }
Java
Button pinButton = findViewById(R.id.pinButton); pinButton.setOnClickListener( (view) -> { SplitAttributes splitAttributes = new SplitAttributes.Builder() .setSplitType(SplitAttributes.SplitType.ratio(0.66f)) .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT) .build(); SplitPinRule pinSplitRule = new SplitPinRule.Builder() .setSticky(true) .setDefaultSplitAttributes(splitAttributes) .build(); SplitController.getInstance(getApplicationContext()) .pinTopActivityStack(getTaskId(), pinSplitRule); });
डायलॉग फ़ुल-स्क्रीन डिम
आम तौर पर, डायलॉग बॉक्स पर ध्यान खींचने के लिए, ऐप्लिकेशन अपनी स्क्रीन को हल्का कर देते हैं. ऐक्टिविटी एम्बेड करने पर, ड्यूअल‑पैन डिसप्ले के दोनों पैनल धुंधले होने चाहिए. सिर्फ़ वह पैनल धुंधला नहीं होना चाहिए जिसमें डायलॉग खोलने वाली ऐक्टिविटी मौजूद है. ऐसा यूज़र इंटरफ़ेस (यूआई) को एक जैसा बनाए रखने के लिए किया जाता है.
WindowManager 1.4 और इसके बाद के वर्शन में, डायलॉग बॉक्स खुलने पर पूरी ऐप्लिकेशन विंडो डिफ़ॉल्ट रूप से धुंधली हो जाती है (EmbeddingConfiguration.DimAreaBehavior.ON_TASK देखें).
डायलॉग बॉक्स खोलने वाली गतिविधि के सिर्फ़ कंटेनर को धुंधला करने के लिए, EmbeddingConfiguration.DimAreaBehavior.ON_ACTIVITY_STACK का इस्तेमाल करें.
स्प्लिट की गई विंडो से किसी गतिविधि को फ़ुल विंडो में ले जाना
एक नया कॉन्फ़िगरेशन बनाएं, जो साइड ऐक्टिविटी को पूरी विंडो में दिखाता हो. इसके बाद, ऐक्टिविटी को ऐसे इंटेंट के साथ फिर से लॉन्च करें जो उसी इंस्टेंस पर ले जाता हो.
देखें कि स्प्लिटिंग की सुविधा रनटाइम के दौरान काम करती है या नहीं
ऐक्टिविटी एम्बेड करने की सुविधा, Android 12L (एपीआई लेवल 32) और इसके बाद के वर्शन पर काम करती है. हालांकि, यह सुविधा प्लैटफ़ॉर्म के पुराने वर्शन वाले कुछ डिवाइसों पर भी उपलब्ध है. रनटाइम पर सुविधा की उपलब्धता की जांच करने के लिए, SplitController.splitSupportStatus प्रॉपर्टी या SplitController.getSplitSupportStatus() तरीके का इस्तेमाल करें:
Kotlin
if (SplitController.getInstance(this).splitSupportStatus == SplitController.SplitSupportStatus.SPLIT_AVAILABLE ) { // Device supports split activity features. }
Java
if (SplitController.getInstance(this).getSplitSupportStatus() == SplitController.SplitSupportStatus.SPLIT_AVAILABLE) { // Device supports split activity features. }
अगर स्प्लिट स्क्रीन की सुविधा काम नहीं करती है, तो गतिविधियां, गतिविधि स्टैक के सबसे ऊपर लॉन्च की जाती हैं. ऐसा गतिविधि एम्बेड करने के मॉडल के हिसाब से किया जाता है.
सिस्टम ओवरराइड को रोकना
Android डिवाइस बनाने वाली कंपनियां (ओरिजनल इक्विपमेंट मैन्युफ़ैक्चरर या ओईएम), डिवाइस सिस्टम के फ़ंक्शन के तौर पर गतिविधि एम्बेड करने की सुविधा लागू कर सकती हैं. सिस्टम, एक साथ कई गतिविधियां करने वाले ऐप्लिकेशन के लिए स्प्लिट करने के नियम तय करता है. इससे, ऐप्लिकेशन के विंडो में दिखने के तरीके को बदला जा सकता है. सिस्टम ओवरराइड की वजह से, एक साथ कई गतिविधियां करने वाले ऐप्लिकेशन, सिस्टम के तय किए गए गतिविधि एम्बेडिंग मोड में चले जाते हैं.
सिस्टम ऐक्टिविटी एम्बेड करने की सुविधा से, ऐप्लिकेशन के प्रज़ेंटेशन को बेहतर बनाया जा सकता है. इसके लिए, मल्टी-पैन लेआउट का इस्तेमाल किया जा सकता है. जैसे, सूची-जानकारी. इसके लिए, ऐप्लिकेशन में कोई बदलाव करने की ज़रूरत नहीं होती. हालांकि, सिस्टम की ऐक्टिविटी एम्बेड करने की सुविधा से, ऐप्लिकेशन के लेआउट गलत हो सकते हैं, बग आ सकते हैं या ऐप्लिकेशन की ओर से लागू की गई ऐक्टिविटी एम्बेड करने की सुविधा के साथ टकराव हो सकता है.
आपका ऐप्लिकेशन, सिस्टम गतिविधि को एम्बेड करने से रोक सकता है या इसकी अनुमति दे सकता है. इसके लिए, ऐप्लिकेशन की मेनिफ़ेस्ट फ़ाइल में PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE सेट करें. उदाहरण के लिए:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<property
android:name="android.window.PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE"
android:value="true|false" />
</application>
</manifest>
प्रॉपर्टी का नाम, Jetpack WindowManager WindowProperties ऑब्जेक्ट में तय किया जाता है. अगर आपका ऐप्लिकेशन, गतिविधि एम्बेड करने की सुविधा लागू करता है या आपको सिस्टम को अपने ऐप्लिकेशन पर गतिविधि एम्बेड करने के नियमों को लागू करने से रोकना है, तो वैल्यू को false पर सेट करें. सिस्टम को अपने ऐप्लिकेशन पर सिस्टम के तय किए गए गतिविधि एम्बेड करने के नियमों को लागू करने की अनुमति देने के लिए, वैल्यू को true पर सेट करें.
सीमाएं, पाबंदियां, और चेतावनियां
- सिर्फ़ टास्क का होस्ट ऐप्लिकेशन, टास्क में अन्य गतिविधियों को व्यवस्थित और एम्बेड कर सकता है. टास्क में रूट गतिविधि के मालिक के तौर पर इसकी पहचान की जाती है. अगर एम्बेड करने और स्प्लिट करने की सुविधा के साथ काम करने वाली गतिविधियाँ, किसी ऐसे टास्क में चलती हैं जो किसी दूसरे ऐप्लिकेशन से जुड़ा है, तो उन गतिविधियों के लिए एम्बेड करने और स्प्लिट करने की सुविधा काम नहीं करेगी.
- गतिविधियों को सिर्फ़ एक टास्क में व्यवस्थित किया जा सकता है. किसी गतिविधि को नए टास्क में लॉन्च करने पर, वह हमेशा किसी भी मौजूदा स्प्लिट के बाहर, बड़ी की गई नई विंडो में खुलती है.
- एक ही प्रोसेस में मौजूद गतिविधियों को व्यवस्थित किया जा सकता है और उन्हें स्प्लिट किया जा सकता है.
SplitInfoकॉलबैक सिर्फ़ एक ही प्रोसेस से जुड़ी गतिविधियों की जानकारी देता है, क्योंकि अलग-अलग प्रोसेस में होने वाली गतिविधियों के बारे में जानने का कोई तरीका नहीं है. - हर जोड़ी या एक गतिविधि से जुड़ा नियम, सिर्फ़ उन गतिविधियों पर लागू होता है जिन्हें नियम रजिस्टर होने के बाद लॉन्च किया जाता है. फ़िलहाल, मौजूदा स्प्लिट या उनकी विज़ुअल प्रॉपर्टी को अपडेट करने का कोई तरीका नहीं है.
- स्प्लिट पेयर फ़िल्टर का कॉन्फ़िगरेशन, गतिविधियों को पूरी तरह से लॉन्च करते समय इस्तेमाल किए गए इंटेंट से मेल खाना चाहिए. मैचिंग तब होती है, जब ऐप्लिकेशन प्रोसेस से कोई नई गतिविधि शुरू की जाती है. इसलिए, हो सकता है कि इसे उन कॉम्पोनेंट के नामों के बारे में पता न हो जिन्हें सिस्टम प्रोसेस में बाद में हल किया जाता है. ऐसा इंप्लिसिट इंटेंट का इस्तेमाल करते समय होता है. अगर लॉन्च के समय किसी कॉम्पोनेंट का नाम नहीं पता है, तो वाइल्डकार्ड ("*/*") का इस्तेमाल किया जा सकता है. साथ ही, इंटेंट ऐक्शन के आधार पर फ़िल्टर किया जा सकता है.
- फ़िलहाल, कंटेनर के बीच गतिविधियों को ट्रांसफ़र करने का कोई तरीका उपलब्ध नहीं है. साथ ही, स्प्लिट बनाने के बाद, उन्हें स्प्लिट में शामिल या उससे हटाने का भी कोई तरीका उपलब्ध नहीं है. स्प्लिट सिर्फ़ तब बनाए जाते हैं, जब WindowManager लाइब्रेरी में मैचिंग नियमों वाली नई गतिविधियां लॉन्च की जाती हैं. साथ ही, स्प्लिट तब बंद हो जाते हैं, जब स्प्लिट कंटेनर में आखिरी गतिविधि खत्म हो जाती है.
- कॉन्फ़िगरेशन में बदलाव होने पर, गतिविधियों को फिर से लॉन्च किया जा सकता है. इसलिए, जब स्प्लिट बनाया जाता है या हटाया जाता है और गतिविधि की सीमाएं बदलती हैं, तो गतिविधि के पिछले इंस्टेंस को पूरी तरह से खत्म किया जा सकता है और नया इंस्टेंस बनाया जा सकता है. इसलिए, ऐप्लिकेशन डेवलपर को लाइफ़साइकल कॉलबैक से नई गतिविधियां लॉन्च करते समय सावधानी बरतनी चाहिए.
- डिवाइसों में विंडो एक्सटेंशन इंटरफ़ेस होना चाहिए, ताकि गतिविधि एम्बेड करने की सुविधा काम कर सके. Android 12L (एपीआई लेवल 32) या इसके बाद के वर्शन पर काम करने वाले लगभग सभी बड़ी स्क्रीन वाले डिवाइसों में यह इंटरफ़ेस शामिल होता है. हालांकि, कुछ बड़ी स्क्रीन वाले डिवाइसों में विंडो एक्सटेंशन इंटरफ़ेस शामिल नहीं होता है. ऐसा इसलिए, क्योंकि इन डिवाइसों पर एक साथ कई ऐक्टिविटी नहीं की जा सकतीं. अगर बड़ी स्क्रीन वाले डिवाइस पर मल्टी-विंडो मोड काम नहीं करता है, तो हो सकता है कि उस पर गतिविधि एम्बेड करने की सुविधा भी काम न करे.
अन्य संसाधन
- कोड लैब:
- विषय से जुड़े ऑनलाइन कोर्स और रेफ़रंस मटीरियल — गतिविधि एम्बेड करना
- सैंपल ऐप्लिकेशन — activity-embedding