मीडिया प्रोजेक्शन

Android 5 (एपीआई लेवल 21) में पेश किए गए android.media.projection एपीआई की मदद से, डिवाइस की डिसप्ले पर मौजूद कॉन्टेंट को मीडिया स्ट्रीम के तौर पर कैप्चर किया जा सकता है. इसे वापस चलाया जा सकता है, रिकॉर्ड किया जा सकता है या टीवी जैसे अन्य डिवाइसों पर कास्ट किया जा सकता है.

Android 14 (एपीआई लेवल 34) में, ऐप्लिकेशन की स्क्रीन शेयर करने की सुविधा जोड़ी गई है. इसकी मदद से, लोग पूरी डिवाइस स्क्रीन के बजाय सिर्फ़ एक ऐप्लिकेशन विंडो शेयर कर सकते हैं. इससे कोई फ़र्क़ नहीं पड़ता कि विंडोइंग मोड कौन-सा है. ऐप्लिकेशन की स्क्रीन शेयर करने पर, स्टेटस बार, नेविगेशन बार, सूचनाएं, और सिस्टम के अन्य यूज़र इंटरफ़ेस (यूआई) एलिमेंट शेयर नहीं किए जाते. भले ही, ऐप्लिकेशन की स्क्रीन शेयर करने की सुविधा का इस्तेमाल, ऐप्लिकेशन को फ़ुल स्क्रीन में कैप्चर करने के लिए किया गया हो. सिर्फ़ चुने गए ऐप्लिकेशन का कॉन्टेंट शेयर किया जाता है.

ऐप्लिकेशन की स्क्रीन शेयर करने की सुविधा से, उपयोगकर्ता की निजता बनी रहती है और उनकी प्रॉडक्टिविटी बढ़ती है. साथ ही, एक साथ कई काम करने की सुविधा बेहतर होती है. ऐसा इसलिए, क्योंकि उपयोगकर्ता एक साथ कई ऐप्लिकेशन चला सकते हैं. हालांकि, वे सिर्फ़ एक ऐप्लिकेशन के साथ कॉन्टेंट शेयर कर सकते हैं.

डिसप्ले के तीन वर्शन

मीडिया प्रोजेक्शन, डिवाइस की स्क्रीन या ऐप्लिकेशन विंडो के कॉन्टेंट को कैप्चर करता है. इसके बाद, कैप्चर की गई इमेज को वर्चुअल डिसप्ले पर प्रोजेक्ट करता है. यह वर्चुअल डिसप्ले, इमेज को Surface पर रेंडर करता है.

असली डिवाइस के डिसप्ले को वर्चुअल डिसप्ले पर प्रोजेक्ट किया गया है. ऐप्लिकेशन के दिए गए `Surface` पर लिखे गए वर्चुअल डिसप्ले का कॉन्टेंट.
पहली इमेज. असली डिवाइस की स्क्रीन या ऐप्लिकेशन विंडो को वर्चुअल डिसप्ले पर प्रोजेक्ट किया गया है. वर्चुअल डिसप्ले, ऐप्लिकेशन के दिए गए Surface में लिखा गया.

यह ऐप्लिकेशन, MediaRecorder, SurfaceTexture या ImageReader के ज़रिए Surface उपलब्ध कराता है. यह कैप्चर किए गए डिसप्ले के कॉन्टेंट का इस्तेमाल करता है. साथ ही, आपको Surface पर रेंडर की गई इमेज को रीयल टाइम में मैनेज करने की सुविधा देता है. इमेज को रिकॉर्डिंग के तौर पर सेव किया जा सकता है. इसके अलावा, उन्हें टीवी या किसी अन्य डिवाइस पर कास्ट किया जा सकता है.

असली डिसप्ले

डिवाइस के डिसप्ले या ऐप्लिकेशन विंडो के कॉन्टेंट को कैप्चर करने की अनुमति देने वाला टोकन पाकर, मीडिया प्रोजेक्शन सेशन शुरू करें. टोकन को MediaProjection क्लास के इंस्टेंस के तौर पर दिखाया जाता है.

नई गतिविधि शुरू करते समय, MediaProjection इंस्टेंस बनाने के लिए, MediaProjectionManager सिस्टम सर्विस के getMediaProjection() तरीके का इस्तेमाल करें. स्क्रीन कैप्चर करने की कार्रवाई तय करने के लिए, createScreenCaptureIntent() तरीके से इंटेंट का इस्तेमाल करके गतिविधि शुरू करें:

