ক্যামেরা API

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

দ্রষ্টব্য: এই পৃষ্ঠায় Camera ক্লাসটির বর্ণনা দেওয়া হয়েছে, যা এখন আর ব্যবহৃত হয় না। আমরা CameraX Jetpack লাইব্রেরি অথবা, বিশেষ কিছু ব্যবহারের ক্ষেত্রে, camera2 ক্লাসটি ব্যবহার করার পরামর্শ দিই। CameraX এবং Camera2 উভয়ই Android 5.0 (API লেভেল 21) এবং তার পরবর্তী সংস্করণগুলোতে কাজ করে।

বিবেচ্য বিষয়সমূহ

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

  • ক্যামেরার প্রয়োজনীয়তা - আপনার অ্যাপ্লিকেশনের জন্য ক্যামেরার ব্যবহার কি এতটাই গুরুত্বপূর্ণ যে আপনি ক্যামেরা নেই এমন কোনো ডিভাইসে আপনার অ্যাপ্লিকেশনটি ইনস্টল করতে চান না? যদি তাই হয়, তবে আপনার ম্যানিফেস্টে ক্যামেরার প্রয়োজনীয়তাটি ঘোষণা করা উচিত।
  • দ্রুত ছবি তোলা বা কাস্টমাইজড ক্যামেরা - আপনার অ্যাপ্লিকেশনটি কীভাবে ক্যামেরা ব্যবহার করবে? আপনি কি শুধু দ্রুত একটি ছবি বা ভিডিও ক্লিপ তুলতে আগ্রহী, নাকি আপনার অ্যাপ্লিকেশনটি ক্যামেরা ব্যবহারের একটি নতুন উপায় প্রদান করবে? দ্রুত ছবি বা ক্লিপ তোলার জন্য, ‘বিদ্যমান ক্যামেরা অ্যাপ ব্যবহার করা’ অংশটি বিবেচনা করুন। একটি কাস্টমাইজড ক্যামেরা ফিচার তৈরি করার জন্য, ‘একটি ক্যামেরা অ্যাপ তৈরি করা’ বিভাগটি দেখুন।
  • ফোরগ্রাউন্ড সার্ভিসের প্রয়োজনীয়তা - আপনার অ্যাপ কখন ক্যামেরা ব্যবহার করে? অ্যান্ড্রয়েড ৯ (এপিআই লেভেল ২৮) এবং এর পরবর্তী সংস্করণগুলোতে, ব্যাকগ্রাউন্ডে চলা অ্যাপগুলো ক্যামেরা অ্যাক্সেস করতে পারে না। তাই, আপনার অ্যাপ যখন ফোরগ্রাউন্ডে থাকবে অথবা কোনো ফোরগ্রাউন্ড সার্ভিসের অংশ হিসেবে ক্যামেরা ব্যবহার করা উচিত।
  • সংরক্ষণ - আপনার অ্যাপ্লিকেশন দ্বারা তৈরি ছবি বা ভিডিওগুলো কি শুধুমাত্র আপনার অ্যাপ্লিকেশনের জন্যই দৃশ্যমান থাকবে, নাকি গ্যালারি বা অন্যান্য মিডিয়া ও সোশ্যাল অ্যাপের মতো অন্য অ্যাপ্লিকেশনগুলো ব্যবহারের জন্য শেয়ার করা হবে? আপনি কি চান যে আপনার অ্যাপ্লিকেশনটি আনইনস্টল করা হলেও ছবি এবং ভিডিওগুলো উপলব্ধ থাকুক? এই বিকল্পগুলো কীভাবে প্রয়োগ করবেন তা দেখতে ‘মিডিয়া ফাইল সংরক্ষণ’ বিভাগটি দেখুন।

মৌলিক বিষয়গুলো

অ্যান্ড্রয়েড ফ্রেমওয়ার্ক android.hardware.camera2 API অথবা camera Intent মাধ্যমে ছবি ও ভিডিও তোলা সমর্থন করে। প্রাসঙ্গিক ক্লাসগুলো নিচে দেওয়া হলো:

android.hardware.camera2
এই প্যাকেজটি ডিভাইস ক্যামেরা নিয়ন্ত্রণের প্রধান এপিআই। ক্যামেরা অ্যাপ্লিকেশন তৈরির সময় ছবি বা ভিডিও তোলার জন্য এটি ব্যবহার করা যেতে পারে।
Camera
এই ক্লাসটি হলো ডিভাইস ক্যামেরা নিয়ন্ত্রণের জন্য ব্যবহৃত একটি পুরোনো ও অপ্রচলিত এপিআই।
SurfaceView
এই ক্লাসটি ব্যবহারকারীকে লাইভ ক্যামেরা প্রিভিউ দেখানোর জন্য ব্যবহৃত হয়।
MediaRecorder
এই ক্লাসটি ক্যামেরা থেকে ভিডিও রেকর্ড করতে ব্যবহৃত হয়।
Intent
সরাসরি Camera অবজেক্ট ব্যবহার না করেই ছবি বা ভিডিও ক্যাপচার করার জন্য MediaStore.ACTION_IMAGE_CAPTURE বা MediaStore.ACTION_VIDEO_CAPTURE ইন্টেন্ট অ্যাকশন টাইপ ব্যবহার করা যেতে পারে।

প্রকাশ্য ঘোষণা

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

  • ক্যামেরার অনুমতি - ডিভাইসের ক্যামেরা ব্যবহার করার জন্য আপনার অ্যাপ্লিকেশনকে অবশ্যই অনুমতি চাইতে হবে।
    <uses-permission android:name="android.permission.CAMERA" />

    দ্রষ্টব্য: আপনি যদি আগে থেকে বিদ্যমান কোনো ক্যামেরা অ্যাপ চালু করে ক্যামেরা ব্যবহার করেন, তাহলে আপনার অ্যাপ্লিকেশনটির এই অনুমতির জন্য অনুরোধ করার প্রয়োজন নেই।

  • ক্যামেরার বৈশিষ্ট্য - আপনার অ্যাপ্লিকেশনকে অবশ্যই ক্যামেরার বৈশিষ্ট্য ব্যবহারের কথাও ঘোষণা করতে হবে, যেমন:
    <uses-feature android:name="android.hardware.camera" />

    ক্যামেরার বৈশিষ্ট্যগুলির তালিকার জন্য, ম্যানিফেস্টের বৈশিষ্ট্য রেফারেন্স দেখুন।

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

    যদি আপনার অ্যাপ্লিকেশনটি সঠিক কার্যকারিতার জন্য ক্যামেরা বা ক্যামেরার কোনো বৈশিষ্ট্য ব্যবহার করতে পারে , কিন্তু সেটির প্রয়োজন না হয়, তবে ম্যানিফেস্টে android:required অ্যাট্রিবিউটটি অন্তর্ভুক্ত করে এবং সেটিকে false সেট করে তা উল্লেখ করা উচিত।

    <uses-feature android:name="android.hardware.camera" android:required="false" />
  • স্টোরেজ অনুমতি - আপনার অ্যাপ্লিকেশনটি ডিভাইসের এক্সটার্নাল স্টোরেজে (এসডি কার্ড) ছবি বা ভিডিও সংরক্ষণ করতে পারবে, যদি এটি অ্যান্ড্রয়েড ১০ (এপিআই লেভেল ২৯) বা তার নিম্নতর সংস্করণকে টার্গেট করে এবং ম্যানিফেস্টে নিম্নলিখিত বিষয়গুলো উল্লেখ করে।
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  • অডিও রেকর্ডিং অনুমতি - ভিডিও ক্যাপচারের সাথে অডিও রেকর্ড করার জন্য, আপনার অ্যাপ্লিকেশনটিকে অবশ্যই অডিও ক্যাপচারের অনুমতি চাইতে হবে।
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
  • অবস্থান অনুমতি - যদি আপনার অ্যাপ্লিকেশন ছবিগুলিতে GPS অবস্থানের তথ্য ট্যাগ করে, তাহলে আপনাকে অবশ্যই ACCESS_FINE_LOCATION অনুমতির জন্য অনুরোধ করতে হবে। মনে রাখবেন, যদি আপনার অ্যাপটি Android 5.0 (API লেভেল 21) বা তার উচ্চতর সংস্করণকে টার্গেট করে, তাহলে আপনাকে এটাও ঘোষণা করতে হবে যে আপনার অ্যাপটি ডিভাইসের GPS ব্যবহার করছে:

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    ...
    <!-- Needed only if your app targets Android 5.0 (API level 21) or higher. -->
    <uses-feature android:name="android.hardware.location.gps" />

    ব্যবহারকারীর অবস্থান জানার বিষয়ে আরও তথ্যের জন্য, অবস্থান কৌশলসমূহ দেখুন।

বিদ্যমান ক্যামেরা অ্যাপ ব্যবহার করে

অতিরিক্ত কোডের ঝামেলা ছাড়াই আপনার অ্যাপ্লিকেশনে ছবি বা ভিডিও তোলার সুবিধা চালু করার একটি দ্রুত উপায় হলো, একটি Intent ব্যবহার করে বিদ্যমান কোনো অ্যান্ড্রয়েড ক্যামেরা অ্যাপ্লিকেশনকে চালু করা। এর বিস্তারিত বিবরণ ‘সহজেই ছবি তোলা’ এবং ‘সহজেই ভিডিও রেকর্ড করা’ প্রশিক্ষণ পাঠগুলোতে বর্ণনা করা হয়েছে।

একটি ক্যামেরা অ্যাপ তৈরি করা

কিছু ডেভেলপারের এমন একটি ক্যামেরা ইউজার ইন্টারফেসের প্রয়োজন হতে পারে যা তাদের অ্যাপ্লিকেশনের চেহারার সাথে মানানসই অথবা বিশেষ বৈশিষ্ট্যসম্পন্ন। নিজের ছবি তোলার কোড লিখলে তা আপনার ব্যবহারকারীদের জন্য আরও আকর্ষণীয় অভিজ্ঞতা প্রদান করতে পারে।

