हम सभी अपने फोन पर कैमरे का उपयोग करते हैं और हम इसका बहुत उपयोग करते हैं। यहां तक कि कुछ एप्लिकेशन भी हैं जिन्होंने कैमरे को एक सुविधा के रूप में एकीकृत किया है।
एक छोर पर, कैमरे के साथ इंटरैक्ट करने का एक मानक तरीका है। दूसरे छोर पर, कैमरे के साथ अपनी बातचीत को अनुकूलित करने का एक तरीका है। यह अंतर करना महत्वपूर्ण है। और यहीं Camera2 आता है।
Camera2 क्या है?
हालांकि यह API लेवल 21 से उपलब्ध है, Camera2 API उन अधिक जटिल वास्तुकला टुकड़ों में से एक है जिनसे डेवलपर्स को निपटना पड़ता है।
यह API और इसके पूर्ववर्ती इसलिए रखे गए थे ताकि डेवलपर अपने एप्लिकेशन के अंदर कैमरे के साथ इंटरैक्ट करने की शक्ति का उपयोग कर सकें।
जिस तरह डिवाइस के माइक्रोफोन या वॉल्यूम के साथ इंटरैक्ट करने का एक तरीका है, Camera2 API आपको डिवाइस के कैमरे के साथ इंटरैक्ट करने के लिए उपकरण देता है।
आम तौर पर, यदि आप Camera2 API का उपयोग करना चाहते हैं, तो यह शायद केवल तस्वीर लेने या वीडियो रिकॉर्ड करने से अधिक के लिए होगा। ऐसा इसलिए है क्योंकि API आपको विभिन्न वर्गों को उजागर करके कैमरे का गहन नियंत्रण देता है जिन्हें प्रति विशिष्ट डिवाइस कॉन्फिगर करने की आवश्यकता होगी।
यहां तक कि अगर आपने पहले कैमरे के साथ काम किया है, तो यह पूर्व कैमरा API से इतना कठोर परिवर्तन है कि आप जो कुछ भी जानते हैं उसे भूल सकते हैं।
बहुत सारे संसाधन हैं जो सीधे इस API का उपयोग करने का प्रदर्शन करने की कोशिश करते हैं, लेकिन उनमें से कुछ पुराने हो सकते हैं और कुछ पूरी तस्वीर पेश नहीं करते हैं।
इसलिए, लापता टुकड़ों को स्वयं भरने की कोशिश करने के बजाय, यह लेख (उम्मीद है) Camera2 API के साथ इंटरैक्ट करने के लिए आपकी वन-स्टॉप शॉप होगी।
Camera2 उपयोग के मामले
किसी भी चीज़ में गोता लगाने से पहले, यह समझना महत्वपूर्ण है कि यदि आप केवल कैमरे का उपयोग तस्वीर लेने या वीडियो रिकॉर्ड करने के लिए करना चाहते हैं, तो आपको Camera2 API से परेशान होने की आवश्यकता नहीं है।
Camera2 API का उपयोग करने का प्राथमिक कारण यह है कि यदि आपके एप्लिकेशन को कैमरे या इसकी कार्यक्षमता के साथ कुछ कस्टम इंटरैक्शन की आवश्यकता है।
यदि आप पूर्व के बजाय बाद वाले में रुचि रखते हैं, तो मैं सुझाव दूंगा कि आप Google से निम्नलिखित डॉक्यूमेंटेशन पर जाएं:
- तस्वीरें लें
- वीडियो कैप्चर करें
वहां आपको अपने कैमरे से शानदार तस्वीरें और वीडियो कैप्चर करने के लिए आवश्यक सभी चरण मिलेंगे। लेकिन इस लेख में, मुख्य फोकस Camera2 का उपयोग कैसे करें पर होगा।
अब, कुछ चीजें हैं जिन्हें हमें अपने मैनिफेस्ट फाइल में जोड़ने की आवश्यकता है:
कैमरा अनुमतियां:
<uses-permission android:name="android.permission.CAMERA" />कैमरा फीचर:
<uses-feature android:name="android.hardware.camera" />आपको यह जांचना होगा कि कैमरा अनुमति दी गई है या नहीं, लेकिन चूंकि इस विषय को व्यापक रूप से कवर किया गया है, हम इस लेख में इससे नहीं निपटेंगे।
Camera2 API घटकों को कैसे सेट करें
Camera2 API कई नए इंटरफेस और क्लास पेश करता है। आइए उनमें से प्रत्येक को तोड़ें ताकि हम बेहतर ढंग से समझ सकें कि उनका उपयोग कैसे करें।