Kotlin

val mediaProjectionManager = getSystemService(MediaProjectionManager::class.java)
var mediaProjection : MediaProjection
val startMediaProjection = registerForActivityResult( StartActivityForResult() ) { result -> if (result.resultCode == RESULT_OK) { mediaProjection = mediaProjectionManager .getMediaProjection(result.resultCode, result.data!!) } }
startMediaProjection.launch(mediaProjectionManager.createScreenCaptureIntent())

Java

final MediaProjectionManager mediaProjectionManager =
    getSystemService(MediaProjectionManager.class);
final MediaProjection[] mediaProjection = new MediaProjection[1];
ActivityResultLauncher startMediaProjection = registerForActivityResult( new StartActivityForResult(), result -> { if (result.getResultCode() == Activity.RESULT_OK) { mediaProjection[0] = mediaProjectionManager .getMediaProjection(result.getResultCode(), result.getData()); } } );
startMediaProjection.launch(mediaProjectionManager.createScreenCaptureIntent());

वर्चुअल डिसप्ले

मीडिया प्रोजेक्शन का मुख्य हिस्सा वर्चुअल डिसप्ले होता है. इसे MediaProjection इंस्टेंस पर createVirtualDisplay() को कॉल करके बनाया जाता है:

Kotlin

virtualDisplay = mediaProjection.createVirtualDisplay(
                     "ScreenCapture",
                     width,
                     height,
                     screenDensity,
                     DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                     surface,
                     null, null)

Java

virtualDisplay = mediaProjection.createVirtualDisplay(
                     "ScreenCapture",
                     width,
                     height,
                     screenDensity,
                     DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                     surface,
                     null, null);

width और height पैरामीटर, वर्चुअल डिसप्ले के डाइमेंशन तय करते हैं. चौड़ाई और ऊंचाई की वैल्यू पाने के लिए, Android 11 (एपीआई लेवल 30) में पेश किए गए WindowMetrics एपीआई का इस्तेमाल करें. (ज़्यादा जानकारी के लिए, मीडिया प्रोजेक्शन का साइज़ सेक्शन देखें.)

सतह

मीडिया प्रोजेक्शन की सतह का साइज़ तय करें, ताकि सही रिज़ॉल्यूशन में आउटपुट मिल सके. टीवी या कंप्यूटर मॉनिटर पर स्क्रीन कास्ट करने के लिए, डिसप्ले का साइज़ बड़ा (कम रिज़ॉल्यूशन) और डिवाइस पर डिसप्ले रिकॉर्ड करने के लिए, छोटा (ज़्यादा रिज़ॉल्यूशन) करें.

Android 12L (एपीआई लेवल 32) के बाद के वर्शन में, कैप्चर किए गए कॉन्टेंट को सर्फ़ेस पर रेंडर करते समय, सिस्टम कॉन्टेंट को एक जैसा स्केल करता है. साथ ही, आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) को बनाए रखता है, ताकि कॉन्टेंट के दोनों डाइमेंशन (चौड़ाई और ऊंचाई) सर्फ़ेस के डाइमेंशन के बराबर या उससे कम हों. इसके बाद, कैप्चर किए गए कॉन्टेंट को स्क्रीन पर बीच में रखा जाता है.

Android 12L में, स्क्रीन कास्टिंग के लिए बेहतर स्केलिंग की सुविधा दी गई है. इससे टीवी और अन्य बड़ी स्क्रीन पर स्क्रीन कास्टिंग की सुविधा बेहतर तरीके से काम करती है. इसमें, स्क्रीन पर दिखने वाली इमेज का साइज़ बड़ा किया जाता है, ताकि वह पूरी स्क्रीन पर दिखे. साथ ही, यह भी पक्का किया जाता है कि इमेज का आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) सही हो.

फ़ोरग्राउंड सेवा की अनुमति

अगर आपका ऐप्लिकेशन, Android 14 या उसके बाद वाले वर्शन को टारगेट करता है, तो ऐप्लिकेशन के मेनिफ़ेस्ट में mediaProjection फ़ोरग्राउंड सेवा के टाइप के लिए अनुमति का एलान शामिल होना चाहिए:

<manifest ...>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
    <application ...>
        <service
            android:name=".MyMediaProjectionService"
            android:foregroundServiceType="mediaProjection"
            android:exported="false">
        </service>
    </application>
</manifest>

startForeground() को कॉल करके, मीडिया प्रोजेक्शन सेवा शुरू करें.