দ্রষ্টব্য: নিম্নলিখিত নির্দেশিকাটি পুরোনো, অপ্রচলিত Camera এপিআই (Camera API)-এর জন্য। নতুন বা উন্নত ক্যামেরা অ্যাপ্লিকেশনের জন্য, অপেক্ষাকৃত নতুন android.hardware.camera2 এপিআই (API) ব্যবহার করার পরামর্শ দেওয়া হয়।

আপনার অ্যাপ্লিকেশনের জন্য একটি কাস্টম ক্যামেরা ইন্টারফেস তৈরি করার সাধারণ ধাপগুলো নিম্নরূপ:

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

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

সতর্কতা: আপনার অ্যাপ্লিকেশনটির ব্যবহার শেষ হলে Camera.release() কল করে Camera অবজেক্টটি রিলিজ করতে ভুলবেন না! যদি আপনার অ্যাপ্লিকেশনটি ক্যামেরাটি সঠিকভাবে রিলিজ না করে, তবে আপনার নিজের অ্যাপ্লিকেশন সহ ক্যামেরাটি অ্যাক্সেস করার পরবর্তী সমস্ত প্রচেষ্টা ব্যর্থ হবে এবং এর ফলে আপনার বা অন্যান্য অ্যাপ্লিকেশন বন্ধ হয়ে যেতে পারে।

ক্যামেরা হার্ডওয়্যার সনাক্তকরণ

যদি আপনার অ্যাপ্লিকেশনে ম্যানিফেস্ট ডিক্লারেশন ব্যবহার করে বিশেষভাবে ক্যামেরার প্রয়োজন না হয়, তবে রানটাইমে ক্যামেরা উপলব্ধ আছে কিনা তা পরীক্ষা করে দেখা উচিত। এই পরীক্ষাটি করার জন্য, PackageManager.hasSystemFeature() মেথডটি ব্যবহার করুন, যেমনটি নিচের উদাহরণ কোডে দেখানো হয়েছে:

কোটলিন

/** Check if this device has a camera */
private fun checkCameraHardware(context: Context): Boolean {
    if (context.packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
        // this device has a camera
        return true
    } else {
        // no camera on this device
        return false
    }
}

জাভা

/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
    if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
        // this device has a camera
        return true;
    } else {
        // no camera on this device
        return false;
    }
}

অ্যান্ড্রয়েড ডিভাইসগুলিতে একাধিক ক্যামেরা থাকতে পারে, যেমন ছবি তোলার জন্য একটি পেছনের ক্যামেরা এবং ভিডিও কলের জন্য একটি সামনের ক্যামেরা। অ্যান্ড্রয়েড ২.৩ (এপিআই লেভেল ৯) এবং এর পরবর্তী সংস্করণগুলিতে Camera.getNumberOfCameras() মেথড ব্যবহার করে ডিভাইসে উপলব্ধ ক্যামেরার সংখ্যা জানা যায়।

ক্যামেরা অ্যাক্সেস করা

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

প্রাথমিক ক্যামেরা অ্যাক্সেস করতে, Camera.open() মেথডটি ব্যবহার করুন এবং যেকোনো এক্সেপশন ক্যাচ করতে ভুলবেন না, যেমনটি নিচের কোডে দেখানো হয়েছে:

কোটলিন

/** A safe way to get an instance of the Camera object. */
fun getCameraInstance(): Camera? {
    return try {
        Camera.open() // attempt to get a Camera instance
    } catch (e: Exception) {
        // Camera is not available (in use or does not exist)
        null // returns null if camera is unavailable
    }
}

জাভা

/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(){
    Camera c = null;
    try {
        c = Camera.open(); // attempt to get a Camera instance
    }
    catch (Exception e){
        // Camera is not available (in use or does not exist)
    }
    return c; // returns null if camera is unavailable
}

সতর্কতা: Camera.open() ব্যবহার করার সময় সর্বদা এক্সেপশন পরীক্ষা করুন। ক্যামেরা ব্যবহৃত হলে বা বিদ্যমান না থাকলে এক্সেপশন পরীক্ষা করতে ব্যর্থ হলে, সিস্টেম আপনার অ্যাপ্লিকেশনটি বন্ধ করে দেবে।

অ্যান্ড্রয়েড ২.৩ (এপিআই লেভেল ৯) বা তার উচ্চতর সংস্করণে চালিত ডিভাইসগুলিতে, আপনি Camera.open(int) ব্যবহার করে নির্দিষ্ট ক্যামেরা অ্যাক্সেস করতে পারেন। উপরের উদাহরণ কোডটি একাধিক ক্যামেরাযুক্ত একটি ডিভাইসের প্রথম, পেছনের ক্যামেরাটি অ্যাক্সেস করবে।

ক্যামেরার বৈশিষ্ট্য পরীক্ষা করা হচ্ছে

একবার কোনো ক্যামেরার অ্যাক্সেস পেয়ে গেলে, আপনি Camera.getParameters() মেথড ব্যবহার করে এবং রিটার্ন করা Camera.Parameters অবজেক্টে সমর্থিত ক্যাপাবিলিটিগুলো পরীক্ষা করে এর সক্ষমতা সম্পর্কে আরও তথ্য পেতে পারেন। API লেভেল 9 বা তার উচ্চতর সংস্করণ ব্যবহার করার সময়, ক্যামেরাটি ডিভাইসের সামনে না পিছনে আছে এবং ছবির ওরিয়েন্টেশন কী, তা নির্ধারণ করতে Camera.getCameraInfo() ব্যবহার করুন।

একটি প্রিভিউ ক্লাস তৈরি করা

ব্যবহারকারীদের কার্যকরভাবে ছবি বা ভিডিও তোলার জন্য, ডিভাইস ক্যামেরা যা দেখছে তা তাদের দেখতে সক্ষম হতে হবে। একটি ক্যামেরা প্রিভিউ ক্লাস হলো এমন একটি SurfaceView যা ক্যামেরা থেকে আসা লাইভ ইমেজ ডেটা প্রদর্শন করতে পারে, যাতে ব্যবহারকারীরা একটি ছবি বা ভিডিও ফ্রেম করে তুলতে পারেন।

নিম্নলিখিত উদাহরণ কোডটি দেখায় কিভাবে একটি মৌলিক ক্যামেরা প্রিভিউ ক্লাস তৈরি করতে হয় যা একটি View লেআউটে অন্তর্ভুক্ত করা যেতে পারে। এই ক্লাসটি SurfaceHolder.Callback ইমপ্লিমেন্ট করে, যাতে ভিউ তৈরি এবং ধ্বংস করার জন্য কলব্যাক ইভেন্টগুলো ক্যাপচার করা যায়, যা ক্যামেরা প্রিভিউ ইনপুট অ্যাসাইন করার জন্য প্রয়োজন।

কোটলিন

/** A basic Camera preview class */
class CameraPreview(
        context: Context,
        private val mCamera: Camera
) : SurfaceView(context), SurfaceHolder.Callback {

    private val mHolder: SurfaceHolder = holder.apply {
        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        addCallback(this@CameraPreview)
        // deprecated setting, but required on Android versions prior to 3.0
        setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS)
    }

    override fun surfaceCreated(holder: SurfaceHolder) {
        // The Surface has been created, now tell the camera where to draw the preview.
        mCamera.apply {
            try {
                setPreviewDisplay(holder)
                startPreview()
            } catch (e: IOException) {
                Log.d(TAG, "Error setting camera preview: ${e.message}")
            }
        }
    }

    override fun surfaceDestroyed(holder: SurfaceHolder) {
        // empty. Take care of releasing the Camera preview in your activity.
    }

    override fun surfaceChanged(holder: SurfaceHolder, format: Int, w: Int, h: Int) {
        // If your preview can change or rotate, take care of those events here.
        // Make sure to stop the preview before resizing or reformatting it.
        if (mHolder.surface == null) {
            // preview surface does not exist
            return
        }

        // stop preview before making changes
        try {
            mCamera.stopPreview()
        } catch (e: Exception) {
            // ignore: tried to stop a non-existent preview
        }

        // set preview size and make any resize, rotate or
        // reformatting changes here

        // start preview with new settings
        mCamera.apply {
            try {
                setPreviewDisplay(mHolder)
                startPreview()
            } catch (e: Exception) {
                Log.d(TAG, "Error starting camera preview: ${e.message}")
            }
        }
    }
}

জাভা

/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder mHolder;
    private Camera mCamera;

    public CameraPreview(Context context, Camera camera) {
        super(context);
        mCamera = camera;

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, now tell the camera where to draw the preview.
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {
            Log.d(TAG, "Error setting camera preview: " + e.getMessage());
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        // empty. Take care of releasing the Camera preview in your activity.
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // If your preview can change or rotate, take care of those events here.
        // Make sure to stop the preview before resizing or reformatting it.

        if (mHolder.getSurface() == null){
          // preview surface does not exist
          return;
        }

        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e){
          // ignore: tried to stop a non-existent preview
        }

        // set preview size and make any resize, rotate or
        // reformatting changes here

        // start preview with new settings
        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();

        } catch (Exception e){
            Log.d(TAG, "Error starting camera preview: " + e.getMessage());
        }
    }
}

আপনি যদি আপনার ক্যামেরা প্রিভিউয়ের জন্য একটি নির্দিষ্ট আকার নির্ধারণ করতে চান, তবে উপরের মন্তব্যগুলিতে উল্লিখিত নির্দেশ অনুযায়ী surfaceChanged() মেথডে এটি সেট করুন। প্রিভিউ সাইজ সেট করার সময়, আপনাকে অবশ্যই getSupportedPreviewSizes() থেকে প্রাপ্ত মান ব্যবহার করতে হবেsetPreviewSize() মেথডে যথেচ্ছভাবে কোনো মান সেট করবেন না

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

