कैमरा कंट्रोल करें

इस लेसन में हमने बताया है कि किसी डिवाइस का इस्तेमाल करके, सीधे तौर पर कैमरा हार्डवेयर को कैसे कंट्रोल किया जा सकता है फ़्रेमवर्क API का इस्तेमाल कर सकते हैं.

ध्यान दें: यह पेज, कैमरा क्लास के बारे में है. यह अब काम नहीं करता. हमारा सुझाव है कि आप CameraX या इस्तेमाल के कुछ खास उदाहरणों के लिए, Camera2 इस्तेमाल करें. CameraX और Camera2, दोनों ही Android 5.0 (एपीआई लेवल 21) और इसके बाद वाले वर्शन पर काम करते हैं.

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

यहां दिए गए मिलते-जुलते संसाधनों को देखें:

कैमरा ऑब्जेक्ट खोलें

Camera ऑब्जेक्ट का इंस्टेंस पाना, कैमरे को सीधे कंट्रोल करने की प्रोसेस शुरू कर दी है. जैसा कि Android का अपना कैमरा ऐप्लिकेशन करता है, हमारा सुझाव है कि आप Camera को एक अलग थ्रेड पर कैमरा ऐक्सेस करें इसे onCreate() से लॉन्च किया गया है. यह एक अच्छा आइडिया है क्योंकि इसमें थोड़ा समय लग सकता है और हो सकता है कि यूज़र इंटरफ़ेस (यूआई) थ्रेड ठीक से काम न करे. बुनियादी तौर पर लागू करने पर, कैमरे को खोलने के लिए, onResume() तरीके का इस्तेमाल करना टाला जा सकता है. इससे कोड को दोबारा इस्तेमाल किया जा सकता है और उसके फ़्लो को बनाए रखा जा सकता है आसान हो जाता है.

Camera.open() को कॉल करने पर अपवाद के तौर पर, जब कैमरा पहले से किसी अन्य ऐप्लिकेशन के इस्तेमाल में हो रहा हो, तो हम उसे रैप कर देते हैं try ब्लॉक में.

Kotlin

private fun safeCameraOpen(id: Int): Boolean {
    return try {
        releaseCameraAndPreview()
        mCamera = Camera.open(id)
        true
    } catch (e: Exception) {
        Log.e(getString(R.string.app_name), "failed to open Camera")
        e.printStackTrace()
        false
    }
}

private fun releaseCameraAndPreview() {
    preview?.setCamera(null)
    mCamera?.also { camera ->
        camera.release()
        mCamera = null
    }
}

Java

private boolean safeCameraOpen(int id) {
    boolean qOpened = false;

    try {
        releaseCameraAndPreview();
        camera = Camera.open(id);
        qOpened = (camera != null);
    } catch (Exception e) {
        Log.e(getString(R.string.app_name), "failed to open Camera");
        e.printStackTrace();
    }

    return qOpened;
}

private void releaseCameraAndPreview() {
    preview.setCamera(null);
    if (camera != null) {
        camera.release();
        camera = null;
    }
}

एपीआई लेवल 9 के बाद से, कैमरे का फ़्रेमवर्क एक से ज़्यादा कैमरों के साथ काम करता है. अगर आपको लेगसी एपीआई को ऐक्सेस करने और open() को कॉल करने के लिए, तो आपको पहला रीयर-फ़ेस वाला कैमरा मिलता है.

कैमरे की झलक बनाएं

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

क्लास की झलक देखें

झलक दिखाना शुरू करने के लिए, आपको 'झलक दिखाने वाली क्लास' की ज़रूरत होगी. कॉन्टेंट बनाने झलक देखने के लिए android.view.SurfaceHolder.Callback इंटरफ़ेस को लागू करना ज़रूरी है, जिसका इस्तेमाल इमेज भेजने के लिए किया जाता है कैमरा हार्डवेयर से ऐप्लिकेशन तक का डेटा.

