মিডিয়া অভিক্ষেপ

অ্যান্ড্রয়েড ৫-এ (এপিআই লেভেল ২১) প্রবর্তিত android.media.projection এপিআই-গুলো আপনাকে ডিভাইসের ডিসপ্লের বিষয়বস্তু একটি মিডিয়া স্ট্রিম হিসেবে ধারণ করতে সক্ষম করে, যা আপনি প্লেব্যাক, রেকর্ড বা টিভি-র মতো অন্যান্য ডিভাইসে কাস্ট করতে পারেন।

অ্যান্ড্রয়েড ১৪ (এপিআই লেভেল ৩৪)-এ অ্যাপ স্ক্রিন শেয়ারিং চালু করা হয়েছে, যা ব্যবহারকারীদের উইন্ডোইং মোড নির্বিশেষে পুরো ডিভাইস স্ক্রিনের পরিবর্তে একটিমাত্র অ্যাপ উইন্ডো শেয়ার করার সুবিধা দেয়। অ্যাপ স্ক্রিন শেয়ারিং-এর মাধ্যমে শেয়ার করা ডিসপ্লেতে স্ট্যাটাস বার, নেভিগেশন বার, নোটিফিকেশন এবং অন্যান্য সিস্টেম ইউআই এলিমেন্ট অন্তর্ভুক্ত থাকে না—এমনকি যখন কোনো অ্যাপকে ফুল স্ক্রিনে ক্যাপচার করার জন্য এটি ব্যবহার করা হয়, তখনও। শুধুমাত্র নির্বাচিত অ্যাপটির বিষয়বস্তুই শেয়ার করা হয়।

অ্যাপ স্ক্রিন শেয়ারিং ব্যবহারকারীর গোপনীয়তা নিশ্চিত করে, তার কর্মদক্ষতা বাড়ায় এবং মাল্টিটাস্কিং উন্নত করে, কারণ এটি ব্যবহারকারীকে একাধিক অ্যাপ চালানোর সুযোগ দিলেও কন্টেন্ট শেয়ারিং শুধুমাত্র একটি অ্যাপের মধ্যেই সীমাবদ্ধ রাখে।

তিনটি প্রদর্শন উপস্থাপনা

একটি মিডিয়া প্রজেকশন কোনো ডিভাইসের ডিসপ্লে বা অ্যাপ উইন্ডোর বিষয়বস্তু ধারণ করে এবং তারপর সেই ধারণ করা ছবিটি একটি ভার্চুয়াল ডিসপ্লেতে প্রক্ষেপণ করে, যা ছবিটিকে একটি Surface রেন্ডার করে।

বাস্তব ডিভাইসের ডিসপ্লে ভার্চুয়াল ডিসপ্লেতে প্রক্ষেপিত হয়। ভার্চুয়াল ডিসপ্লের বিষয়বস্তু অ্যাপ্লিকেশন-প্রদত্ত 'সারফেস'-এ লেখা হয়।
চিত্র ১। বাস্তব ডিভাইসের স্ক্রিন বা অ্যাপ উইন্ডো ভার্চুয়াল ডিসপ্লেতে প্রক্ষেপিত। ভার্চুয়াল ডিসপ্লেটি অ্যাপ্লিকেশন-প্রদত্ত Surface -এ লেখা হয়েছে।

অ্যাপ্লিকেশনটি একটি MediaRecorder , SurfaceTexture , বা ImageReader এর মাধ্যমে Surface সরবরাহ করে, যা ক্যাপচার করা ডিসপ্লের বিষয়বস্তু গ্রহণ করে এবং আপনাকে রিয়েল টাইমে Surface রেন্ডার করা ছবিগুলো পরিচালনা করতে সক্ষম করে। আপনি ছবিগুলো রেকর্ডিং হিসেবে সংরক্ষণ করতে পারেন অথবা টিভি বা অন্য কোনো ডিভাইসে কাস্ট করতে পারেন।

আসল প্রদর্শন

একটি টোকেন সংগ্রহ করে মিডিয়া প্রজেকশন সেশন শুরু করুন, যা আপনার অ্যাপকে ডিভাইস ডিসপ্লে বা অ্যাপ উইন্ডোর বিষয়বস্তু ক্যাপচার করার ক্ষমতা প্রদান করে। টোকেনটি MediaProjection ক্লাসের একটি ইনস্ট্যান্স দ্বারা উপস্থাপিত হয়।