একটি লেআউটে প্রিভিউ স্থাপন করা

পূর্ববর্তী বিভাগে দেখানো উদাহরণের মতো একটি ক্যামেরা প্রিভিউ ক্লাসকে, ছবি বা ভিডিও তোলার জন্য অন্যান্য ইউজার ইন্টারফেস কন্ট্রোলগুলোর সাথে একটি অ্যাক্টিভিটির লেআউটে স্থাপন করতে হবে। এই বিভাগে দেখানো হয়েছে কীভাবে প্রিভিউয়ের জন্য একটি বেসিক লেআউট এবং অ্যাক্টিভিটি তৈরি করতে হয়।

নিম্নলিখিত লেআউট কোডটি একটি অত্যন্ত সাধারণ ভিউ প্রদান করে যা ক্যামেরা প্রিভিউ প্রদর্শনের জন্য ব্যবহার করা যেতে পারে। এই উদাহরণে, FrameLayout এলিমেন্টটি ক্যামেরা প্রিভিউ ক্লাসের কন্টেইনার হিসেবে ব্যবহৃত হয়েছে। এই লেআউট টাইপটি ব্যবহার করা হয় যাতে লাইভ ক্যামেরা প্রিভিউ ছবিগুলোর উপর অতিরিক্ত ছবির তথ্য বা কন্ট্রোল ওভারলে করা যায়।

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
  <FrameLayout
    android:id="@+id/camera_preview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_weight="1"
    />

  <Button
    android:id="@+id/button_capture"
    android:text="Capture"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    />
</LinearLayout>

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

<activity android:name=".CameraActivity"
          android:label="@string/app_name"

          android:screenOrientation="landscape">
          <!-- configure this activity to use landscape orientation -->

          <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

দ্রষ্টব্য: ক্যামেরা প্রিভিউকে ল্যান্ডস্কেপ মোডে থাকতে হবে এমন কোনো বাধ্যবাধকতা নেই। অ্যান্ড্রয়েড ২.২ (এপিআই লেভেল ৮) থেকে, আপনি প্রিভিউ ইমেজের রোটেশন সেট করার জন্য setDisplayOrientation() মেথডটি ব্যবহার করতে পারেন। ব্যবহারকারী যখন ফোনের দিক পরিবর্তন করেন, তখন প্রিভিউয়ের ওরিয়েন্টেশন পরিবর্তন করার জন্য, আপনার প্রিভিউ ক্লাসের surfaceChanged() মেথডের মধ্যে, প্রথমে Camera.stopPreview() দিয়ে প্রিভিউটি বন্ধ করুন, ওরিয়েন্টেশন পরিবর্তন করুন এবং তারপর Camera.startPreview() দিয়ে প্রিভিউটি আবার চালু করুন।

আপনার ক্যামেরা ভিউ-এর অ্যাক্টিভিটিতে, উপরের উদাহরণে দেখানো FrameLayout এলিমেন্টে আপনার প্রিভিউ ক্লাসটি যোগ করুন। আপনার ক্যামেরা অ্যাক্টিভিটিকে অবশ্যই এটিও নিশ্চিত করতে হবে যে, ক্যামেরা পজ বা শাট ডাউন করার সময় যেন তা রিলিজ হয়ে যায়। নিচের উদাহরণটি দেখায় কিভাবে একটি ক্যামেরা অ্যাক্টিভিটি পরিবর্তন করে 'একটি প্রিভিউ ক্লাস তৈরি করা' অংশে দেখানো প্রিভিউ ক্লাসটি সংযুক্ত করা যায়।

কোটলিন

class CameraActivity : Activity() {

    private var mCamera: Camera? = null
    private var mPreview: CameraPreview? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Create an instance of Camera
        mCamera = getCameraInstance()

        mPreview = mCamera?.let {
            // Create our Preview view
            CameraPreview(this, it)
        }

        // Set the Preview view as the content of our activity.
        mPreview?.also {
            val preview: FrameLayout = findViewById(R.id.camera_preview)
            preview.addView(it)
        }
    }
}

জাভা

public class CameraActivity extends Activity {

    private Camera mCamera;
    private CameraPreview mPreview;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // Create an instance of Camera
        mCamera = getCameraInstance();

        // Create our Preview view and set it as the content of our activity.
        mPreview = new CameraPreview(this, mCamera);
        FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
        preview.addView(mPreview);
    }
}

দ্রষ্টব্য: উপরের উদাহরণে getCameraInstance() মেথডটি "ক্যামেরা অ্যাক্সেস করা" অংশে দেখানো উদাহরণ মেথডটিকে নির্দেশ করে।

ছবি তোলা

একবার আপনি একটি প্রিভিউ ক্লাস এবং এটি প্রদর্শনের জন্য একটি ভিউ লেআউট তৈরি করে ফেললে, আপনার অ্যাপ্লিকেশন দিয়ে ছবি তোলা শুরু করার জন্য আপনি প্রস্তুত। আপনার অ্যাপ্লিকেশন কোডে, ব্যবহারকারীর কোনো কাজের প্রতিক্রিয়ায় ছবি তোলার জন্য ইউজার ইন্টারফেস কন্ট্রোলগুলোর জন্য অবশ্যই লিসেনার সেট আপ করতে হবে।

একটি ছবি পুনরুদ্ধার করতে, Camera.takePicture() মেথডটি ব্যবহার করুন। এই মেথডটি তিনটি প্যারামিটার গ্রহণ করে, যেগুলো ক্যামেরা থেকে ডেটা গ্রহণ করে। JPEG ফরম্যাটে ডেটা গ্রহণ করার জন্য, আপনাকে অবশ্যই ছবির ডেটা গ্রহণ করতে এবং একটি ফাইলে লিখতে Camera.PictureCallback ইন্টারফেসটি ইমপ্লিমেন্ট করতে হবে। নিচের কোডটি ক্যামেরা থেকে প্রাপ্ত একটি ছবি সংরক্ষণ করার জন্য Camera.PictureCallback ইন্টারফেসের একটি সাধারণ ইমপ্লিমেন্টেশন দেখাচ্ছে।

কোটলিন

private val mPicture = Camera.PictureCallback { data, _ ->
    val pictureFile: File = getOutputMediaFile(MEDIA_TYPE_IMAGE) ?: run {
        Log.d(TAG, ("Error creating media file, check storage permissions"))
        return@PictureCallback
    }

    try {
        val fos = FileOutputStream(pictureFile)
        fos.write(data)
        fos.close()
    } catch (e: FileNotFoundException) {
        Log.d(TAG, "File not found: ${e.message}")
    } catch (e: IOException) {
        Log.d(TAG, "Error accessing file: ${e.message}")
    }
}

জাভা

private PictureCallback mPicture = new PictureCallback() {

    @Override
    public void onPictureTaken(byte[] data, Camera camera) {

        File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
        if (pictureFile == null){
            Log.d(TAG, "Error creating media file, check storage permissions");
            return;
        }

        try {
            FileOutputStream fos = new FileOutputStream(pictureFile);
            fos.write(data);
            fos.close();
        } catch (FileNotFoundException e) {
            Log.d(TAG, "File not found: " + e.getMessage());
        } catch (IOException e) {
            Log.d(TAG, "Error accessing file: " + e.getMessage());
        }
    }
};

Camera.takePicture() মেথডটি কল করে ছবি তোলার প্রক্রিয়াটি শুরু করুন। নিচের উদাহরণ কোডটিতে দেখানো হয়েছে কিভাবে একটি বাটনের View.OnClickListener থেকে এই মেথডটি কল করতে হয়।

কোটলিন

val captureButton: Button = findViewById(R.id.button_capture)
captureButton.setOnClickListener {
    // get an image from the camera
    mCamera?.takePicture(null, null, picture)
}

জাভা

// Add a listener to the Capture button
Button captureButton = (Button) findViewById(R.id.button_capture);
captureButton.setOnClickListener(
    new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // get an image from the camera
            mCamera.takePicture(null, null, picture);
        }
    }
);

দ্রষ্টব্য: নিম্নলিখিত উদাহরণে mPicture মেম্বারটি উপরের উদাহরণ কোডটিকে নির্দেশ করে।

সতর্কতা: আপনার অ্যাপ্লিকেশনটির ব্যবহার শেষ হয়ে গেলে Camera.release() কল করে Camera অবজেক্টটি রিলিজ করতে ভুলবেন না! কীভাবে ক্যামেরা রিলিজ করতে হয় সে সম্পর্কে জানতে, “ক্যামেরা রিলিজ করা” দেখুন।

ভিডিও ধারণ করা

অ্যান্ড্রয়েড ফ্রেমওয়ার্ক ব্যবহার করে ভিডিও ধারণ করার জন্য Camera অবজেক্টের সতর্ক ব্যবস্থাপনা এবং MediaRecorder ক্লাসের সাথে সমন্বয় প্রয়োজন। Camera দিয়ে ভিডিও রেকর্ড করার সময়, Camera.lock() এবং Camera.unlock() কলগুলোর পাশাপাশি, MediaRecorder ক্যামেরা হার্ডওয়্যারে অ্যাক্সেস দেওয়ার জন্য আপনাকে Camera.lock Camera.open() ) এবং Camera.release() কলগুলোও পরিচালনা করতে হবে।

দ্রষ্টব্য: অ্যান্ড্রয়েড ৪.০ (এপিআই লেভেল ১৪) থেকে Camera.lock() এবং Camera.unlock() কলগুলো আপনার জন্য স্বয়ংক্রিয়ভাবে পরিচালিত হয়।