Kotlin

class Preview(
        context: Context,
        val surfaceView: SurfaceView = SurfaceView(context)
) : ViewGroup(context), SurfaceHolder.Callback {

    var mHolder: SurfaceHolder = surfaceView.holder.apply {
        addCallback(this@Preview)
        setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS)
    }
    ...
}

Java

class Preview extends ViewGroup implements SurfaceHolder.Callback {

    SurfaceView surfaceView;
    SurfaceHolder holder;

    Preview(Context context) {
        super(context);

        surfaceView = new SurfaceView(context);
        addView(surfaceView);

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        holder = surfaceView.getHolder();
        holder.addCallback(this);
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }
...
}

लाइव स्ट्रीम शुरू होने से पहले, झलक वाली क्लास को Camera ऑब्जेक्ट को पास करना ज़रूरी है इमेज की झलक को शुरू किया जा सकता है, जैसा कि अगले सेक्शन में दिखाया गया है.

झलक सेट करें और शुरू करें

कैमरा इंस्टेंस और इससे जुड़ी झलक को किसी खास जिसमें कैमरा ऑब्जेक्ट पहले होता है. नीचे दिए गए स्निपेट में, कैमरा शुरू करने की प्रोसेस इनकैप्सुलेट की गई है, ताकि Camera.startPreview() को setCamera() तरीका इस्तेमाल करके, जब भी उपयोगकर्ता कैमरा. प्रीव्यू क्लास surfaceChanged() कॉलबैक तरीके में, झलक को भी रीस्टार्ट करना ज़रूरी है.

Kotlin

fun setCamera(camera: Camera?) {
    if (mCamera == camera) {
        return
    }

    stopPreviewAndFreeCamera()

    mCamera = camera

    mCamera?.apply {
        mSupportedPreviewSizes = parameters.supportedPreviewSizes
        requestLayout()

        try {
            setPreviewDisplay(holder)
        } catch (e: IOException) {
            e.printStackTrace()
        }

        // Important: Call startPreview() to start updating the preview
        // surface. Preview must be started before you can take a picture.
        startPreview()
    }
}

Java

public void setCamera(Camera camera) {
    if (mCamera == camera) { return; }

    stopPreviewAndFreeCamera();

    mCamera = camera;

    if (mCamera != null) {
        List<Size> localSizes = mCamera.getParameters().getSupportedPreviewSizes();
        supportedPreviewSizes = localSizes;
        requestLayout();

        try {
            mCamera.setPreviewDisplay(holder);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Important: Call startPreview() to start updating the preview
        // surface. Preview must be started before you can take a picture.
        mCamera.startPreview();
    }
}

कैमरा सेटिंग बदलें

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

Kotlin

override fun surfaceChanged(holder: SurfaceHolder, format: Int, w: Int, h: Int) {
    mCamera?.apply {
        // Now that the size is known, set up the camera parameters and begin
        // the preview.
        parameters?.also { params ->
            params.setPreviewSize(previewSize.width, previewSize.height)
            requestLayout()
            parameters = params
        }

        // Important: Call startPreview() to start updating the preview surface.
        // Preview must be started before you can take a picture.
        startPreview()
    }
}

Java

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    // Now that the size is known, set up the camera parameters and begin
    // the preview.
    Camera.Parameters parameters = mCamera.getParameters();
    parameters.setPreviewSize(previewSize.width, previewSize.height);
    requestLayout();
    mCamera.setParameters(parameters);

    // Important: Call startPreview() to start updating the preview surface.
    // Preview must be started before you can take a picture.
    mCamera.startPreview();
}

प्रीव्यू का ओरिएंटेशन सेट करें

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

फ़ोटो खींचें

Camera.takePicture() का इस्तेमाल करना उपयोग करने का तरीका बताया है. Camera.PictureCallback और Camera.ShutterCallback ऑब्जेक्ट बनाए जा सकते हैं और उन्हें Camera.takePicture() में पास किया जा सकता है.