নতুন অ্যাক্টিভিটি শুরু করার সময় একটি MediaProjection ইনস্ট্যান্স তৈরি করতে MediaProjectionManager সিস্টেম সার্ভিসের getMediaProjection() মেথডটি ব্যবহার করুন। স্ক্রিন ক্যাপচার অপারেশন নির্দিষ্ট করতে createScreenCaptureIntent() মেথড থেকে একটি ইন্টেন্ট দিয়ে অ্যাক্টিভিটিটি শুরু করুন:

কোটলিন

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())

জাভা

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() কল করার মাধ্যমে তৈরি করেন:

কোটলিন

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

জাভা

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

width এবং height প্যারামিটারগুলো ভার্চুয়াল ডিসপ্লের মাত্রা নির্দিষ্ট করে। width এবং height-এর মান পেতে, Android 11-এ প্রবর্তিত WindowMetrics API (API লেভেল 30) ব্যবহার করুন। (বিস্তারিত জানতে, Media projection size অংশটি দেখুন।)

পৃষ্ঠতল

উপযুক্ত রেজোলিউশনে আউটপুট তৈরি করার জন্য মিডিয়া প্রজেকশন সারফেসের আকার নির্ধারণ করুন। টিভি বা কম্পিউটার মনিটরে স্ক্রিন কাস্টিং করার জন্য সারফেসটিকে বড় (নিম্ন রেজোলিউশন) এবং ডিভাইস ডিসপ্লে রেকর্ডিংয়ের জন্য ছোট (উচ্চ রেজোলিউশন) করুন।

অ্যান্ড্রয়েড ১২এল (এপিআই লেভেল ৩২) অনুযায়ী, সারফেসে ক্যাপচার করা কন্টেন্ট রেন্ডার করার সময়, সিস্টেম অ্যাস্পেক্ট রেশিও বজায় রেখে কন্টেন্টটিকে সুষমভাবে স্কেল করে, যাতে কন্টেন্টের উভয় মাত্রা (প্রস্থ এবং উচ্চতা) সারফেসের সংশ্লিষ্ট মাত্রার সমান বা তার চেয়ে কম হয়। এরপর ক্যাপচার করা কন্টেন্টটি সারফেসের কেন্দ্রে স্থাপন করা হয়।

অ্যান্ড্রয়েড ১২এল-এর স্কেলিং পদ্ধতি সঠিক অ্যাসপেক্ট রেশিও নিশ্চিত করার পাশাপাশি সারফেস ইমেজের আকার সর্বাধিক করে টেলিভিশন এবং অন্যান্য বড় ডিসপ্লেতে স্ক্রিন কাস্টিং উন্নত করে।

ফোরগ্রাউন্ড পরিষেবা অনুমতি

আপনার অ্যাপটি যদি অ্যান্ড্রয়েড ১৪ বা তার উচ্চতর সংস্করণকে টার্গেট করে, তাহলে অ্যাপ ম্যানিফেস্টে অবশ্যই 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 টোকেন শুধুমাত্র একবার ব্যবহার করতে হবে।