ডিভাইসের ক্যামেরা দিয়ে ছবি তোলার থেকে ভিন্ন, ভিডিও ধারণ করার জন্য একটি অত্যন্ত নির্দিষ্ট কার্যক্রম প্রয়োজন। আপনার অ্যাপ্লিকেশনের মাধ্যমে সফলভাবে ভিডিও প্রস্তুত ও ধারণ করার জন্য আপনাকে অবশ্যই একটি নির্দিষ্ট কার্যসম্পাদন ক্রম অনুসরণ করতে হবে, যা নিচে বিস্তারিতভাবে বর্ণনা করা হলো।

  1. ক্যামেরা খুলুন - ক্যামেরা অবজেক্টের একটি ইনস্ট্যান্স পেতে Camera.open() ব্যবহার করুন।
  2. কানেক্ট প্রিভিউ - Camera.setPreviewDisplay() ব্যবহার করে একটি SurfaceView ক্যামেরার সাথে সংযুক্ত করে একটি লাইভ ক্যামেরা ইমেজ প্রিভিউ প্রস্তুত করুন।
  3. প্রিভিউ শুরু করুন - ক্যামেরার লাইভ ছবি দেখানো শুরু করতে Camera.startPreview() কল করুন।
  4. ভিডিও রেকর্ডিং শুরু করুন - সফলভাবে ভিডিও রেকর্ড করার জন্য নিম্নলিখিত ধাপগুলো অবশ্যই সম্পন্ন করতে হবে:
    1. ক্যামেরা আনলক করুন - MediaRecorder ব্যবহারের জন্য Camera.unlock() কল করে ক্যামেরাটি আনলক করুন।
    2. MediaRecorder কনফিগার করুন - নিম্নলিখিত MediaRecorder মেথডগুলো এই ক্রমে কল করুন। আরও তথ্যের জন্য, MediaRecorder রেফারেন্স ডকুমেন্টেশন দেখুন।
      1. setCamera() - ভিডিও ধারণের জন্য ব্যবহৃত ক্যামেরা সেট করুন, আপনার অ্যাপ্লিকেশনের Camera এর বর্তমান ইনস্ট্যান্সটি ব্যবহার করুন।
      2. setAudioSource() - অডিও উৎস নির্ধারণ করতে MediaRecorder.AudioSource.CAMCORDER ব্যবহার করুন।
      3. setVideoSource() - ভিডিওর উৎস নির্ধারণ করতে MediaRecorder.VideoSource.CAMERA ব্যবহার করুন।
      4. ভিডিও আউটপুট ফরম্যাট এবং এনকোডিং সেট করুন। অ্যান্ড্রয়েড ২.২ (এপিআই লেভেল ৮) এবং তার পরবর্তী সংস্করণগুলোর জন্য, MediaRecorder.setProfile মেথডটি ব্যবহার করুন এবং CamcorderProfile.get() ব্যবহার করে একটি প্রোফাইল ইনস্ট্যান্স নিন। অ্যান্ড্রয়েড ২.২-এর পূর্ববর্তী সংস্করণগুলোর জন্য, আপনাকে অবশ্যই ভিডিও আউটপুট ফরম্যাট এবং এনকোডিং প্যারামিটারগুলো সেট করতে হবে:
        1. setOutputFormat() - আউটপুট ফরম্যাট সেট করুন, ডিফল্ট সেটিং অথবা MediaRecorder.OutputFormat.MPEG_4 উল্লেখ করুন।
        2. setAudioEncoder() - সাউন্ড এনকোডিংয়ের ধরন সেট করুন, ডিফল্ট সেটিং অথবা MediaRecorder.AudioEncoder.AMR_NB উল্লেখ করুন।
        3. setVideoEncoder() - ভিডিও এনকোডিংয়ের ধরন নির্ধারণ করুন, ডিফল্ট সেটিং অথবা MediaRecorder.VideoEncoder.MPEG_4_SP উল্লেখ করুন।
      5. setOutputFile() - আউটপুট ফাইল সেট করুন, এর জন্য "মিডিয়া ফাইল সংরক্ষণ" অংশের উদাহরণ পদ্ধতি থেকে getOutputMediaFile(MEDIA_TYPE_VIDEO).toString() ব্যবহার করুন।
      6. setPreviewDisplay() - আপনার অ্যাপ্লিকেশনের জন্য SurfaceView প্রিভিউ লেআউট এলিমেন্টটি নির্দিষ্ট করুন। Connect Preview-এর জন্য আপনি যে অবজেক্টটি নির্দিষ্ট করেছিলেন, সেটিই ব্যবহার করুন।

      সতর্কতা: আপনাকে অবশ্যই এই MediaRecorder কনফিগারেশন মেথডগুলো এই ক্রমেই কল করতে হবে, অন্যথায় আপনার অ্যাপ্লিকেশনে ত্রুটি দেখা দেবে এবং রেকর্ডিং ব্যর্থ হবে।

    3. মিডিয়া রেকর্ডার প্রস্তুত করুন - MediaRecorder.prepare() কল করে প্রদত্ত কনফিগারেশন সেটিংস দিয়ে MediaRecorder প্রস্তুত করুন।
    4. মিডিয়া রেকর্ডার চালু করুন - MediaRecorder.start() কল করে ভিডিও রেকর্ডিং শুরু করুন।
  5. ভিডিও রেকর্ডিং বন্ধ করুন - একটি ভিডিও রেকর্ডিং সফলভাবে সম্পন্ন করতে, নিম্নলিখিত মেথডগুলো ক্রমানুসারে কল করুন:
    1. মিডিয়া রেকর্ডার বন্ধ করুন - MediaRecorder.stop() কল করে ভিডিও রেকর্ডিং বন্ধ করুন।
    2. মিডিয়া রেকর্ডার রিসেট করুন - ঐচ্ছিকভাবে, MediaRecorder.reset() কল করে রেকর্ডার থেকে কনফিগারেশন সেটিংস মুছে ফেলুন।
    3. MediaRecorder রিলিজ করতে MediaRecorder MediaRecorder.release() কল করুন।
    4. ক্যামেরা লক করুন - Camera.lock() কল করে ক্যামেরাটি লক করুন, যাতে ভবিষ্যতের MediaRecorder সেশনগুলো এটি ব্যবহার করতে পারে। Android 4.0 (API লেভেল 14) থেকে, MediaRecorder.prepare() কলটি ব্যর্থ না হলে এই কলটির প্রয়োজন হয় না।
  6. প্রিভিউ বন্ধ করুন - আপনার অ্যাক্টিভিটির ক্যামেরা ব্যবহার করা শেষ হলে, Camera.stopPreview() ব্যবহার করে প্রিভিউ বন্ধ করুন।
  7. ক্যামেরা রিলিজ করুন - Camera.release() কল করে ক্যামেরাটি রিলিজ করুন, যাতে অন্যান্য অ্যাপ্লিকেশন এটি ব্যবহার করতে পারে।

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

পরামর্শ: যদি আপনার অ্যাপ্লিকেশনটি সাধারণত ভিডিও রেকর্ডিংয়ের জন্য ব্যবহৃত হয়, তাহলে প্রিভিউ শুরু করার আগে setRecordingHint(boolean) কে true তে সেট করুন। এই সেটিংটি রেকর্ডিং শুরু হওয়ার সময় কমাতে সাহায্য করতে পারে।

মিডিয়া রেকর্ডার কনফিগার করা

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

কোটলিন

private fun prepareVideoRecorder(): Boolean {
    mediaRecorder = MediaRecorder()

    mCamera?.let { camera ->
        // Step 1: Unlock and set camera to MediaRecorder
        camera?.unlock()

        mediaRecorder?.run {
            setCamera(camera)

            // Step 2: Set sources
            setAudioSource(MediaRecorder.AudioSource.CAMCORDER)
            setVideoSource(MediaRecorder.VideoSource.CAMERA)

            // Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
            setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH))

            // Step 4: Set output file
            setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString())

            // Step 5: Set the preview output
            setPreviewDisplay(mPreview?.holder?.surface)

            setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
            setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT)
            setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT)


            // Step 6: Prepare configured MediaRecorder
            return try {
                prepare()
                true
            } catch (e: IllegalStateException) {
                Log.d(TAG, "IllegalStateException preparing MediaRecorder: ${e.message}")
                releaseMediaRecorder()
                false
            } catch (e: IOException) {
                Log.d(TAG, "IOException preparing MediaRecorder: ${e.message}")
                releaseMediaRecorder()
                false
            }
        }

    }
    return false
}

জাভা

private boolean prepareVideoRecorder(){

    mCamera = getCameraInstance();
    mediaRecorder = new MediaRecorder();

    // Step 1: Unlock and set camera to MediaRecorder
    mCamera.unlock();
    mediaRecorder.setCamera(mCamera);

    // Step 2: Set sources
    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
    mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

    // Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
    mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));

    // Step 4: Set output file
    mediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString());

    // Step 5: Set the preview output
    mediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());

    // Step 6: Prepare configured MediaRecorder
    try {
        mediaRecorder.prepare();
    } catch (IllegalStateException e) {
        Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
        releaseMediaRecorder();
        return false;
    } catch (IOException e) {
        Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
        releaseMediaRecorder();
        return false;
    }
    return true;
}

অ্যান্ড্রয়েড ২.২ (এপিআই লেভেল ৮)-এর আগে, CamcorderProfile ব্যবহার না করে আপনাকে আউটপুট ফরম্যাট এবং এনকোডিং ফরম্যাট প্যারামিটারগুলো সরাসরি সেট করতে হতো। এই পদ্ধতিটি নিম্নলিখিত কোডে দেখানো হয়েছে:

কোটলিন

    // Step 3: Set output format and encoding (for versions prior to API Level 8)
    mediaRecorder?.apply {
        setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
        setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT)
        setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT)
    }

জাভা

    // Step 3: Set output format and encoding (for versions prior to API Level 8)
    mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
    mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);

