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

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

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

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

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

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

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

ऐप्लिकेशन, Surface को MediaRecorder, SurfaceTexture या ImageReader की मदद से उपलब्ध कराता है. यह ऐप्लिकेशन, कैप्चर किए गए डिसप्ले के कॉन्टेंट का इस्तेमाल करता है. साथ ही, 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<Intent> 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 (एपीआई लेवल 35) QPR1 में, स्टेटस बार में एक नया चिप जोड़ा गया है. यह चिप बड़ा और साफ़ तौर पर दिखता है. इससे उपयोगकर्ताओं को स्क्रीन प्रोजेक्शन के दौरान सूचना मिलती है. उपयोगकर्ता अपनी स्क्रीन को शेयर, 'कास्ट' या रिकॉर्ड किए जाने से रोकने के लिए, चिप पर टैप कर सकते हैं.

Android 15 QPR1 और उसके बाद के वर्शन पर, डिवाइस की स्क्रीन लॉक होने पर स्क्रीन प्रोजेक्शन अपने-आप बंद हो जाता है.

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

अन्य संसाधन

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