सबसे पहले, हम TextureView से शुरू करेंगे।
Camera2 TextureView घटक
TextureView एक UI घटक है जिसका उपयोग आप कंटेंट स्ट्रीम (वीडियो सोचें) प्रदर्शित करने के लिए करते हैं। हमें कैमरे से फीड प्रदर्शित करने के लिए TextureView का उपयोग करने की आवश्यकता है, चाहे वह प्रीव्यू हो या तस्वीर/वीडियो लेने से पहले।
TextureView के संबंध में दो महत्वपूर्ण गुण हैं:
- SurfaceTexture फील्ड
- SurfaceTextureListener इंटरफेस
पहला वह जगह है जहां कंटेंट प्रदर्शित होगा, और दूसरे में चार कॉलबैक हैं:
- onSurfaceTextureAvailable
- onSurfaceTextureSizeChanged
- onSurfaceTextureUpdated
- onSurfaceTextureDestroyed
private val surfaceTextureListener = object : TextureView.SurfaceTextureListener { override fun onSurfaceTextureAvailable(texture: SurfaceTexture, width: Int, height: Int) { } override fun onSurfaceTextureSizeChanged(texture: SurfaceTexture, width: Int, height: Int) { } override fun onSurfaceTextureDestroyed(texture: SurfaceTexture) { } override fun onSurfaceTextureUpdated(texture: SurfaceTexture) { } }पहला कॉलबैक कैमरे का उपयोग करते समय महत्वपूर्ण है। ऐसा इसलिए है क्योंकि हम सूचित होना चाहते हैं जब SurfaceTexture उपलब्ध हो ताकि हम उस पर फीड प्रदर्शित करना शुरू कर सकें।
ध्यान रखें कि TextureView केवल तभी उपलब्ध होता है जब यह एक विंडो से जुड़ा होता है।
पिछले API के बाद से कैमरे के साथ इंटरैक्ट करना बदल गया है। अब, हमारे पास CameraManager है। यह एक सिस्टम सर्विस है जो हमें CameraDevice ऑब्जेक्ट के साथ इंटरैक्ट करने की अनुमति देती है।
वे विधियां जिन पर आप पूरा ध्यान देना चाहते हैं:
- openCamera
- getCameraCharacteristics
- getCameraIdList
यह जानने के बाद कि TextureView उपलब्ध और तैयार है, हमें कैमरे से कनेक्शन खोलने के लिए openCamera को कॉल करना होगा। यह विधि तीन तर्क लेती है:
- CameraId - String
- CameraDevice.StateCallback
- एक Handler
CameraId तर्क दर्शाता है कि हम किस कैमरे से कनेक्ट करना चाहते हैं। आपके फोन पर, मुख्य रूप से दो कैमरे होते हैं, फ्रंट और बैक। प्रत्येक की अपनी विशिष्ट आईडी होती है। आमतौर पर, यह या तो शून्य या एक होता है।
कैमरा आईडी कैसे प्राप्त करें? हम CameraManager की getCamerasIdList विधि का उपयोग करते हैं। यह डिवाइस से पहचाने गए सभी कैमरा आईडी की स्ट्रिंग प्रकार की एक सरणी वापस करेगा।
val cameraManager: CameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager val cameraIds: Array<String> = cameraManager.cameraIdList var cameraId: String = "" for (id in cameraIds) { val cameraCharacteristics = cameraManager.getCameraCharacteristics(id) //यदि हम फ्रंट फेसिंग के बजाय रियर फेसिंग कैमरा चुनना चाहते हैं if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) continue } val previewSize = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)!!.getOutputSizes(ImageFormat.JPEG).maxByOrNull { it.height * it.width }!! val imageReader = ImageReader.newInstance(previewSize.width, previewSize.height, ImageFormat.JPEG, 1) imageReader.setOnImageAvailableListener(onImageAvailableListener, backgroundHandler) cameraId = id }अगले तर्क कैमरे की स्थिति के लिए कॉलबैक हैं जब हम इसे खोलने का प्रयास करते हैं। यदि आप इसके बारे में सोचते हैं, तो इस क्रिया के लिए केवल कई परिणाम हो सकते हैं:
- कैमरा सफलतापूर्वक खुल जाता है
- कैमरा डिस्कनेक्ट हो जाता है
- कोई त्रुटि होती है
और यही आपको CameraDevice.StateCallback के अंदर मिलेगा:
private val cameraStateCallback = object : CameraDevice.StateCallback() { override fun onOpened(camera: CameraDevice) { } override fun onDisconnected(cameraDevice: CameraDevice) { } override fun onError(cameraDevice: CameraDevice, error: Int) { val errorMsg = when(error) { ERROR_CAMERA_DEVICE -> "Fatal (device)" ERROR_CAMERA_DISABLED -> "Device policy" ERROR_CAMERA_IN_USE -> "Camera in use" ERROR_CAMERA_SERVICE -> "Fatal (service)" ERROR_MAX_CAMERAS_IN_USE -> "Maximum cameras in use" else -> "Unknown" } Log.e(TAG, "Error when trying to connect camera $errorMsg") } }तीसरा तर्क उस स्थान से संबंधित है जहां यह काम होगा। चूंकि हम मुख्य थ्रेड पर कब्जा नहीं करना चाहते, इसलिए इस काम को बैकग्राउंड में करना बेहतर है।
इसलिए हमें इसे एक Handler पास करने की आवश्यकता है। इस हैंडलर इंस्टेंस को हमारे चुने हुए थ्रेड के साथ इंस्टेंटिएट करना बुद्धिमानी होगी ताकि हम काम को इसमें सौंप सकें।
private lateinit var backgroundHandlerThread: HandlerThread private lateinit var backgroundHandler: Handler private fun startBackgroundThread() { backgroundHandlerThread = HandlerThread("CameraVideoThread") backgroundHandlerThread.start() backgroundHandler = Handler( backgroundHandlerThread.looper) } private fun stopBackgroundThread() { backgroundHandlerThread.quitSafely() backgroundHandlerThread.join() }हमने जो कुछ भी किया है, उसके साथ हम अब openCamera को कॉल कर सकते हैं:
cameraManager.openCamera(cameraId, cameraStateCallback,backgroundHandler)फिर onOpened कॉलबैक में, हम TextureView के माध्यम से उपयोगकर्ता को कैमरा फीड प्रस्तुत करने के तर्क से निपटना शुरू कर सकते हैं।

फीड का प्रीव्यू कैसे दिखाएं
हमारे पास हमारा कैमरा (cameraDevice) और फीड दिखाने के लिए TextureView है। लेकिन हमें उन्हें एक दूसरे से जोड़ने की आवश्यकता है ताकि हम फीड का प्रीव्यू दिखा सकें।
ऐसा करने के लिए, हम TextureView के SurfaceTexture गुण का उपयोग करेंगे और एक CaptureRequest बनाएंगे।
val surfaceTexture : SurfaceTexture? = textureView.surfaceTexture // 1 val cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId) //2 val previewSize = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)!! .getOutputSizes(ImageFormat.JPEG).maxByOrNull { it.height * it.width }!! surfaceTexture?.setDefaultBufferSize(previewSize.width, previewSize.height) //3 val previewSurface: Surface = Surface(surfaceTexture) captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW) //4 captureRequestBuilder.addTarget(previewSurface) //5 cameraDevice.createCaptureSession(listOf(previewSurface, imageReader.surface), captureStateCallback, null) //6उपरोक्त कोड में, पहले हम अपने TextureView से surfaceTexture प्राप्त करते हैं। फिर हम कैमरा कैरेक्टरिस्टिक्स ऑब्जेक्ट का उपयोग करके सभी आउटपुट आकारों की सूची प्राप्त करते हैं। वांछित आकार प्राप्त करने के लिए, हम इसे surfaceTexture के लिए सेट करते हैं।
इसके बाद, हम TEMPLATE_PREVIEW पास करके एक captureRequest बनाते हैं। हम अपने इनपुट सरफेस को captureRequest में जोड़ते हैं।
अंत में, हम अपने इनपुट और आउटपुट सरफेस, captureStateCallback, और हैंडलर के लिए null पास करके एक captureSession शुरू करते हैं।
तो यह captureStateCallback क्या है? यदि आप इस लेख की शुरुआत से आरेख याद करते हैं, तो यह CameraCaptureSession का हिस्सा है जिसे हम शुरू कर रहे हैं। यह ऑब्जेक्ट निम्नलिखित कॉलबैक के साथ captureRequest की प्रगति को ट्रैक करता है:
- onConfigured
- onConfigureFailed
private val captureStateCallback = object : CameraCaptureSession.StateCallback() { override fun onConfigureFailed(session: CameraCaptureSession) { } override fun onConfigured(session: CameraCaptureSession) { } }जब cameraCaptureSession सफलतापूर्वक कॉन्फिगर हो जाता है, तो हम सत्र के लिए एक दोहराने वाला अनुरोध सेट करते हैं ताकि हमें प्रीव्यू को लगातार दिखाने की अनुमति मिल सके।
ऐसा करने के लिए, हम कॉलबैक में मिलने वाले सत्र ऑब्जेक्ट का उपयोग करते हैं:
session.setRepeatingRequest(captureRequestBuilder.build(), null, backgroundHandler)आप हमारे captureRequestBuilder ऑब्जेक्ट को पहचान लेंगे जिसे हमने पहले इस विधि के पहले तर्क के रूप में बनाया था। हम बिल्ड विधि लागू करते हैं ताकि पास किया गया अंतिम पैरामीटर CaptureRequest हो।
दूसरा तर्क CameraCaptureSession.captureCallback लिस्टनर है, लेकिन चूंकि हम कैप्चर की गई छवियों के साथ कुछ नहीं करना चाहते (क्योंकि यह एक प्रीव्यू है), हम null पास करते हैं।
तीसरा तर्क एक हैंडलर है, और यहां हम अपने स्वयं के backgroundHandler का उपयोग करते हैं। यही कारण है कि हमने पिछले अनुभाग में null पास किया था, क्योंकि दोहराने वाला अनुरोध बैकग्राउंड थ्रेड पर चलेगा।

तस्वीर कैसे लें
कैमरे का लाइव प्रीव्यू होना बहुत अच्छा है, लेकिन अधिकांश उपयोगकर्ता शायद इसके साथ कुछ करना चाहेंगे। तस्वीर लेने के लिए हम जो कुछ तर्क लिखेंगे, वह पिछले अनुभाग में हमने जो किया था, उसके समान होगा।
- हम एक captureRequest बनाएंगे
- हम फोटो लेने के लिए ImageReader और उसके लिस्टनर का उपयोग करेंगे
- अपने cameraCaptureSession का उपयोग करके, हम capture विधि को लागू करेंगे
val orientations : SparseIntArray = SparseIntArray(4).apply { append(Surface.ROTATION_0, 0) append(Surface.ROTATION_90, 90) append(Surface.ROTATION_180, 180) append(Surface.ROTATION_270, 270) } val captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE) captureRequestBuilder.addTarget(imageReader.surface) val rotation = windowManager.defaultDisplay.rotation captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, orientations.get(rotation)) cameraCaptureSession.capture(captureRequestBuilder.build(), captureCallback, null)लेकिन यह ImageReader क्या है? खैर, एक ImageReader एक सरफेस पर रेंडर किए गए छवि डेटा तक पहुंच प्रदान करता है। हमारे मामले में, यह TextureView का सरफेस है।
यदि आप पिछले अनुभाग से कोड स्निपेट देखते हैं, तो आप देखेंगे कि हमने वहां पहले ही एक ImageReader परिभाषित कर दिया है।
val cameraManager: CameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager val cameraIds: Array<String> = cameraManager.cameraIdList var cameraId: String = "" for (id in cameraIds) { val cameraCharacteristics = cameraManager.getCameraCharacteristics(id) //यदि हम फ्रंट फेसिंग के बजाय रियर फेसिंग कैमरा चुनना चाहते हैं if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) continue } val previewSize = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)!!.getOutputSizes(ImageFormat.JPEG).maxByOrNull { it.height * it.width }!! val imageReader = ImageReader.newInstance(previewSize.width, previewSize.height, ImageFormat.JPEG, 1) imageReader.setOnImageAvailableListener(onImageAvailableListener, backgroundHandler) cameraId = id }जैसा कि आप ऊपर देख सकते हैं, हम एक चौड़ाई और ऊंचाई, छवि प्रारूप जिसे हम अपनी छवि में चाहते हैं, और छवियों की संख्या जो यह कैप्चर कर सकता है, पास करके एक ImageReader को इंस्टेंटिएट करते हैं।
ImageReader क्लास का एक गुण onImageAvailableListener नामक एक लिस्टनर है। यह लिस्टनर तब ट्रिगर होगा जब एक फोटो ली जाती है (क्योंकि हमने इसके सरफेस को अपने कैप्चर अनुरोध के लिए आउटपुट स्रोत के रूप में पास किया था)।
val onImageAvailableListener = object: ImageReader.OnImageAvailableListener{ override fun onImageAvailable(reader: ImageReader) { val image: Image = reader.acquireLatestImage() } }⚠️ प्रोसेसिंग के बाद छवि को बंद करना सुनिश्चित करें अन्यथा आप दूसरी फोटो नहीं ले पाएंगे।

वीडियो कैसे रिकॉर्ड करें
वीडियो रिकॉर्ड करने के लिए, हमें MediaRecorder नामक एक नए ऑब्जेक्ट के साथ इंटरैक्ट करने की आवश्यकता है। मीडिया रिकॉर्डर ऑब्जेक्ट ऑडियो और वीडियो रिकॉर्ड करने का प्रभारी है और हम इसका उपयोग ठीक उसी के लिए करेंगे।
कुछ भी करने से पहले, हमें मीडिया रिकॉर्डर सेटअप करने की आवश्यकता है। निपटने के लिए विभिन्न कॉन्फिगरेशन हैं और उन्हें सही क्रम में होना चाहिए अन्यथा अपवाद फेंके जाएंगे।
नीचे कॉन्फिगरेशन का चयन है जो हमें वीडियो कैप्चर करने की अनुमति देगा (ऑडियो के बिना)।
fun setupMediaRecorder(width: Int, height: Int) { val mediaRecorder: MediaRecorder = MediaRecorder() mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE) mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4) mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264) mediaRecorder.setVideoSize(videoSize.width, videoSize.height) mediaRecorder.setVideoFrameRate(30) mediaRecorder.setOutputFile(PATH_TO_FILE) mediaRecorder.setVideoEncodingBitRate(10_000_000) mediaRecorder.prepare() }setOutputFile विधि पर ध्यान दें क्योंकि यह उस फाइल का पथ अपेक्षा करता है जो हमारे वीडियो को स्टोर करेगा। इन सभी कॉन्फिगरेशन को सेट करने के बाद हमें prepare कॉल करना होगा।
ध्यान दें कि mediaRecorder में एक start विधि भी है और हमें इसे कॉल करने से पहले prepare कॉल करना होगा।
अपना mediaRecorder सेटअप करने के बाद, हमें एक कैप्चर अनुरोध और एक कैप्चर सत्र बनाने की आवश्यकता है।
fun startRecording() { val surfaceTexture : SurfaceTexture? = textureView.surfaceTexture surfaceTexture?.setDefaultBufferSize(previewSize.width, previewSize.height) val previewSurface: Surface = Surface(surfaceTexture) val recordingSurface = mediaRecorder.surface captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD) captureRequestBuilder.addTarget(previewSurface) captureRequestBuilder.addTarget(recordingSurface) cameraDevice.createCaptureSession(listOf(previewSurface, recordingSurface), captureStateVideoCallback, backgroundHandler) }प्रीव्यू या स्टिल फोटो सेटअप करने के समान, हमें अपने इनपुट और आउटपुट सरफेस को परिभाषित करना होगा।
यहां हम TextureView के surfaceTexture से एक Surface ऑब्जेक्ट बना रहे हैं और मीडिया रिकॉर्डर से सरफेस भी ले रहे हैं। हम कैप्चर अनुरोध बनाते समय TEMPLATE_RECORD मान पास कर रहे हैं।
हमारा captureStateVideoCallback उसी प्रकार का है जिसका उपयोग हमने स्टिल फोटो के लिए किया था, लेकिन onConfigured कॉलबैक के अंदर हम मीडिया रिकॉर्डर की start विधि को कॉल करते हैं।
val captureStateVideoCallback = object : CameraCaptureSession.StateCallback() { override fun onConfigureFailed(session: CameraCaptureSession) { } override fun onConfigured(session: CameraCaptureSession) { session.setRepeatingRequest(captureRequestBuilder.build(), null, backgroundHandler) mediaRecorder.start() } }अब हम वीडियो रिकॉर्ड कर रहे हैं, लेकिन रिकॉर्डिंग कैसे रोकें? इसके लिए, हम mediaRecorder ऑब्जेक्ट पर stop और reset विधियों का उपयोग करेंगे:
mediaRecorder.stop() mediaRecorder.reset()निष्कर्ष
यह प्रोसेस करने के लिए बहुत कुछ था। तो अगर आप यहां तक पहुंचे, तो बधाई! इससे बचने का कोई रास्ता नहीं है – केवल कोड के साथ अपने हाथ गंदे करके आप समझना शुरू करेंगे कि सब कुछ कैसे एक साथ जुड़ता है।
आप इस लेख में दिखाए गए सभी कोड को नीचे देखने के लिए प्रोत्साहित हैं :
MediumArticles/Camrea2API at master · TomerPacific/MediumArticlesविभिन्न माध्यम लेखों से जुड़ा कोड वाला एक रिपॉजिटरी जो मैंने लिखा है - MediumArticles/Camrea2API at master · TomerPacific/MediumArticles
TomerPacificGitHub
ध्यान रखें कि Camera2 API की बात आती है तो यह सिर्फ हिमशैल का सिरा है। बहुत सी अन्य चीजें हैं जो आप कर सकते हैं, जैसे स्लो मोशन वीडियो कैप्चर करना, फ्रंट और बैक कैमरे के बीच स्विच करना, फोकस को नियंत्रित करना, और बहुत कुछ।