MediaRecorder জন্য নিম্নলিখিত ভিডিও রেকর্ডিং প্যারামিটারগুলো ডিফল্ট সেটিংসে দেওয়া আছে, তবে আপনি আপনার অ্যাপ্লিকেশনের জন্য এই সেটিংসগুলো পরিবর্তন করতে চাইতে পারেন:

মিডিয়া রেকর্ডার চালু এবং বন্ধ করা

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

  1. Camera.unlock() ব্যবহার করে ক্যামেরা আনলক করুন।
  2. উপরের কোড উদাহরণে দেখানো অনুযায়ী MediaRecorder কনফিগার করুন।
  3. MediaRecorder.start() ব্যবহার করে রেকর্ডিং শুরু করুন
  4. ভিডিওটি রেকর্ড করুন
  5. MediaRecorder.stop() ব্যবহার করে রেকর্ডিং বন্ধ করুন।
  6. MediaRecorder.release() ব্যবহার করে মিডিয়া রেকর্ডারটি রিলিজ করুন।
  7. Camera.lock() ব্যবহার করে ক্যামেরা লক করুন।

নিম্নলিখিত উদাহরণ কোডটিতে দেখানো হয়েছে কিভাবে ক্যামেরা এবং MediaRecorder ক্লাস ব্যবহার করে একটি বাটনের মাধ্যমে সঠিকভাবে ভিডিও রেকর্ডিং শুরু ও বন্ধ করা যায়।

দ্রষ্টব্য: ভিডিও রেকর্ডিং সম্পন্ন করার পর ক্যামেরাটি ছেড়ে দেবেন না, অন্যথায় আপনার প্রিভিউ বন্ধ হয়ে যাবে।

কোটলিন

var isRecording = false
val captureButton: Button = findViewById(R.id.button_capture)
captureButton.setOnClickListener {
    if (isRecording) {
        // stop recording and release camera
        mediaRecorder?.stop() // stop the recording
        releaseMediaRecorder() // release the MediaRecorder object
        mCamera?.lock() // take camera access back from MediaRecorder

        // inform the user that recording has stopped
        setCaptureButtonText("Capture")
        isRecording = false
    } else {
        // initialize video camera
        if (prepareVideoRecorder()) {
            // Camera is available and unlocked, MediaRecorder is prepared,
            // now you can start recording
            mediaRecorder?.start()

            // inform the user that recording has started
            setCaptureButtonText("Stop")
            isRecording = true
        } else {
            // prepare didn't work, release the camera
            releaseMediaRecorder()
            // inform user
        }
    }
}

জাভা

private boolean isRecording = false;

// Add a listener to the Capture button
Button captureButton = (Button) findViewById(id.button_capture);
captureButton.setOnClickListener(
    new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (isRecording) {
                // stop recording and release camera
                mediaRecorder.stop();  // stop the recording
                releaseMediaRecorder(); // release the MediaRecorder object
                mCamera.lock();         // take camera access back from MediaRecorder

                // inform the user that recording has stopped
                setCaptureButtonText("Capture");
                isRecording = false;
            } else {
                // initialize video camera
                if (prepareVideoRecorder()) {
                    // Camera is available and unlocked, MediaRecorder is prepared,
                    // now you can start recording
                    mediaRecorder.start();

                    // inform the user that recording has started
                    setCaptureButtonText("Stop");
                    isRecording = true;
                } else {
                    // prepare didn't work, release the camera
                    releaseMediaRecorder();
                    // inform user
                }
            }
        }
    }
);

দ্রষ্টব্য: উপরের উদাহরণে, prepareVideoRecorder() মেথডটি "মিডিয়া রেকর্ডার কনফিগার করা" অংশে দেখানো উদাহরণ কোডকে নির্দেশ করে। এই মেথডটি ক্যামেরা লক করা, MediaRecorder ইনস্ট্যান্স কনফিগার করা এবং প্রস্তুত করার কাজ করে।

ক্যামেরা ছেড়ে দেওয়া

ক্যামেরা হলো একটি রিসোর্স যা ডিভাইসের অ্যাপ্লিকেশনগুলো দ্বারা শেয়ার করা হয়। Camera এর একটি ইনস্ট্যান্স পাওয়ার পর আপনার অ্যাপ্লিকেশন ক্যামেরাটি ব্যবহার করতে পারে, এবং যখন আপনার অ্যাপ্লিকেশন এটি ব্যবহার করা বন্ধ করে, এবং অ্যাপ্লিকেশনটি পজ ( Activity.onPause() ) হওয়ার সাথে সাথেই ক্যামেরা অবজেক্টটি রিলিজ করার ব্যাপারে আপনাকে বিশেষভাবে সতর্ক থাকতে হবে। যদি আপনার অ্যাপ্লিকেশন সঠিকভাবে ক্যামেরাটি রিলিজ না করে, তবে আপনার নিজের অ্যাপ্লিকেশন সহ ক্যামেরা অ্যাক্সেস করার পরবর্তী সমস্ত প্রচেষ্টা ব্যর্থ হবে এবং এর ফলে আপনার বা অন্যান্য অ্যাপ্লিকেশন বন্ধ হয়ে যেতে পারে।

Camera অবজেক্টের একটি ইনস্ট্যান্স রিলিজ করতে, Camera.release() মেথডটি ব্যবহার করুন, যেমনটি নিচের উদাহরণ কোডে দেখানো হয়েছে।

কোটলিন

class CameraActivity : Activity() {
    private var mCamera: Camera?
    private var preview: SurfaceView?
    private var mediaRecorder: MediaRecorder?

    override fun onPause() {
        super.onPause()
        releaseMediaRecorder() // if you are using MediaRecorder, release it first
        releaseCamera() // release the camera immediately on pause event
    }

    private fun releaseMediaRecorder() {
        mediaRecorder?.reset() // clear recorder configuration
        mediaRecorder?.release() // release the recorder object
        mediaRecorder = null
        mCamera?.lock() // lock camera for later use
    }

    private fun releaseCamera() {
        mCamera?.release() // release the camera for other applications
        mCamera = null
    }
}

জাভা

public class CameraActivity extends Activity {
    private Camera mCamera;
    private SurfaceView preview;
    private MediaRecorder mediaRecorder;

    ...

    @Override
    protected void onPause() {
        super.onPause();
        releaseMediaRecorder();       // if you are using MediaRecorder, release it first
        releaseCamera();              // release the camera immediately on pause event
    }

    private void releaseMediaRecorder(){
        if (mediaRecorder != null) {
            mediaRecorder.reset();   // clear recorder configuration
            mediaRecorder.release(); // release the recorder object
            mediaRecorder = null;
            mCamera.lock();           // lock camera for later use
        }
    }

    private void releaseCamera(){
        if (mCamera != null){
            mCamera.release();        // release the camera for other applications
            mCamera = null;
        }
    }
}

সতর্কতা: যদি আপনার অ্যাপ্লিকেশনটি সঠিকভাবে ক্যামেরাটি মুক্ত না করে, তবে আপনার নিজের অ্যাপ্লিকেশন সহ ক্যামেরা অ্যাক্সেস করার পরবর্তী সমস্ত প্রচেষ্টা ব্যর্থ হবে এবং এর ফলে আপনার বা অন্যান্য অ্যাপ্লিকেশন বন্ধ হয়ে যেতে পারে।

মিডিয়া ফাইল সংরক্ষণ করা

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

  • Environment.getExternalStoragePublicDirectory ( Environment.DIRECTORY_PICTURES ) - এই মেথডটি ছবি এবং ভিডিও সংরক্ষণের জন্য স্ট্যান্ডার্ড, শেয়ার করা এবং প্রস্তাবিত লোকেশন রিটার্ন করে। এই ডিরেক্টরিটি শেয়ার করা (পাবলিক), তাই অন্যান্য অ্যাপ্লিকেশনগুলো এই লোকেশনে সংরক্ষিত ফাইলগুলো সহজেই খুঁজে পেতে, পড়তে, পরিবর্তন করতে এবং মুছে ফেলতে পারে। যদি ব্যবহারকারী আপনার অ্যাপ্লিকেশনটি আনইনস্টল করে দেয়, তাহলেও এই লোকেশনে সংরক্ষিত মিডিয়া ফাইলগুলো মুছে যাবে না। ব্যবহারকারীদের বিদ্যমান ছবি এবং ভিডিওতে যাতে কোনো সমস্যা না হয়, সেজন্য আপনার অ্যাপ্লিকেশনের মিডিয়া ফাইলগুলোর জন্য এই ডিরেক্টরির ভেতরে একটি সাব-ডিরেক্টরি তৈরি করা উচিত, যেমনটি নিচের কোড স্যাম্পলে দেখানো হয়েছে। এই মেথডটি অ্যান্ড্রয়েড ২.২ (এপিআই লেভেল ৮)-এ উপলব্ধ; এর আগের এপিআই সংস্করণগুলোতে সমতুল্য কলের জন্য, শেয়ার করা ফাইল সংরক্ষণ (Saving Shared Files ) দেখুন।
  • Context.getExternalFilesDir ( Environment.DIRECTORY_PICTURES ) - এই মেথডটি আপনার অ্যাপ্লিকেশনের সাথে যুক্ত ছবি এবং ভিডিও সংরক্ষণের জন্য একটি স্ট্যান্ডার্ড লোকেশন রিটার্ন করে। যদি আপনার অ্যাপ্লিকেশনটি আনইনস্টল করা হয়, তবে এই লোকেশনে সংরক্ষিত সমস্ত ফাইল মুছে ফেলা হয়। এই লোকেশনের ফাইলগুলির জন্য নিরাপত্তা বলবৎ করা হয় না এবং অন্যান্য অ্যাপ্লিকেশন সেগুলি পড়তে, পরিবর্তন করতে এবং মুছে ফেলতে পারে।