अगर कॉल में फ़ोरग्राउंड सेवा के टाइप की जानकारी नहीं दी जाती है, तो टाइप डिफ़ॉल्ट रूप से, मेनिफ़ेस्ट में तय किए गए फ़ोरग्राउंड सेवा के टाइप का बिटवाइज़ पूर्णांक होता है. अगर मेनिफ़ेस्ट फ़ाइल में किसी भी सेवा के टाइप के बारे में जानकारी नहीं दी गई है, तो सिस्टम MissingForegroundServiceTypeException दिखाता है.

आपके ऐप्लिकेशन को हर मीडिया प्रोजेक्शन सेशन से पहले, उपयोगकर्ता से सहमति लेनी होगी. सेशन, createVirtualDisplay() को किया गया एक कॉल होता है. कॉल करने के लिए, MediaProjection टोकन का इस्तेमाल सिर्फ़ एक बार किया जाना चाहिए.

Android 14 या इसके बाद के वर्शन पर, अगर आपका ऐप्लिकेशन इनमें से कोई काम करता है, तो createVirtualDisplay() तरीके से SecurityException थ्रो होता है:

  • createScreenCaptureIntent() से मिले Intent इंस्टेंस को getMediaProjection() में एक से ज़्यादा बार पास करता है
  • एक ही MediaProjection इंस्टेंस पर createVirtualDisplay() को एक से ज़्यादा बार कॉल करता है

मीडिया प्रोजेक्शन का साइज़

मीडिया प्रोजेक्शन, डिवाइस के पूरे डिसप्ले या किसी ऐप्लिकेशन विंडो को कैप्चर कर सकता है. इससे कोई फ़र्क़ नहीं पड़ता कि विंडोविंग मोड कौन-सा है.

शुरुआती साइज़

फ़ुल-स्क्रीन मीडिया प्रोजेक्शन के लिए, आपके ऐप्लिकेशन को डिवाइस की स्क्रीन का साइज़ पता होना चाहिए. ऐप्लिकेशन में स्क्रीन शेयर करने की सुविधा के तहत, जब तक उपयोगकर्ता कैप्चर करने के लिए कोई क्षेत्र नहीं चुन लेता, तब तक आपका ऐप्लिकेशन कैप्चर किए गए डिसप्ले का साइज़ तय नहीं कर पाएगा. इसलिए, किसी भी मीडिया प्रोजेक्शन का शुरुआती साइज़, डिवाइस की स्क्रीन के साइज़ के बराबर होता है.

डिवाइस की स्क्रीन के लिए WindowMetrics ऑब्जेक्ट वापस पाने के लिए, प्लैटफ़ॉर्म WindowManager getMaximumWindowMetrics() तरीके का इस्तेमाल करें. भले ही, मीडिया प्रोजेक्शन होस्ट ऐप्लिकेशन मल्टी-विंडो मोड में हो और डिसप्ले का सिर्फ़ कुछ हिस्सा इस्तेमाल कर रहा हो.

एपीआई लेवल 14 तक के साथ काम करने के लिए, Jetpack WindowManager लाइब्रेरी से WindowMetricsCalculator computeMaximumWindowMetrics() तरीके का इस्तेमाल करें.

डिवाइस डिसप्ले की चौड़ाई और ऊंचाई पाने के लिए, WindowMetrics getBounds() तरीके को कॉल करें.

आकार में बदलाव

डिवाइस को घुमाने पर या ऐप्लिकेशन की स्क्रीन शेयर करने के दौरान, उपयोगकर्ता के ऐप्लिकेशन की विंडो को कैप्चर करने के लिए क्षेत्र के तौर पर चुनने पर, मीडिया प्रोजेक्शन का साइज़ बदल सकता है. अगर कैप्चर किया गया कॉन्टेंट, मीडिया प्रोजेक्शन सेट अप करते समय मिली ज़्यादा से ज़्यादा विंडो मेट्रिक से अलग साइज़ का है, तो मीडिया प्रोजेक्शन लेटरबॉक्स हो सकता है.

यह पक्का करने के लिए कि मीडिया प्रोजेक्शन, कैप्चर किए गए कॉन्टेंट के साइज़ के साथ सटीक तरीके से अलाइन हो, onCapturedContentResize() कॉलबैक का इस्तेमाल करके कैप्चर किए गए कॉन्टेंट का साइज़ बदलें. इससे, कैप्चर किए गए किसी भी हिस्से और डिवाइस के रोटेशन के हिसाब से, मीडिया प्रोजेक्शन का साइज़ बदल जाएगा. (ज़्यादा जानकारी के लिए, इसके बाद दिया गया पसंद के मुताबिक बनाना सेक्शन देखें).