अगर आपको लगातार इमेज कैप्चर करनी हैं, तो onPreviewFrame() को लागू करने वाला Camera.PreviewCallback बनाएं. इसके लिए करने के बीच में कोई अंतर नहीं है, तो आप केवल चुनिंदा पूर्वावलोकन फ़्रेम कैप्चर कर सकते हैं या takePicture() को कॉल करने में देरी हुई.

झलक फिर से शुरू करें

कोई तस्वीर लेने के बाद, आपको उपयोगकर्ता से पहले झलक को फिर से शुरू करना होगा दूसरा चित्र ले सकता है. इस उदाहरण में, रीस्टार्ट करने के लिए ओवरलोड हो रहा है शटर बटन को दबाया जा सकता है.

Kotlin

fun onClick(v: View) {
    previewState = if (previewState == K_STATE_FROZEN) {
        camera?.startPreview()
        K_STATE_PREVIEW
    } else {
        camera?.takePicture(null, rawCallback, null)
        K_STATE_BUSY
    }
    shutterBtnConfig()
}

Java

@Override
public void onClick(View v) {
    switch(previewState) {
    case K_STATE_FROZEN:
        camera.startPreview();
        previewState = K_STATE_PREVIEW;
        break;

    default:
        camera.takePicture( null, rawCallback, null);
        previewState = K_STATE_BUSY;
    } // switch
    shutterBtnConfig();
}

झलक देखना बंद करें और कैमरा रिलीज़ कर दें

कैमरे का इस्तेमाल कर लिए जाने के बाद, ऐप्लिकेशन को खाली करें. तय सीमा में खास तौर पर, आपको Camera ऑब्जेक्ट को रिलीज़ करना होगा. ऐसा न करने पर, किसी दूसरे ऐप्लिकेशन को क्रैश करने का खतरा रहता है जिसमें आपके खुद के ऐप्लिकेशन के नए इंस्टेंस शामिल हैं.

झलक देखना बंद करके, कैमरे को कब रिलीज़ करना चाहिए? अपने बारे में नष्ट की गई झलक की झलक इस बात का काफ़ी अच्छा संकेत है कि अब आपकी साइट के कैमरे की झलक देखें और उसे रिलीज़ करें, जैसा कि Preview क्लास से इन तरीकों में दिखाया गया है.

Kotlin

override fun surfaceDestroyed(holder: SurfaceHolder) {
    // Surface will be destroyed when we return, so stop the preview.
    // Call stopPreview() to stop updating the preview surface.
    mCamera?.stopPreview()
}

/**
 * When this function returns, mCamera will be null.
 */
private fun stopPreviewAndFreeCamera() {
    mCamera?.apply {
        // Call stopPreview() to stop updating the preview surface.
        stopPreview()

        // Important: Call release() to release the camera for use by other
        // applications. Applications should release the camera immediately
        // during onPause() and re-open() it during onResume()).
        release()

        mCamera = null
    }
}

Java

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    // Surface will be destroyed when we return, so stop the preview.
    if (mCamera != null) {
        // Call stopPreview() to stop updating the preview surface.
        mCamera.stopPreview();
    }
}

/**
 * When this function returns, mCamera will be null.
 */
private void stopPreviewAndFreeCamera() {

    if (mCamera != null) {
        // Call stopPreview() to stop updating the preview surface.
        mCamera.stopPreview();

        // Important: Call release() to release the camera for use by other
        // applications. Applications should release the camera immediately
        // during onPause() and re-open() it during onResume()).
        mCamera.release();

        mCamera = null;
    }
}

इस लेसन में पहले, यह प्रोसेस setCamera() तरीके का भी हिस्सा थी. इसलिए, कैमरा शुरू करने की शुरुआत हमेशा झलक देखें.