নিম্নলিখিত উদাহরণ কোডটি দেখায় কিভাবে একটি মিডিয়া ফাইলের জন্য File বা Uri লোকেশন তৈরি করতে হয়, যা একটি Intent মাধ্যমে ডিভাইসের ক্যামেরা চালু করার সময় অথবা একটি ক্যামেরা অ্যাপ তৈরির অংশ হিসেবে ব্যবহার করা যেতে পারে।

কোটলিন

val MEDIA_TYPE_IMAGE = 1
val MEDIA_TYPE_VIDEO = 2

/** Create a file Uri for saving an image or video */
private fun getOutputMediaFileUri(type: Int): Uri {
    return Uri.fromFile(getOutputMediaFile(type))
}

/** Create a File for saving an image or video */
private fun getOutputMediaFile(type: Int): File? {
    // To be safe, you should check that the SDCard is mounted
    // using Environment.getExternalStorageState() before doing this.

    val mediaStorageDir = File(
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
            "MyCameraApp"
    )
    // This location works best if you want the created images to be shared
    // between applications and persist after your app has been uninstalled.

    // Create the storage directory if it does not exist
    mediaStorageDir.apply {
        if (!exists()) {
            if (!mkdirs()) {
                Log.d("MyCameraApp", "failed to create directory")
                return null
            }
        }
    }

    // Create a media file name
    val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
    return when (type) {
        MEDIA_TYPE_IMAGE -> {
            File("${mediaStorageDir.path}${File.separator}IMG_$timeStamp.jpg")
        }
        MEDIA_TYPE_VIDEO -> {
            File("${mediaStorageDir.path}${File.separator}VID_$timeStamp.mp4")
        }
        else -> null
    }
}

জাভা

public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;

/** Create a file Uri for saving an image or video */
private static Uri getOutputMediaFileUri(int type){
      return Uri.fromFile(getOutputMediaFile(type));
}

/** Create a File for saving an image or video */
private static File getOutputMediaFile(int type){
    // To be safe, you should check that the SDCard is mounted
    // using Environment.getExternalStorageState() before doing this.

    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
              Environment.DIRECTORY_PICTURES), "MyCameraApp");
    // This location works best if you want the created images to be shared
    // between applications and persist after your app has been uninstalled.

    // Create the storage directory if it does not exist
    if (! mediaStorageDir.exists()){
        if (! mediaStorageDir.mkdirs()){
            Log.d("MyCameraApp", "failed to create directory");
            return null;
        }
    }

    // Create a media file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    File mediaFile;
    if (type == MEDIA_TYPE_IMAGE){
        mediaFile = new File(mediaStorageDir.getPath() + File.separator +
        "IMG_"+ timeStamp + ".jpg");
    } else if(type == MEDIA_TYPE_VIDEO) {
        mediaFile = new File(mediaStorageDir.getPath() + File.separator +
        "VID_"+ timeStamp + ".mp4");
    } else {
        return null;
    }

    return mediaFile;
}

দ্রষ্টব্য: Environment.getExternalStoragePublicDirectory() অ্যান্ড্রয়েড ২.২ (এপিআই লেভেল ৮) বা তার উচ্চতর সংস্করণে উপলব্ধ। আপনি যদি অ্যান্ড্রয়েডের পূর্ববর্তী সংস্করণের ডিভাইস ব্যবহার করেন, তবে এর পরিবর্তে Environment.getExternalStorageDirectory() ব্যবহার করুন। আরও তথ্যের জন্য, শেয়ার করা ফাইল সংরক্ষণ দেখুন।

URI সাপোর্ট ওয়ার্ক প্রোফাইল চালু করতে, প্রথমে ফাইল URI-কে একটি কন্টেন্ট URI-তে রূপান্তর করুন । তারপর, একটি Intent এর EXTRA_OUTPUT এ কন্টেন্ট URI-টি যোগ করুন।

অ্যান্ড্রয়েড ডিভাইসে ফাইল সংরক্ষণ সম্পর্কে আরও তথ্যের জন্য, ডেটা স্টোরেজ দেখুন।

ক্যামেরার বৈশিষ্ট্য

অ্যান্ড্রয়েড বিভিন্ন ধরণের ক্যামেরা ফিচার সমর্থন করে যা আপনি আপনার ক্যামেরা অ্যাপ্লিকেশনের মাধ্যমে নিয়ন্ত্রণ করতে পারেন, যেমন পিকচার ফরম্যাট, ফ্ল্যাশ মোড, ফোকাস সেটিংস এবং আরও অনেক কিছু। এই বিভাগে সাধারণ ক্যামেরা ফিচারগুলোর একটি তালিকা দেওয়া হয়েছে এবং সেগুলো কীভাবে ব্যবহার করতে হয় তা সংক্ষেপে আলোচনা করা হয়েছে। বেশিরভাগ ক্যামেরা ফিচার Camera.Parameters অবজেক্টের মাধ্যমে অ্যাক্সেস এবং সেট করা যায়। তবে, এমন কিছু গুরুত্বপূর্ণ ফিচার রয়েছে যেগুলোর জন্য Camera.Parameters এর সাধারণ সেটিংসের চেয়ে বেশি কিছু প্রয়োজন। এই ফিচারগুলো নিম্নলিখিত বিভাগগুলোতে আলোচনা করা হয়েছে:

Camera.Parameters দ্বারা নিয়ন্ত্রিত ফিচারগুলো কীভাবে ব্যবহার করতে হয় সে সম্পর্কে সাধারণ তথ্যের জন্য, "ক্যামেরা ফিচার ব্যবহার" বিভাগটি পর্যালোচনা করুন। ক্যামেরা প্যারামিটার অবজেক্টের মাধ্যমে নিয়ন্ত্রিত ফিচারগুলো কীভাবে ব্যবহার করতে হয় সে সম্পর্কে আরও বিস্তারিত তথ্যের জন্য, নিচের ফিচার তালিকায় থাকা লিঙ্কগুলো অনুসরণ করে এপিআই রেফারেন্স ডকুমেন্টেশনে যান।

সারণি ১. প্রচলিত ক্যামেরা বৈশিষ্ট্যসমূহ, যে অ্যান্ড্রয়েড এপিআই লেভেলে সেগুলো চালু করা হয়েছিল সেই অনুযায়ী সাজানো।

বৈশিষ্ট্য এপিআই স্তর বর্ণনা
মুখ সনাক্তকরণ ১৪ ছবির মধ্যে মানুষের মুখ শনাক্ত করুন এবং ফোকাস, মিটারিং ও হোয়াইট ব্যালেন্সের জন্য সেগুলো ব্যবহার করুন।
মিটারিং এলাকা ১৪ হোয়াইট ব্যালেন্স গণনা করার জন্য একটি ছবির মধ্যে এক বা একাধিক এলাকা নির্দিষ্ট করুন।
ফোকাস ক্ষেত্র ১৪ ফোকাসের জন্য ছবির মধ্যে এক বা একাধিক এলাকা সেট করুন।
White Balance Lock ১৪ স্বয়ংক্রিয় হোয়াইট ব্যালেন্স সমন্বয় বন্ধ বা চালু করুন
Exposure Lock ১৪ স্বয়ংক্রিয় এক্সপোজার সমন্বয় বন্ধ বা চালু করুন
Video Snapshot ১৪ ভিডিও ধারণ করার সময় ছবি তুলুন (ফ্রেম গ্র্যাব)।
টাইম ল্যাপস ভিডিও ১১ টাইম ল্যাপস ভিডিও রেকর্ড করতে নির্দিষ্ট বিলম্ব সহ ফ্রেম রেকর্ড করুন।
Multiple Cameras একটি ডিভাইসে একাধিক ক্যামেরার সমর্থন, যার মধ্যে সামনের এবং পেছনের ক্যামেরাও অন্তর্ভুক্ত।
Focus Distance ক্যামেরা এবং ফোকাসে থাকা বস্তুগুলোর মধ্যকার দূরত্ব রিপোর্ট করে।
Zoom ছবির বিবর্ধন সেট করুন
Exposure Compensation আলোর সংস্পর্শের মাত্রা বাড়ান বা কমান
GPS Data ছবির সাথে ভৌগোলিক অবস্থানের তথ্য অন্তর্ভুক্ত করুন বা বাদ দিন
White Balance হোয়াইট ব্যালেন্স মোড সেট করুন, যা তোলা ছবির রঙের মানকে প্রভাবিত করে।
Focus Mode ক্যামেরা কোনো বিষয়ের উপর কীভাবে ফোকাস করবে তা সেট করুন, যেমন—অটোমেটিক, ফিক্সড, ম্যাক্রো বা ইনফিনিটি।
Scene Mode রাত্রি, সৈকত, বরফ বা মোমবাতির আলোর দৃশ্যের মতো নির্দিষ্ট ধরনের ফটোগ্রাফি পরিস্থিতির জন্য একটি প্রিসেট মোড প্রয়োগ করুন।
JPEG Quality একটি JPEG ছবির জন্য কম্প্রেশন লেভেল সেট করুন, যা ছবির আউটপুট ফাইলের গুণমান ও আকার বাড়ায় বা কমায়।
Flash Mode ফ্ল্যাশ চালু, বন্ধ করুন অথবা স্বয়ংক্রিয় সেটিং ব্যবহার করুন
Color Effects তোলা ছবিতে সাদা-কালো, সেপিয়া টোন বা নেগেটিভের মতো একটি কালার ইফেক্ট প্রয়োগ করুন।
Anti-Banding JPEG কম্প্রেশনের কারণে কালার গ্রেডিয়েন্টে সৃষ্ট ব্যান্ডিং-এর প্রভাব হ্রাস করে।
Picture Format ছবির জন্য ফাইল ফরম্যাট নির্দিষ্ট করুন।
Picture Size সংরক্ষিত ছবির পিক্সেল মাত্রা নির্দিষ্ট করুন।