पसंद के मुताबिक बनाएं

आपका ऐप्लिकेशन, मीडिया प्रोजेक्शन के उपयोगकर्ता अनुभव को इन MediaProjection.Callback एपीआई की मदद से अपनी पसंद के मुताबिक बना सकता है:

  • onCapturedContentVisibilityChanged(): इससे होस्ट ऐप्लिकेशन (वह ऐप्लिकेशन जिसने मीडिया प्रोजेक्शन शुरू किया है) को शेयर किया गया कॉन्टेंट दिखाने या छिपाने की अनुमति मिलती है.

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

  • onCapturedContentResize(): इससे होस्ट ऐप्लिकेशन, कैप्चर किए गए डिसप्ले क्षेत्र के साइज़ के आधार पर, वर्चुअल डिसप्ले और मीडिया प्रोजेक्शन Surface पर मीडिया प्रोजेक्शन का साइज़ बदल सकता है.

    यह इवेंट तब ट्रिगर होता है, जब कैप्चर किए गए कॉन्टेंट—किसी ऐप्लिकेशन की एक विंडो या पूरे डिवाइस का डिसप्ले—का साइज़ बदलता है. ऐसा डिवाइस के रोटेशन या कैप्चर किए गए ऐप्लिकेशन के किसी दूसरे विंडोविंग मोड में जाने की वजह से होता है. इस एपीआई का इस्तेमाल करके, वर्चुअल डिसप्ले और सर्फ़ेस, दोनों का साइज़ बदलें. इससे यह पक्का किया जा सकेगा कि आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात), कैप्चर किए गए कॉन्टेंट से मेल खाता हो और कैप्चर किए गए कॉन्टेंट में लेटरबॉक्सिंग न हो.

संसाधन वापस पाना

आपके ऐप्लिकेशन को MediaProjection onStop() कॉलबैक रजिस्टर करना चाहिए, ताकि मीडिया प्रोजेक्शन सेशन के बंद होने और अमान्य होने पर उसे सूचना मिल सके. सेशन बंद होने पर, आपके ऐप्लिकेशन को उन संसाधनों को रिलीज़ कर देना चाहिए जिन्हें उसने होल्ड किया है. जैसे, वर्चुअल डिसप्ले और प्रोजेक्शन सर्फ़ेस. मीडिया प्रोजेक्शन का सेशन बंद होने के बाद, नया वर्चुअल डिसप्ले नहीं बनाया जा सकता. भले ही, आपके ऐप्लिकेशन ने पहले कभी उस मीडिया प्रोजेक्शन के लिए वर्चुअल डिसप्ले न बनाया हो.

मीडिया प्रोजेक्शन बंद होने पर, सिस्टम इस कॉलबैक को शुरू करता है. खाता बंद होने की कई वजहें हो सकती हैं. जैसे:

  • जब उपयोगकर्ता, ऐप्लिकेशन के यूज़र इंटरफ़ेस या सिस्टम के मीडिया प्रोजेक्शन स्टेटस बार चिप का इस्तेमाल करके सेशन बंद कर देता है
  • स्क्रीन लॉक की जा रही हो
  • मीडिया प्रोजेक्शन का कोई दूसरा सेशन शुरू होता है
  • ऐप्लिकेशन की प्रोसेस बंद हो जाती है

अगर आपका ऐप्लिकेशन, कॉलबैक को रजिस्टर नहीं करता है, तो createVirtualDisplay() पर किए गए किसी भी कॉल से IllegalStateException गड़बड़ी होती है.

ऑप्ट आउट करें

Android 14 या इसके बाद के वर्शन में, ऐप्लिकेशन की स्क्रीन शेयर करने की सुविधा डिफ़ॉल्ट रूप से चालू होती है. मीडिया प्रोजेक्शन के हर सेशन में, उपयोगकर्ताओं के पास किसी ऐप्लिकेशन की विंडो या पूरी स्क्रीन शेयर करने का विकल्प होता है.