অ্যান্ড্রয়েড ১৪ বা তার পরবর্তী সংস্করণে, আপনার অ্যাপ নিম্নলিখিত কাজগুলোর কোনো একটি করলে createVirtualDisplay() ` মেথডটি একটি SecurityException থ্রো করে:

  • createScreenCaptureIntent() থেকে প্রাপ্ত একটি Intent ইনস্ট্যান্সকে getMediaProjection() ফাংশনে একাধিকবার পাস করা হলে
  • একই MediaProjection ইনস্ট্যান্সে createVirtualDisplay() একাধিকবার কল করা হলে

মিডিয়া প্রজেকশন আকার

মিডিয়া প্রজেকশন উইন্ডোয়িং মোড নির্বিশেষে ডিভাইসের সম্পূর্ণ ডিসপ্লে বা একটি অ্যাপ উইন্ডো ক্যাপচার করতে পারে।

প্রাথমিক আকার

ফুল-স্ক্রিন মিডিয়া প্রজেকশনের ক্ষেত্রে, আপনার অ্যাপকে ডিভাইসের স্ক্রিনের আকার নির্ধারণ করতে হয়। অ্যাপ স্ক্রিন শেয়ারিংয়ের ক্ষেত্রে, ব্যবহারকারী ক্যাপচার অঞ্চল নির্বাচন না করা পর্যন্ত আপনার অ্যাপ ক্যাপচার করা ডিসপ্লের আকার নির্ধারণ করতে পারে না। তাই, যেকোনো মিডিয়া প্রজেকশনের প্রাথমিক আকার হলো ডিভাইসের স্ক্রিনের আকার।

মিডিয়া প্রজেকশন হোস্ট অ্যাপটি মাল্টি-উইন্ডো মোডে থেকে ডিসপ্লের কেবল একটি অংশ দখল করলেও, ডিভাইস স্ক্রিনের জন্য একটি WindowMetrics অবজেক্ট রিটার্ন করতে প্ল্যাটফর্ম WindowManager getMaximumWindowMetrics() মেথডটি ব্যবহার করুন।

এপিআই লেভেল ১৪ পর্যন্ত সামঞ্জস্যের জন্য, জেটপ্যাক WindowManager লাইব্রেরি থেকে WindowMetricsCalculator computeMaximumWindowMetrics() মেথডটি ব্যবহার করুন।

ডিভাইস ডিসপ্লের প্রস্থ এবং উচ্চতা পেতে WindowMetrics getBounds() মেথডটি কল করুন।

আকারের পরিবর্তন

ডিভাইসটি ঘোরানো হলে অথবা অ্যাপ স্ক্রিন শেয়ারিং-এর সময় ব্যবহারকারী কোনো অ্যাপ উইন্ডোকে ক্যাপচার অঞ্চল হিসেবে নির্বাচন করলে মিডিয়া প্রজেকশনের আকার পরিবর্তিত হতে পারে। মিডিয়া প্রজেকশনটি সেট আপ করার সময় প্রাপ্ত সর্বোচ্চ উইন্ডো মেট্রিক্সের চেয়ে ক্যাপচার করা কন্টেন্টের আকার ভিন্ন হলে, মিডিয়া প্রজেকশনটি লেটারবক্সড হতে পারে।

যেকোনো ক্যাপচার করা অঞ্চলের জন্য এবং ডিভাইস ঘোরানোর পরেও মিডিয়া প্রজেকশন যেন ক্যাপচার করা কন্টেন্টের আকারের সাথে নিখুঁতভাবে মিলে যায়, তা নিশ্চিত করতে ক্যাপচারের আকার পরিবর্তন করার জন্য onCapturedContentResize() কলব্যাকটি ব্যবহার করুন। (আরও তথ্যের জন্য, পরবর্তী কাস্টমাইজেশন বিভাগটি দেখুন)।

কাস্টমাইজেশন

আপনার অ্যাপ নিম্নলিখিত MediaProjection.Callback API-গুলো ব্যবহার করে মিডিয়া প্রজেকশনের ইউজার এক্সপেরিয়েন্স কাস্টমাইজ করতে পারে:

  • onCapturedContentVisibilityChanged() : হোস্ট অ্যাপকে (যে অ্যাপটি মিডিয়া প্রজেকশন শুরু করেছে) শেয়ার করা কন্টেন্ট দেখানো বা লুকানোর ক্ষমতা দেয়।

    ক্যাপচার করা অঞ্চলটি ব্যবহারকারীর কাছে দৃশ্যমান কিনা, তার উপর ভিত্তি করে আপনার অ্যাপের UI কাস্টমাইজ করতে এই কলব্যাকটি ব্যবহার করুন। উদাহরণস্বরূপ, যদি আপনার অ্যাপটি ব্যবহারকারীর কাছে দৃশ্যমান হয় এবং অ্যাপের UI-এর মধ্যে ক্যাপচার করা কন্টেন্ট প্রদর্শন করে, এবং ক্যাপচার করা অ্যাপটিও ব্যবহারকারীর কাছে দৃশ্যমান হয় (যেমনটি এই কলব্যাকের মাধ্যমে নির্দেশিত), তাহলে ব্যবহারকারী একই কন্টেন্ট দুইবার দেখতে পাবেন। ক্যাপচার করা কন্টেন্টটি লুকানোর জন্য এবং আপনার অ্যাপে অন্যান্য কন্টেন্টের জন্য লেআউটের জায়গা খালি করতে আপনার অ্যাপের UI আপডেট করার জন্য এই কলব্যাকটি ব্যবহার করুন।

  • onCapturedContentResize() : ক্যাপচার করা ডিসপ্লে অঞ্চলের আকারের উপর ভিত্তি করে হোস্ট অ্যাপকে ভার্চুয়াল ডিসপ্লে এবং মিডিয়া প্রজেকশন Surface মিডিয়া প্রজেকশনের আকার পরিবর্তন করার ক্ষমতা দেয়।

    যখনই ক্যাপচার করা কন্টেন্টের—তা একটি একক অ্যাপ উইন্ডো হোক বা সম্পূর্ণ ডিভাইস ডিসপ্লে—আকার পরিবর্তন হয় (ডিভাইস ঘোরানোর কারণে বা ক্যাপচার করা অ্যাপটি ভিন্ন উইন্ডোইং মোডে প্রবেশ করার কারণে), তখনই এটি ট্রিগার হয়। ভার্চুয়াল ডিসপ্লে এবং সারফেস উভয়ের আকার পরিবর্তন করতে এই API ব্যবহার করুন, যাতে অ্যাস্পেক্ট রেশিও ক্যাপচার করা কন্টেন্টের সাথে মিলে যায় এবং ক্যাপচারটি লেটারবক্সড না হয়।

সম্পদ পুনরুদ্ধার

মিডিয়া প্রজেকশন সেশনটি বন্ধ হয়ে গেলে এবং অবৈধ হয়ে গেলে, সেই তথ্য পাওয়ার জন্য আপনার অ্যাপে MediaProjection onStop() কলব্যাকটি রেজিস্টার করা উচিত। সেশনটি বন্ধ হয়ে গেলে, আপনার অ্যাপের উচিত তার দখলে থাকা রিসোর্সগুলো, যেমন ভার্চুয়াল ডিসপ্লে এবং প্রজেকশন সারফেস, ছেড়ে দেওয়া। একটি বন্ধ মিডিয়া প্রজেকশন সেশন আর নতুন কোনো ভার্চুয়াল ডিসপ্লে তৈরি করতে পারে না, এমনকি যদি আপনার অ্যাপ সেই মিডিয়া প্রজেকশনের জন্য আগে কোনো ভার্চুয়াল ডিসপ্লে তৈরি না করেও থাকে।

মিডিয়া প্রজেকশন বন্ধ হয়ে গেলে সিস্টেমটি কলব্যাকটি চালু করে। এই বন্ধ হয়ে যাওয়া বিভিন্ন কারণে ঘটতে পারে, যেমন:

  • ব্যবহারকারী অ্যাপের UI অথবা সিস্টেমের মিডিয়া প্রজেকশন স্ট্যাটাস বার চিপ ব্যবহার করে সেশনটি বন্ধ করে দেয়।
  • স্ক্রিনটি লক করা হচ্ছে
  • আরেকটি মিডিয়া প্রজেকশন সেশন শুরু হয়
  • অ্যাপ প্রসেসটি বন্ধ করে দেওয়া হয়েছে

আপনার অ্যাপ যদি কলব্যাকটি রেজিস্টার না করে, তাহলে createVirtualDisplay() এর যেকোনো কলে IllegalStateException থ্রো হবে।

অপ্ট আউট

অ্যান্ড্রয়েড ১৪ বা তার উচ্চতর সংস্করণে অ্যাপ স্ক্রিন শেয়ারিং ডিফল্টরূপে সক্ষম করা থাকে। প্রতিটি মিডিয়া প্রজেকশন সেশনে ব্যবহারকারীরা একটি অ্যাপ উইন্ডো অথবা সম্পূর্ণ ডিসপ্লে শেয়ার করার বিকল্প পান।

আপনার অ্যাপ, createConfigForDefaultDisplay() কল থেকে প্রাপ্ত MediaProjectionConfig আর্গুমেন্ট সহ createScreenCaptureIntent(MediaProjectionConfig) মেথডটি কল করার মাধ্যমে অ্যাপ স্ক্রিন শেয়ারিং থেকে বিরত থাকতে পারে।

createConfigForUserChoice() কল থেকে প্রাপ্ত MediaProjectionConfig আর্গুমেন্ট সহ createScreenCaptureIntent(MediaProjectionConfig) কল করা ডিফল্ট আচরণের মতোই, অর্থাৎ, createScreenCaptureIntent() কল করার মতোই।

আকার পরিবর্তনযোগ্য অ্যাপ

আপনার মিডিয়া প্রজেকশন অ্যাপগুলিকে সর্বদা রিসাইজযোগ্য করুন ( resizeableActivity="true" )। রিসাইজযোগ্য অ্যাপগুলি ডিভাইস কনফিগারেশন পরিবর্তন এবং মাল্টি-উইন্ডো মোড সমর্থন করে ( মাল্টি-উইন্ডো সমর্থন দেখুন)।

যদি আপনার অ্যাপটি রিসাইজযোগ্য না হয়, তবে এটিকে অবশ্যই একটি উইন্ডো কনটেক্সট থেকে ডিসপ্লে বাউন্ডস কোয়েরি করতে হবে এবং অ্যাপটির জন্য উপলব্ধ সর্বোচ্চ ডিসপ্লে এলাকার WindowMetrics পুনরুদ্ধার করতে getMaximumWindowMetrics() ব্যবহার করতে হবে।

কোটলিন

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

জাভা

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

স্ট্যাটাস বার চিপ এবং অটো স্টপ

স্ক্রীন প্রজেকশন শোষণ ব্যক্তিগত ব্যবহারকারীর ডেটা যেমন আর্থিক তথ্য প্রকাশ করে কারণ ব্যবহারকারীরা বুঝতে পারে না যে তাদের ডিভাইসের স্ক্রিন ভাগ করা হচ্ছে।

Android 15 QPR1 বা উচ্চতর ডিভাইসে চলমান অ্যাপ্লিকেশানগুলির জন্য, একটি স্ট্যাটাস বার চিপ যা বড় এবং বিশিষ্ট যেকোন চলমান স্ক্রীন প্রজেকশনে ব্যবহারকারীদের সতর্ক করে। ব্যবহারকারীরা তাদের স্ক্রীন শেয়ার করা, কাস্ট করা বা রেকর্ড করা থেকে বন্ধ করতে চিপটিতে ট্যাপ করতে পারেন। এছাড়াও, ডিভাইসের স্ক্রিন লক হয়ে গেলে স্ক্রিন প্রজেকশন স্বয়ংক্রিয়ভাবে বন্ধ হয়ে যায়।

চিত্র ২. স্ক্রিন শেয়ারিং, কাস্টিং ও রেকর্ডিংয়ের জন্য স্ট্যাটাস বার চিপ।

স্ক্রিন শেয়ারিং, কাস্টিং বা রেকর্ডিং শুরু করে মিডিয়া প্রজেকশন স্ট্যাটাস বার চিপটির প্রাপ্যতা পরীক্ষা করুন। চিপটি স্ট্যাটাস বারে প্রদর্শিত হওয়া উচিত।

ব্যবহারকারীর স্ট্যাটাস বার চিপের সাথে ইন্টারঅ্যাকশনের মাধ্যমে অথবা লক স্ক্রিন সক্রিয় করার মাধ্যমে স্ক্রিন প্রজেকশন বন্ধ হয়ে গেলে আপনার অ্যাপ যেন রিসোর্স মুক্ত করে এবং এর UI আপডেট করে, তা নিশ্চিত করতে নিম্নলিখিতগুলি করুন:

  • MediaProjection.Callback এর একটি ইনস্ট্যান্স তৈরি করুন।

  • onStop() কলব্যাক মেথডটি প্রয়োগ করুন। স্ক্রিন প্রজেকশন বন্ধ হলে এই মেথডটি কল করা হয়। আপনার অ্যাপের দখলে থাকা যেকোনো রিসোর্স মুক্ত করুন এবং প্রয়োজন অনুযায়ী অ্যাপের UI আপডেট করুন।

কলব্যাকটি পরীক্ষা করতে, স্ক্রিন প্রজেকশন বন্ধ করার জন্য স্ট্যাটাস বার চিপটিতে ট্যাপ করুন অথবা ডিভাইসের স্ক্রিন লক করুন। যাচাই করুন যে onStop() মেথডটি কল করা হয়েছে এবং আপনার অ্যাপটি প্রত্যাশিতভাবে সাড়া দিচ্ছে।

অতিরিক্ত সম্পদ

মিডিয়া প্রজেকশন সম্পর্কে আরও তথ্যের জন্য, ভিডিও এবং অডিও প্লেব্যাক ক্যাপচার দেখুন।