দ্রষ্টব্য: হার্ডওয়্যারের ভিন্নতা এবং সফটওয়্যার বাস্তবায়নের কারণে এই ফিচারগুলো সব ডিভাইসে সমর্থিত নয়। আপনার অ্যাপ্লিকেশনটি যে ডিভাইসে চলছে, সেখানে ফিচারগুলোর প্রাপ্যতা যাচাই করার তথ্যের জন্য, ‘ফিচারের প্রাপ্যতা যাচাই’ দেখুন।

ফিচারের প্রাপ্যতা যাচাই করা

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

আপনি ক্যামেরার প্যারামিটারস অবজেক্টের একটি ইনস্ট্যান্স নিয়ে এবং প্রাসঙ্গিক মেথডগুলো পরীক্ষা করে ক্যামেরার ফিচারগুলোর প্রাপ্যতা যাচাই করতে পারেন। নিচের কোড স্যাম্পলটি দেখায় কিভাবে একটি Camera.Parameters অবজেক্ট পেতে হয় এবং ক্যামেরাটি অটোফোকাস ফিচার সমর্থন করে কিনা তা পরীক্ষা করতে হয়:

কোটলিন

val params: Camera.Parameters? = camera?.parameters
val focusModes: List<String>? = params?.supportedFocusModes
if (focusModes?.contains(Camera.Parameters.FOCUS_MODE_AUTO) == true) {
    // Autofocus mode is supported
}

জাভা

// get Camera parameters
Camera.Parameters params = camera.getParameters();

List<String> focusModes = params.getSupportedFocusModes();
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
  // Autofocus mode is supported
}

আপনি ক্যামেরার বেশিরভাগ ফিচারের জন্য উপরে দেখানো কৌশলটি ব্যবহার করতে পারেন। কোনো ফিচার সমর্থিত কিনা (এবং কী পরিমাণে) তা নির্ধারণ করার জন্য Camera.Parameters অবজেক্টটিতে getSupported...() , is...Supported() বা getMax...() মেথড রয়েছে।

আপনার অ্যাপ্লিকেশনটি সঠিকভাবে কাজ করার জন্য যদি নির্দিষ্ট কিছু ক্যামেরা ফিচারের প্রয়োজন হয়, তবে আপনি আপনার অ্যাপ্লিকেশন ম্যানিফেস্টে সংযোজনের মাধ্যমে সেগুলোকে আবশ্যক করতে পারেন। যখন আপনি ফ্ল্যাশ এবং অটো-ফোকাসের মতো নির্দিষ্ট ক্যামেরা ফিচার ব্যবহারের ঘোষণা দেন, তখন গুগল প্লে সেইসব ডিভাইসে আপনার অ্যাপ্লিকেশনটি ইনস্টল হওয়া থেকে বিরত রাখে যেগুলো এই ফিচারগুলো সমর্থন করে না। আপনার অ্যাপ ম্যানিফেস্টে যে ক্যামেরা ফিচারগুলো ঘোষণা করা যেতে পারে তার তালিকার জন্য, ম্যানিফেস্ট ফিচারস রেফারেন্স দেখুন।

ক্যামেরার বৈশিষ্ট্য ব্যবহার করে

ক্যামেরার বেশিরভাগ ফিচার একটি Camera.Parameters অবজেক্ট ব্যবহার করে সক্রিয় ও নিয়ন্ত্রণ করা হয়। এই অবজেক্টটি পেতে হলে প্রথমে Camera অবজেক্টের একটি ইনস্ট্যান্স নিতে হবে, getParameters() মেথডটি কল করতে হবে, ফেরত আসা প্যারামিটার অবজেক্টটি পরিবর্তন করতে হবে এবং সবশেষে সেটিকে আবার ক্যামেরা অবজেক্টে সেট করতে হবে, যেমনটি নিচের উদাহরণ কোডে দেখানো হয়েছে:

কোটলিন

val params: Camera.Parameters? = camera?.parameters
params?.focusMode = Camera.Parameters.FOCUS_MODE_AUTO
camera?.parameters = params

জাভা

// get Camera parameters
Camera.Parameters params = camera.getParameters();
// set the focus mode
params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
// set Camera parameters
camera.setParameters(params);

এই কৌশলটি ক্যামেরার প্রায় সমস্ত বৈশিষ্ট্যের জন্যই কাজ করে, এবং Camera অবজেক্টের একটি ইনস্ট্যান্স পাওয়ার পর যেকোনো সময়ে বেশিরভাগ প্যারামিটার পরিবর্তন করা যায়। প্যারামিটারের পরিবর্তনগুলো সাধারণত অ্যাপ্লিকেশনটির ক্যামেরা প্রিভিউতে ব্যবহারকারী তাৎক্ষণিকভাবে দেখতে পান। সফটওয়্যার পর্যায়ে, প্যারামিটারের পরিবর্তনগুলো কার্যকর হতে কয়েকটি ফ্রেম সময় লাগতে পারে, কারণ ক্যামেরা হার্ডওয়্যার নতুন নির্দেশাবলী প্রক্রিয়াকরণ করে এবং তারপর হালনাগাদ করা ছবির ডেটা পাঠায়।

গুরুত্বপূর্ণ: ক্যামেরার কিছু ফিচার ইচ্ছামতো পরিবর্তন করা যায় না। বিশেষ করে, ক্যামেরা প্রিভিউয়ের আকার বা ওরিয়েন্টেশন পরিবর্তন করতে হলে, আপনাকে প্রথমে প্রিভিউটি বন্ধ করতে হবে, প্রিভিউয়ের আকার পরিবর্তন করতে হবে এবং তারপরে প্রিভিউটি পুনরায় চালু করতে হবে। অ্যান্ড্রয়েড ৪.০ (এপিআই লেভেল ১৪) থেকে প্রিভিউ পুনরায় চালু না করেই প্রিভিউ ওরিয়েন্টেশন পরিবর্তন করা যাবে।

ক্যামেরার অন্যান্য বৈশিষ্ট্যগুলো বাস্তবায়নের জন্য আরও কোডের প্রয়োজন হয়, যার মধ্যে রয়েছে:

  • মিটারিং এবং ফোকাস এলাকা
  • মুখ শনাক্তকরণ
  • টাইম ল্যাপস ভিডিও

এই বৈশিষ্ট্যগুলো কীভাবে বাস্তবায়ন করা যায় তার একটি সংক্ষিপ্ত রূপরেখা নিম্নলিখিত বিভাগগুলিতে দেওয়া হয়েছে।

মিটারিং এবং ফোকাস এলাকা

কিছু ফটোগ্রাফিক পরিস্থিতিতে, স্বয়ংক্রিয় ফোকাসিং এবং লাইট মিটারিং কাঙ্ক্ষিত ফলাফল নাও দিতে পারে। অ্যান্ড্রয়েড ৪.০ (এপিআই লেভেল ১৪) থেকে শুরু করে, আপনার ক্যামেরা অ্যাপ্লিকেশনটি অতিরিক্ত কন্ট্রোল প্রদান করতে পারে, যার মাধ্যমে আপনার অ্যাপ বা ব্যবহারকারীরা কোনো ছবির নির্দিষ্ট এলাকা ফোকাস বা আলোর মাত্রা নির্ধারণের জন্য নির্দিষ্ট করতে পারবেন এবং ছবি বা ভিডিও তোলার জন্য এই মানগুলো ক্যামেরা হার্ডওয়্যারে পাঠাতে পারবেন।

মিটারিং এবং ফোকাসের ক্ষেত্রগুলো ক্যামেরার অন্যান্য ফিচারের মতোই কাজ করে, কারণ এগুলো Camera.Parameters অবজেক্টের মেথডগুলোর মাধ্যমে নিয়ন্ত্রণ করা হয়। নিচের কোডটি Camera র একটি ইনস্ট্যান্সের জন্য দুটি লাইট মিটারিং ক্ষেত্র সেট করার পদ্ধতি দেখাচ্ছে:

কোটলিন

// Create an instance of Camera
camera = getCameraInstance()

// set Camera parameters
val params: Camera.Parameters? = camera?.parameters

params?.apply {
    if (maxNumMeteringAreas > 0) { // check that metering areas are supported
        meteringAreas = ArrayList<Camera.Area>().apply {
            val areaRect1 = Rect(-100, -100, 100, 100) // specify an area in center of image
            add(Camera.Area(areaRect1, 600)) // set weight to 60%
            val areaRect2 = Rect(800, -1000, 1000, -800) // specify an area in upper right of image
            add(Camera.Area(areaRect2, 400)) // set weight to 40%
        }
    }
    camera?.parameters = this
}

জাভা

// Create an instance of Camera
camera = getCameraInstance();

// set Camera parameters
Camera.Parameters params = camera.getParameters();

if (params.getMaxNumMeteringAreas() > 0){ // check that metering areas are supported
    List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>();

    Rect areaRect1 = new Rect(-100, -100, 100, 100);    // specify an area in center of image
    meteringAreas.add(new Camera.Area(areaRect1, 600)); // set weight to 60%
    Rect areaRect2 = new Rect(800, -1000, 1000, -800);  // specify an area in upper right of image
    meteringAreas.add(new Camera.Area(areaRect2, 400)); // set weight to 40%
    params.setMeteringAreas(meteringAreas);
}

camera.setParameters(params);

Camera.Area অবজেক্টটিতে দুটি ডেটা প্যারামিটার থাকে: একটি Rect অবজেক্ট, যা ক্যামেরার ফিল্ড অফ ভিউ-এর মধ্যে একটি এলাকা নির্দিষ্ট করার জন্য ব্যবহৃত হয়, এবং একটি ওয়েট ভ্যালু, যা ক্যামেরাকে বলে দেয় যে লাইট মিটারিং বা ফোকাস গণনার ক্ষেত্রে এই এলাকাটিকে কী পরিমাণ গুরুত্ব দেওয়া উচিত।