आपका ऐप्लिकेशन, ऐप्लिकेशन की स्क्रीन शेयर करने की सुविधा से ऑप्ट आउट कर सकता है. इसके लिए, उसे createScreenCaptureIntent(MediaProjectionConfig) तरीके को कॉल करना होगा. साथ ही, createConfigForDefaultDisplay() को कॉल करने पर मिले MediaProjectionConfig आर्ग्युमेंट का इस्तेमाल करना होगा.

createConfigForUserChoice() को कॉल करने से मिले MediaProjectionConfig आर्ग्युमेंट के साथ createScreenCaptureIntent(MediaProjectionConfig) को कॉल करना, डिफ़ॉल्ट व्यवहार के जैसा ही होता है. इसका मतलब है कि createScreenCaptureIntent() को कॉल करना.

साइज बदलने की सुविधा वाले ऐप्लिकेशन

मीडिया प्रोजेक्शन वाले ऐप्लिकेशन का साइज़ हमेशा बदला जा सकता है (resizeableActivity="true"). साइज़ बदले जा सकने वाले ऐप्लिकेशन, डिवाइस के कॉन्फ़िगरेशन में होने वाले बदलावों और मल्टी-विंडो मोड के साथ काम करते हैं. ज़्यादा जानकारी के लिए, मल्टी-विंडो मोड की सुविधा देखें.

अगर आपके ऐप्लिकेशन का साइज़ नहीं बदला जा सकता, तो उसे विंडो कॉन्टेक्स्ट से डिसप्ले बाउंड्री के बारे में क्वेरी करनी होगी. साथ ही, ऐप्लिकेशन के लिए उपलब्ध सबसे बड़े डिसप्ले एरिया का WindowMetrics पाने के लिए, getMaximumWindowMetrics() का इस्तेमाल करना होगा :

Kotlin

val windowContext = context.createWindowContext(context.display!!,
      WindowManager.LayoutParams.TYPE_APPLICATION, null)
val projectionMetrics = windowContext.getSystemService(WindowManager::class.java)
      .maximumWindowMetrics

Java

Context windowContext = context.createWindowContext(context.getDisplay(),
      WindowManager.LayoutParams.TYPE_APPLICATION, null);
WindowMetrics projectionMetrics = windowContext.getSystemService(WindowManager.class)
      .getMaximumWindowMetrics();

स्टेटस बार चिप और ऑटो स्टॉप

Screen projection exploits expose private user data such as financial information because users don't realize their device screen is being shared.

For apps running on devices with Android 15 QPR1 or higher, a status bar chip that is large and prominent alerts users to any in‑progress screen projection. Users can tap the chip to stop their screen from being shared, cast, or recorded. Also, screen projection automatically stops when the device screen is locked.

दूसरी इमेज. स्क्रीन शेयर करने, कास्ट करने, और रिकॉर्ड करने के लिए स्टेटस बार चिप.

स्क्रीन शेयर करने, कास्ट करने या रिकॉर्ड करने की सुविधा शुरू करके, मीडिया प्रोजेक्शन स्टेटस बार चिप की उपलब्धता की जांच करें. चिप, स्टेटस बार में दिखनी चाहिए.

यह पक्का करने के लिए कि स्क्रीन प्रोजेक्शन बंद होने पर, आपका ऐप्लिकेशन संसाधन रिलीज़ करे और अपने यूज़र इंटरफ़ेस (यूआई) को अपडेट करे, यह तरीका अपनाएं. स्क्रीन प्रोजेक्शन तब बंद होता है, जब उपयोगकर्ता स्टेटस बार चिप से इंटरैक्ट करता है या लॉक स्क्रीन चालू करता है:

  • MediaProjection.Callback का इंस्टेंस बनाएं.

  • कॉलबैक onStop() तरीके को लागू करें. स्क्रीन प्रोजेक्शन बंद होने पर, इस तरीके को कॉल किया जाता है. आपके ऐप्लिकेशन के पास मौजूद सभी संसाधनों को रिलीज़ करें और ज़रूरत के मुताबिक ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) को अपडेट करें.

कॉल बैक की सुविधा को आज़माने के लिए, स्टेटस बार चिप पर टैप करें या स्क्रीन प्रोजेक्शन को रोकने के लिए, डिवाइस की स्क्रीन लॉक करें. पुष्टि करें कि onStop() तरीके को कॉल किया गया है और आपका ऐप्लिकेशन, उम्मीद के मुताबिक जवाब दे रहा है.

अन्य संसाधन

मीडिया प्रोजेक्शन के बारे में ज़्यादा जानने के लिए, वीडियो और ऑडियो कैप्चर करना लेख पढ़ें.