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

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 एपीआई का इस्तेमाल करें. (ज़्यादा जानकारी के लिए, मीडिया प्रोजेक्शन का साइज़ सेक्शन देखें.)

Surface

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

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() से getMediaProjection() में एक से ज़्यादा बार, Intent इंस्टेंस को पास करता है
  • एक ही MediaProjection के लिए, createVirtualDisplay() को एक से ज़्यादा बार कॉल करता है

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

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

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

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

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

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

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

साइज़ में बदलाव

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

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

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

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

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

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

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

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

रिसॉर्स रिकवरी

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

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

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

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

ऑप्ट आउट करें

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

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

स्टेटस बार में दिखने वाला चिप और ऑटो स्टॉप

屏幕投影漏洞会泄露用户的私密数据(例如财务信息),因为用户不知道自己的设备屏幕正在共享。

对于搭载 Android 15 QPR1 或更高版本的设备上运行的应用,系统会在状态栏中显示一个醒目的大条状标签,以提醒用户正在进行的任何屏幕投影。用户可以点按该条状标签,停止共享、投放或录制其屏幕。此外,当设备屏幕锁定时,屏幕投影会自动停止。

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

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

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

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

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

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

अन्य संसाधन

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