একটি Camera.Area অবজেক্টের Rect ফিল্ডটি একটি 2000 x 2000 একক গ্রিডের উপর ম্যাপ করা একটি আয়তক্ষেত্রাকার আকৃতি বর্ণনা করে। -1000, -1000 স্থানাঙ্কগুলি ক্যামেরা চিত্রের উপরের, বাম কোণাকে এবং 1000, 1000 স্থানাঙ্কগুলি ক্যামেরা চিত্রের নীচের, ডান কোণাকে প্রতিনিধিত্ব করে, যেমনটি নীচের চিত্রে দেখানো হয়েছে।

চিত্র ১। লাল রেখাগুলো ক্যামেরা প্রিভিউয়ের মধ্যে একটি Camera.Area নির্দিষ্ট করার জন্য স্থানাঙ্ক ব্যবস্থাটি চিত্রিত করে। নীল বাক্সটি 333,333,667,667 Rect মানসহ একটি ক্যামেরা এলাকার অবস্থান এবং আকৃতি দেখায়।

এই স্থানাঙ্ক ব্যবস্থার সীমানা সর্বদা ক্যামেরা প্রিভিউতে দৃশ্যমান ছবির বাইরের প্রান্তের সাথে সঙ্গতিপূর্ণ থাকে এবং জুম লেভেলের সাথে সংকুচিত বা প্রসারিত হয় না। একইভাবে, Camera.setDisplayOrientation() ব্যবহার করে ছবির প্রিভিউ ঘোরানো হলেও স্থানাঙ্ক ব্যবস্থার কোনো পরিবর্তন হয় না।

মুখ শনাক্তকরণ

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

দ্রষ্টব্য: ফেস ডিটেকশন ফিচারটি চালু থাকা অবস্থায়, setWhiteBalance(String) , setFocusAreas(List<Camera.Area>) এবং setMeteringAreas(List<Camera.Area>) এর কোনো প্রভাব থাকে না।

আপনার ক্যামেরা অ্যাপ্লিকেশনে ফেস ডিটেকশন ফিচারটি ব্যবহার করার জন্য কয়েকটি সাধারণ ধাপ অনুসরণ করতে হয়:

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

ফেস ডিটেকশন ফিচারটি সব ডিভাইসে সমর্থিত নয়। এই ফিচারটি সমর্থিত কিনা তা আপনি getMaxNumDetectedFaces() কল করে যাচাই করতে পারেন। এই যাচাইয়ের একটি উদাহরণ নিচের startFaceDetection() স্যাম্পল মেথডে দেখানো হয়েছে।

মুখমণ্ডল শনাক্তকরণের বিজ্ঞপ্তি পেতে এবং তাতে সাড়া দেওয়ার জন্য, আপনার ক্যামেরা অ্যাপ্লিকেশনটিতে অবশ্যই ফেস ডিটেকশন ইভেন্টের জন্য একটি লিসেনার সেট করতে হবে। এটি করার জন্য, আপনাকে একটি লিসেনার ক্লাস তৈরি করতে হবে যা Camera.FaceDetectionListener ইন্টারফেসটি ইমপ্লিমেন্ট করে, যেমনটি নিচের উদাহরণ কোডে দেখানো হয়েছে।

কোটলিন

internal class MyFaceDetectionListener : Camera.FaceDetectionListener {

    override fun onFaceDetection(faces: Array<Camera.Face>, camera: Camera) {
        if (faces.isNotEmpty()) {
            Log.d("FaceDetection", ("face detected: ${faces.size}" +
                    " Face 1 Location X: ${faces[0].rect.centerX()}" +
                    "Y: ${faces[0].rect.centerY()}"))
        }
    }
}

জাভা

class MyFaceDetectionListener implements Camera.FaceDetectionListener {

    @Override
    public void onFaceDetection(Face[] faces, Camera camera) {
        if (faces.length > 0){
            Log.d("FaceDetection", "face detected: "+ faces.length +
                    " Face 1 Location X: " + faces[0].rect.centerX() +
                    "Y: " + faces[0].rect.centerY() );
        }
    }
}

এই ক্লাসটি তৈরি করার পর, আপনি এটিকে আপনার অ্যাপ্লিকেশনের Camera অবজেক্টে সেট করবেন, যেমনটি নিচের উদাহরণ কোডে দেখানো হয়েছে:

কোটলিন

camera?.setFaceDetectionListener(MyFaceDetectionListener())

জাভা

camera.setFaceDetectionListener(new MyFaceDetectionListener());

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

কোটলিন

fun startFaceDetection() {
    // Try starting Face Detection
    val params = mCamera?.parameters
    // start face detection only *after* preview has started

    params?.apply {
        if (maxNumDetectedFaces > 0) {
            // camera supports face detection, so can start it:
            mCamera?.startFaceDetection()
        }
    }
}

জাভা

public void startFaceDetection(){
    // Try starting Face Detection
    Camera.Parameters params = mCamera.getParameters();

    // start face detection only *after* preview has started
    if (params.getMaxNumDetectedFaces() > 0){
        // camera supports face detection, so can start it:
        mCamera.startFaceDetection();
    }
}

You must start face detection each time you start (or restart) the camera preview. If you use the preview class shown in Creating a preview class , add your startFaceDetection() method to both the surfaceCreated() and surfaceChanged() methods in your preview class, as shown in the sample code below.

কোটলিন

override fun surfaceCreated(holder: SurfaceHolder) {
    try {
        mCamera.setPreviewDisplay(holder)
        mCamera.startPreview()

        startFaceDetection() // start face detection feature
    } catch (e: IOException) {
        Log.d(TAG, "Error setting camera preview: ${e.message}")
    }
}

override fun surfaceChanged(holder: SurfaceHolder, format: Int, w: Int, h: Int) {
    if (holder.surface == null) {
        // preview surface does not exist
        Log.d(TAG, "holder.getSurface() == null")
        return
    }
    try {
        mCamera.stopPreview()
    } catch (e: Exception) {
        // ignore: tried to stop a non-existent preview
        Log.d(TAG, "Error stopping camera preview: ${e.message}")
    }
    try {
        mCamera.setPreviewDisplay(holder)
        mCamera.startPreview()

        startFaceDetection() // re-start face detection feature
    } catch (e: Exception) {
        // ignore: tried to stop a non-existent preview
        Log.d(TAG, "Error starting camera preview: ${e.message}")
    }
}

জাভা

public void surfaceCreated(SurfaceHolder holder) {
    try {
        mCamera.setPreviewDisplay(holder);
        mCamera.startPreview();

        startFaceDetection(); // start face detection feature

    } catch (IOException e) {
        Log.d(TAG, "Error setting camera preview: " + e.getMessage());
    }
}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {

    if (holder.getSurface() == null){
        // preview surface does not exist
        Log.d(TAG, "holder.getSurface() == null");
        return;
    }

    try {
        mCamera.stopPreview();

    } catch (Exception e){
        // ignore: tried to stop a non-existent preview
        Log.d(TAG, "Error stopping camera preview: " + e.getMessage());
    }

    try {
        mCamera.setPreviewDisplay(holder);
        mCamera.startPreview();

        startFaceDetection(); // re-start face detection feature

    } catch (Exception e){
        // ignore: tried to stop a non-existent preview
        Log.d(TAG, "Error starting camera preview: " + e.getMessage());
    }
}

Note: Remember to call this method after calling startPreview() . Do not attempt to start face detection in the onCreate() method of your camera app's main activity, as the preview is not available by this point in your application's the execution.

Time lapse video

Time lapse video allows users to create video clips that combine pictures taken a few seconds or minutes apart. This feature uses MediaRecorder to record the images for a time lapse sequence.

To record a time lapse video with MediaRecorder , you must configure the recorder object as if you are recording a normal video, setting the captured frames per second to a low number and using one of the time lapse quality settings, as shown in the code example below.

কোটলিন

mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH))
mediaRecorder.setCaptureRate(0.1) // capture a frame every 10 seconds

জাভা

// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH));
...
// Step 5.5: Set the video capture rate to a low number
mediaRecorder.setCaptureRate(0.1); // capture a frame every 10 seconds

These settings must be done as part of a larger configuration procedure for MediaRecorder . For a full configuration code example, see Configuring MediaRecorder . Once the configuration is complete, you start the video recording as if you were recording a normal video clip. For more information about configuring and running MediaRecorder , see Capturing videos .

The Camera2Video and HdrViewfinder samples further demonstrate the use of the APIs covered on this page.

Camera fields that require permission

Apps running Android 10 (API level 29) or higher must have the CAMERA permission in order to access the values of the following fields that the getCameraCharacteristics() method returns:

  • LENS_POSE_ROTATION
  • LENS_POSE_TRANSLATION
  • LENS_INTRINSIC_CALIBRATION
  • LENS_RADIAL_DISTORTION
  • LENS_POSE_REFERENCE
  • LENS_DISTORTION
  • LENS_INFO_HYPERFOCAL_DISTANCE
  • LENS_INFO_MINIMUM_FOCUS_DISTANCE
  • SENSOR_REFERENCE_ILLUMINANT1
  • SENSOR_REFERENCE_ILLUMINANT2
  • SENSOR_CALIBRATION_TRANSFORM1
  • SENSOR_CALIBRATION_TRANSFORM2
  • SENSOR_COLOR_TRANSFORM1
  • SENSOR_COLOR_TRANSFORM2
  • SENSOR_FORWARD_MATRIX1
  • SENSOR_FORWARD_MATRIX2

Additional sample code

To download sample apps, see the Camera2Basic sample and Official CameraX sample app .