Camera1 को CameraX पर माइग्रेट करें

अगर आपका ऐप्लिकेशन ओरिजनल Camera का इस्तेमाल करता है क्लास ("Camera1") है. इस तारीख से इसका इस्तेमाल रोक दिया गया है Android 5.0 (एपीआई लेवल 21), हमारी सलाह है कि आप मॉडर्न Android Camera API पर अपडेट करें. Android ऑफ़र CameraX (स्टैंडर्ड और मज़बूत Jetpack कैमरा एपीआई) और Camera2 (कम लेवल का, फ़्रेमवर्क एपीआई). ज़्यादातर मामलों में, हम आपको अपने ऐप्लिकेशन को CameraX पर माइग्रेट करने का सुझाव देते हैं. ऐसा इन वजहों से हो सकता है:

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

इस गाइड में, आपको कैमरा ऐप्लिकेशन के सामान्य स्थितियों के बारे में पता चलेगा. हर स्थिति में, Camera1 लागू करने और CameraX लागू करने की प्रोसेस शामिल है तुलना.

जब बात माइग्रेशन की हो, तो कभी-कभी आपको इंटिग्रेशन करने के लिए ज़्यादा सुविधाओं की ज़रूरत होती है मौजूदा कोड बेस के साथ. इस गाइड में मौजूद सभी CameraX कोड में CameraController लागू करें—अगर आपको CameraX इस्तेमाल करने का सबसे आसान तरीका चाहिए, तो यह भी एक अच्छा विकल्प है. साथ ही, CameraProvider लागू करें—अगर आपको ज़्यादा सुविधा की ज़रूरत है, तो यह बढ़िया विकल्प है. यह तय करने में आपकी मदद करने के लिए कि आपके लिए सही है. यहां हर एक के फ़ायदे बताए गए हैं:

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

कैमरा प्रोवाइडर

कम सेटअप कोड की ज़रूरत होती है ज़्यादा कंट्रोल की अनुमति देता है
CameraX को सेटअप की ज़्यादा प्रक्रिया मैनेज करने की अनुमति देने का मतलब है फ़ोकस करने के लिए टैप करने और ज़ूम करने के लिए पिंच करने जैसी सुविधाएं अपने-आप काम करती हैं ऐप्लिकेशन डेवलपर सेटअप को मैनेज करता है, इसलिए ऑपर्च्यूनिटी की संभावना और भी ज़्यादा होती है कॉन्फ़िगरेशन को पसंद के मुताबिक बनाने के लिए किया जा सकता है. जैसे, आउटपुट वाली इमेज रोटेशन की सुविधा को चालू करना या ImageAnalysis में आउटपुट इमेज फ़ॉर्मैट सेट करें
कैमरे की झलक के लिए, PreviewView की ज़रूरत है CameraX की मदद से, मशीन लर्निंग की हमारी किट का इस्तेमाल करें और आसानी से एंड-टू-एंड इंटिग्रेशन की सुविधा देता है इंटिग्रेशन जो एमएल मॉडल के नतीजे के निर्देशांक को मैप कर सकता है (जैसे कि चेहरा बाउंडिंग बॉक्स) सीधे पूर्वावलोकन निर्देशांक पर कैमरे की झलक के लिए, ज़रूरत के मुताबिक `Surface` को इस्तेमाल करने की सुविधा से इस्तेमाल करना आसान बनाता है, जैसे कि आपके मौजूदा `Surface` कोड का इस्तेमाल करना आपके ऐप्लिकेशन के अन्य हिस्सों के लिए इनपुट हो सकते हैं

अगर आपको माइग्रेट करने में समस्या आ रही है, तो CameraX चर्चा ग्रुप.

माइग्रेट करने से पहले

CameraX और Camera1 के इस्तेमाल की तुलना

कोड अलग दिख सकता है, लेकिन Camera1 और CameraX बहुत मिलते-जुलते हैं. कैमराएक्स कैमरे के सामान्य फ़ंक्शन को इस्तेमाल के उदाहरणों में शामिल नहीं करते हैं, इस वजह से, Camera1 में डेवलपर के लिए जो टास्क बचे थे उनमें से कई CameraX अपने-आप हैंडल करता है. कुल चार CameraX में UseCase हैं, जिन्हें आप कैमरे के कई तरह के कामों के लिए इस्तेमाल किया जाता है: Preview, ImageCapture, VideoCapture और ImageAnalysis.

डेवलपर के लिए कम-लेवल की जानकारी को मैनेज करने वाला CameraX इसका एक उदाहरण है ViewPort जिसे इनके बीच शेयर किया गया है चालू UseCase. इससे यह पक्का होता है कि सभी UseCase को एक जैसे पिक्सल दिखते हैं. Camera1 में, आपको इन जानकारी को खुद मैनेज करना होगा और बदलाव के हिसाब से भी बदलाव करने होंगे आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) में साथ ही, कैमरा सेंसर और स्क्रीन पर नज़र रखना मुश्किल हो सकता है. पक्का करें कि झलक, कैप्चर की गई फ़ोटो और वीडियो से मेल खाती हो.

दूसरे उदाहरण के तौर पर, CameraX इस ब्राउज़र पर Lifecycle कॉलबैक को अपने-आप हैंडल करता है Lifecycle इंस्टेंस आपने इसे पास किया हो. इसका मतलब है कि CameraX आपके ऐप्लिकेशन की कैमरे से कनेक्ट करने की कोशिश करते हैं. Android पर की गई गतिविधि की लाइफ़साइकल, निम्न मामलों को शामिल करते हुए: आपका ऐप्लिकेशन बैकग्राउंड; जब स्क्रीन की ज़रूरत न हो, तब कैमरे की झलक को हटा दिया जाएगा उसे दिखाना; साथ ही, कोई दूसरी गतिविधि होने पर कैमरे की झलक को रोक दिया जाएगा फ़ोरग्राउंड प्राथमिकता, जैसे कि इनकमिंग वीडियो कॉल.

आखिर में, CameraX बिना किसी अतिरिक्त कोड के रोटेशन और स्केलिंग को मैनेज करता है डेटा को सुरक्षित रखने में मदद मिलती है. अनलॉक किए गए ओरिएंटेशन वाले Activity के मामले में, डिवाइस को हर बार घुमाने पर, UseCase का सेटअप पूरा हो जाता है. ऐसा सिस्टम बंद होने पर होता है और ओरिएंटेशन बदलने पर Activity को फिर से बनाता है. इसका नतीजा यह होता है कि UseCases अपने टारगेट रोटेशन को, इसके हिसाब से डिसप्ले ओरिएंटेशन के हिसाब से सेट कर रहे हैं डिफ़ॉल्ट रूप से डिफ़ॉल्ट सेटिंग होती है. CameraX में घुमाने के बारे में ज़्यादा जानें.

ज़्यादा जानकारी पाने से पहले, CameraX की ये सुविधाएं आज़माएं UseCase और Camera1 ऐप्लिकेशन एक-दूसरे से कैसे जुड़ा होगा. (CameraX कॉन्सेप्ट नीला और Camera1 कॉन्सेप्ट यहां मौजूद हैं हरा.)

कैमराएक्स

CameraController / CameraProvider कॉन्फ़िगरेशन
झलक इमेज कैप्चर वीडियोकैप्चर इमेज का विश्लेषण
झलक देखने की सेटिंग मैनेज करें और उसे कैमरे पर सेट करें कैमरे पर पिक्चर कॉलबैक सेट करें और Takeout() को कॉल करें कैमरे और MediaRecorder कॉन्फ़िगरेशन को खास क्रम में मैनेज करें झलक दिखाने वाले प्लैटफ़ॉर्म के ऊपर बनाया गया कस्टम विश्लेषण कोड
डिवाइस के लिए खास कोड
डिवाइस रोटेशन और स्केलिंग मैनेजमेंट
कैमरा सेशन मैनेजमेंट (कैमरा चुनना, लाइफ़साइकल मैनेजमेंट)

कैमरा1

CameraX के साथ काम करने की सुविधा और परफ़ॉर्मेंस

CameraX उन डिवाइसों पर काम करता है जिन पर कैमरा काम करता है Android 5.0 (एपीआई लेवल 21) और इसके बाद के वर्शन. यह मौजूदा Android डिवाइसों का 98% से ज़्यादा हिस्सा है. CameraX, हैंडल के लिए बनाया गया है डिवाइसों के बीच अपने-आप अंतर होता है. इससे अलग-अलग डिवाइसों की ज़रूरतों को पूरा करने में मदद मिलती है कोड दिखाई दे सकता है. इसके अलावा, हमने हर Android डिवाइस पर 150 से ज़्यादा फ़िज़िकल डिवाइसों की जांच की हमारे CameraX टेस्ट लैब में, 5.0 से अब तक के वर्शन मौजूद हैं. आपने लोगों तक पहुंचाया मुफ़्त में की पूरी सूची देख सकते हैं. टेस्ट लैब में मौजूद डिवाइस.

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

अगर आपके ऐप्लिकेशन को टारगेट किए जाने वाले बाज़ार में कम कीमत वाले डिवाइस शामिल हैं, तो CameraX के साथ सेटअप समय कम करने का एक तरीका है. कैमरे को सीमित करने की सीमा. क्योंकि हार्डवेयर के कॉम्पोनेंट से कनेक्ट करने की प्रोसेस में समय, खासकर कम कीमत वाले डिवाइसों पर, आप अपने ऐप्लिकेशन के कैमरे का सेट ज़रूरतें पूरी करता है. सेटअप के दौरान, CameraX सिर्फ़ इन कैमरों से कनेक्ट होता है. उदाहरण के लिए, अगर यह ऐप्लिकेशन केवल बैक-फ़ेसिंग कैमरों का उपयोग करता है, इसलिए यह कॉन्फ़िगरेशन के साथ DEFAULT_BACK_CAMERA और फिर CameraX, सामने की ओर से शुरू करने से बचाता है इंतज़ार का समय कम करने के लिए, इन कैमरों का इस्तेमाल करें.

Android डेवलपमेंट के सिद्धांत

इस गाइड में Android डेवलपमेंट के बारे में सामान्य जानकारी दी गई है. यहां कुछ ऐसे कॉन्सेप्ट के बारे में बताया गया है जिन्हें ध्यान में रखकर, इसके लिए, नीचे दिया गया कोड देखें:

सामान्य स्थितियों को माइग्रेट करना

इस सेक्शन में, सामान्य स्थितियों को Camera1 से CameraX में माइग्रेट करने का तरीका बताया गया है. हर स्थिति में Camera1 सेटअप और CameraX CameraProvider लागू करने की प्रोसेस शामिल होती है और CameraX CameraController लागू करना ज़रूरी है.

कैमरा चुनना

कैमरा ऐप्लिकेशन में, आपको सबसे पहले ये चीज़ें ऑफ़र करनी पड़ सकती हैं: का इस्तेमाल करके अलग-अलग कैमरे चुन सकते हैं.

कैमरा1

Camera1 में, इनमें से किसी एक को कॉल किया जा सकता है Camera.open(), जिसमें कोई पैरामीटर नहीं है में खोलने के लिए, कोई इंटीजर आईडी देना होगा. कैमरा जो आपको खोलना है. यहां उदाहरण देकर बताया गया है कि यह कैसा दिख सकता है:

// Camera1: select a camera from id.

// Note: opening the camera is a non-trivial task, and it shouldn't be
// called from the main thread, unlike CameraX calls, which can be
// on the main thread since CameraX kicks off background threads
// internally as needed.

private fun safeCameraOpen(id: Int): Boolean {
    return try {
        releaseCameraAndPreview()
        camera = Camera.open(id)
        true
    } catch (e: Exception) {
        Log.e(TAG, "failed to open camera", e)
        false
    }
}

private fun releaseCameraAndPreview() {
    preview?.setCamera(null)
    camera?.release()
    camera = null
}

CameraX: CameraController

CameraX में, चुने गए कैमरे को CameraSelector क्लास मैनेज करती है. कैमराएक्स डिफ़ॉल्ट कैमरे के इस्तेमाल के सामान्य मामले को आसान बनाता है. यह तय किया जा सकता है कि आपको डिफ़ॉल्ट फ़्रंट कैमरा या डिफ़ॉल्ट बैक कैमरा चाहिए. इसके अलावा, CameraX का CameraControl ऑब्जेक्ट, आपको आसानी से अपने ऐप्लिकेशन के लिए ज़ूम का लेवल सेट करें आपका ऐप्लिकेशन किसी ऐसे डिवाइस पर चल रहा है जो लॉजिकल कैमरा को चुनने पर, यह स्विच हो जाएगा सही लेंस इस्तेमाल किया जाता है.

वीडियो के साथ डिफ़ॉल्ट बैक कैमरा इस्तेमाल करने के लिए CameraX कोड यहां दिया गया है CameraController:

// CameraX: select a camera with CameraController

var cameraController = LifecycleCameraController(baseContext)
val selector = CameraSelector.Builder()
    .requireLensFacing(CameraSelector.LENS_FACING_BACK).build()
cameraController.cameraSelector = selector

CameraX: CameraProvider

यहां CameraProvider के साथ डिफ़ॉल्ट फ़्रंट कैमरा चुनने का एक उदाहरण दिया गया है (सामने या पीछे वाले कैमरे का इस्तेमाल CameraController या CameraProvider):

// CameraX: select a camera with CameraProvider.

// Use await() within a suspend function to get CameraProvider instance.
// For more details on await(), see the "Android development concepts"
// section above.
private suspend fun startCamera() {
    val cameraProvider = ProcessCameraProvider.getInstance(this).await()

    // Set up UseCases (more on UseCases in later scenarios)
    var useCases:Array = ...

    // Set the cameraSelector to use the default front-facing (selfie)
    // camera.
    val cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA

    try {
        // Unbind UseCases before rebinding.
        cameraProvider.unbindAll()

        // Bind UseCases to camera. This function returns a camera
        // object which can be used to perform operations like zoom,
        // flash, and focus.
        var camera = cameraProvider.bindToLifecycle(
            this, cameraSelector, useCases)

    } catch(exc: Exception) {
        Log.e(TAG, "UseCase binding failed", exc)
    }
})

...

// Call startCamera in the setup flow of your app, such as in onViewCreated.
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    ...

    lifecycleScope.launch {
        startCamera()
    }
}

अगर आपको यह कंट्रोल करना है कि कौनसा कैमरा चुना गया है, तो कॉल करके CameraProvider का इस्तेमाल करने पर CameraX getAvailableCameraInfos(), यह आपको एक CameraInfo ऑब्जेक्ट देता है. इसकी मदद से, कैमरे की कुछ प्रॉपर्टी की जांच की जा सकती है, जैसे कि isFocusMeteringSupported(). इसके बाद, उसे CameraSelector में बदला जा सकता है, ताकि ऊपर दिए गए उदाहरण की तरह इसका इस्तेमाल किया जा सके CameraInfo.getCameraSelector() तरीके से उदाहरण.

आप URL का उपयोग करके Camera2CameraInfo क्लास. कॉल करें getCameraCharacteristic() को चालू या बंद करने की अनुमति दें. सेटअप के निर्देश देखें CameraCharacteristics क्लास का इस्तेमाल करें.

यहां कस्टम checkFocalLength() फ़ंक्शन का इस्तेमाल करके, एक उदाहरण दिया गया है. खुद को परिभाषित करें:

// CameraX: get a cameraSelector for first camera that matches the criteria
// defined in checkFocalLength().

val cameraInfo = cameraProvider.getAvailableCameraInfos()
    .first { cameraInfo ->
        val focalLengths = Camera2CameraInfo.from(cameraInfo)
            .getCameraCharacteristic(
                CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS
            )
        return checkFocalLength(focalLengths)
    }
val cameraSelector = cameraInfo.getCameraSelector()

झलक दिखाई जा रही है

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

इसके अलावा, Camera1 में आपको यह तय करना होगा कि TextureView या SurfaceView का इस्तेमाल, झलक दिखाने वाले प्लैटफ़ॉर्म के तौर पर करें. दोनों ही विकल्पों के साथ, आपको पसंद के मुताबिक कीमत मिल सकती है. दोनों ही मामलों में, Camera1 को चालू करने के लिए आपको रोटेशन और स्केलिंग को सही ढंग से संभालेंगे. दूसरी तरफ़ CameraX का PreviewView साथ ही, इसमें TextureView और SurfaceView, दोनों को लागू किया गया है. CameraX कई बातों के आधार पर यह तय करता है कि कौनसा तरीका सबसे सही है डिवाइस का टाइप और जिस Android वर्शन पर आपका ऐप्लिकेशन चल रहा है. अगर इनमें से कोई एक है लागू करने की सुविधा संगत है, तो आप इसके साथ अपनी प्राथमिकता का एलान कर सकते हैं: PreviewView.ImplementationMode. COMPATIBLE विकल्प, झलक दिखाने के लिए TextureView का इस्तेमाल करता है और PERFORMANCE वैल्यू, SurfaceView (ज़रूरी होने पर) का इस्तेमाल करती है.

कैमरा1

पूर्वावलोकन दिखाने के लिए, आपको अपनी Preview क्लास को लागू करना android.view.SurfaceHolder.Callback इंटरफ़ेस का इस्तेमाल करता है, जिसका इस्तेमाल कैमरा हार्डवेयर से इमेज डेटा को का इस्तेमाल करें. इसके बाद, लाइव इमेज की झलक देखने से पहले, Preview क्लास को Camera ऑब्जेक्ट में पास किया जाना चाहिए.

// Camera1: set up a camera preview.

class Preview(
        context: Context,
        private val camera: Camera
) : SurfaceView(context), SurfaceHolder.Callback {

    private val holder: SurfaceHolder = holder.apply {
        addCallback(this@Preview)
        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.
        camera.apply {
            try {
                setPreviewDisplay(holder)
                startPreview()
            } catch (e: IOException) {
                Log.d(TAG, "error setting camera preview", e)
            }
        }
    }

    override fun surfaceDestroyed(holder: SurfaceHolder) {
        // 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 (holder.surface == null) {
            return  // The preview surface does not exist.
        }

        // Stop preview before making changes.
        try {
            camera.stopPreview()
        } catch (e: Exception) {
            // Tried to stop a non-existent preview; nothing to do.
        }

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

        // Start preview with new settings.
        camera.apply {
            try {
                setPreviewDisplay(holder)
                startPreview()
            } catch (e: Exception) {
                Log.d(TAG, "error starting camera preview", e)
            }
        }
    }
}

class CameraActivity : AppCompatActivity() {
    private lateinit var viewBinding: ActivityMainBinding
    private var camera: Camera? = null
    private var preview: Preview? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewBinding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(viewBinding.root)

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

        preview = camera?.let {
            // Create the Preview view.
            Preview(this, it)
        }

        // Set the Preview view as the content of the activity.
        val cameraPreview: FrameLayout = viewBinding.cameraPreview
        cameraPreview.addView(preview)
    }
}

CameraX: CameraController

CameraX में, आपके लिए यानी डेवलपर के पास मैनेज करने के लिए बहुत कुछ है. अगर आपको किसी CameraController, तो आपको PreviewView का भी इस्तेमाल करना होगा. इसका मतलब है कि Preview UseCase लागू है, जिससे सेटअप बहुत कम काम करता है:

// CameraX: set up a camera preview with a CameraController.

class MainActivity : AppCompatActivity() {
    private lateinit var viewBinding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewBinding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(viewBinding.root)

        // Create the CameraController and set it on the previewView.
        var cameraController = LifecycleCameraController(baseContext)
        cameraController.bindToLifecycle(this)
        val previewView: PreviewView = viewBinding.cameraPreview
        previewView.controller = cameraController
    }
}

CameraX: CameraProvider

CameraX के CameraProvider के साथ, आपको PreviewView का इस्तेमाल करने की ज़रूरत नहीं है, लेकिन यह अब भी Camera1 पर झलक देखने के सेटअप को बहुत आसान बना देता है. दिखाने के लिए उद्देश्यों को पूरा नहीं करता है, तो इस उदाहरण में PreviewView का इस्तेमाल किया गया है, लेकिन आप अगर आपका दस्तावेज़ जटिल है, तो setSurfaceProvider() में जाने के लिए SurfaceProvider ज़रूरतें पूरी करता है.

यहां, Preview UseCase को ज़ाहिर नहीं किया गया है, जैसा कि यह CameraController के साथ किया गया है, इसलिए आपको इसे सेट अप करना होगा:

// CameraX: set up a camera preview with a CameraProvider.

// Use await() within a suspend function to get CameraProvider instance.
// For more details on await(), see the "Android development concepts"
// section above.
private suspend fun startCamera() {
    val cameraProvider = ProcessCameraProvider.getInstance(this).await()

    // Create Preview UseCase.
    val preview = Preview.Builder()
        .build()
        .also {
            it.setSurfaceProvider(
                viewBinding.viewFinder.surfaceProvider
            )
        }

    // Select default back camera.
    val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA

    try {
        // Unbind UseCases before rebinding.
        cameraProvider.unbindAll()

        // Bind UseCases to camera. This function returns a camera
        // object which can be used to perform operations like zoom,
        // flash, and focus.
        var camera = cameraProvider.bindToLifecycle(
            this, cameraSelector, useCases)

    } catch(exc: Exception) {
        Log.e(TAG, "UseCase binding failed", exc)
    }
})

...

// Call startCamera() in the setup flow of your app, such as in onViewCreated.
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    ...

    lifecycleScope.launch {
        startCamera()
    }
}

टैप-टू-फ़ोकस

जब कैमरे की झलक स्क्रीन पर होती है, तो एक सामान्य कंट्रोल, फ़ोकस सेट करना होता है पॉइंट करें, जब उपयोगकर्ता झलक पर टैप करता है.

कैमरा1

Camera1 में टैप-टू-फ़ोकस लागू करने के लिए, आपको सबसे सही फ़ोकस का हिसाब लगाना होगा यह बताने के लिए कि Camera को कहां फ़ोकस करना चाहिए, Area. यह Area है setFocusAreas() में पास किया गया. साथ ही, आपको इस पर काम करने वाला फ़ोकस मोड सेट करना होगा: Camera. फ़ोकस एरिया सिर्फ़ तब काम करता है, जब मौजूदा फ़ोकस मोड FOCUS_MODE_AUTO, FOCUS_MODE_MACRO, FOCUS_MODE_CONTINUOUS_VIDEO या FOCUS_MODE_CONTINUOUS_PICTURE.

हर Area तय वज़न के साथ एक रेक्टैंगल है. वज़न इनके बीच का मान है 1 और 1,000 है. अगर एक से ज़्यादा वैल्यू सेट की गई हैं, तो Areas पर फ़ोकस करने के लिए इसका इस्तेमाल किया जाता है. यह उदाहरण में सिर्फ़ एक Area का इस्तेमाल किया जाता है. इसलिए, वज़न की वैल्यू से कोई फ़र्क़ नहीं पड़ता. के निर्देशांक रेक्टैंगल की रेंज -1,000 से 1,000 के बीच होगी. सबसे ऊपर बायां पॉइंट (-1,000, -1,000) है. सबसे नीचे दायां पॉइंट (1,000, 1,000) है. दिशा सेंसर के हिसाब से दी गई है स्क्रीन की दिशा, यानी सेंसर को जो दिखता है. दिशा Camera.setDisplayOrientation() को घुमाना या उसका डुप्लीकेट बनाना, ताकि आपको ये काम करने हों टच इवेंट निर्देशांक को सेंसर निर्देशांक में बदल सकते हैं.

// Camera1: implement tap-to-focus.

class TapToFocusHandler : Camera.AutoFocusCallback {
    private fun handleFocus(event: MotionEvent) {
        val camera = camera ?: return
        val parameters = try {
            camera.getParameters()
        } catch (e: RuntimeException) {
            return
        }

        // Cancel previous auto-focus function, if one was in progress.
        camera.cancelAutoFocus()

        // Create focus Area.
        val rect = calculateFocusAreaCoordinates(event.x, event.y)
        val weight = 1  // This value's not important since there's only 1 Area.
        val focusArea = Camera.Area(rect, weight)

        // Set the focus parameters.
        parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO)
        parameters.setFocusAreas(listOf(focusArea))

        // Set the parameters back on the camera and initiate auto-focus.
        camera.setParameters(parameters)
        camera.autoFocus(this)
    }

    private fun calculateFocusAreaCoordinates(x: Int, y: Int) {
        // Define the size of the Area to be returned. This value
        // should be optimized for your app.
        val focusAreaSize = 100

        // You must define functions to rotate and scale the x and y values to
        // be values between 0 and 1, where (0, 0) is the upper left-hand side
        // of the preview, and (1, 1) is the lower right-hand side.
        val normalizedX = (rotateAndScaleX(x) - 0.5) * 2000
        val normalizedY = (rotateAndScaleY(y) - 0.5) * 2000

        // Calculate the values for left, top, right, and bottom of the Rect to
        // be returned. If the Rect would extend beyond the allowed values of
        // (-1000, -1000, 1000, 1000), then crop the values to fit inside of
        // that boundary.
        val left = max(normalizedX - (focusAreaSize / 2), -1000)
        val top = max(normalizedY - (focusAreaSize / 2), -1000)
        val right = min(left + focusAreaSize, 1000)
        val bottom = min(top + focusAreaSize, 1000)

        return Rect(left, top, left + focusAreaSize, top + focusAreaSize)
    }

    override fun onAutoFocus(focused: Boolean, camera: Camera) {
        if (!focused) {
            Log.d(TAG, "tap-to-focus failed")
        }
    }
}

CameraX: CameraController

CameraController, PreviewView के टच इवेंट को हैंडल करने के लिए सुनता है अपने आप फ़ोकस करने के लिए टैप करें. आप इनसे टैप-टू-फ़ोकस को चालू और बंद कर सकते हैं: setTapToFocusEnabled() और मिलते-जुलते गैटर की वैल्यू की जांच करें isTapToFocusEnabled().

कॉन्टेंट बनाने getTapToFocusState() तरीका, LiveData ऑब्जेक्ट दिखाता है CameraController पर फ़ोकस स्थिति में बदलावों को ट्रैक करने के लिए.

// CameraX: track the state of tap-to-focus over the Lifecycle of a PreviewView,
// with handlers you can define for focused, not focused, and failed states.

val tapToFocusStateObserver = Observer { state ->
    when (state) {
        CameraController.TAP_TO_FOCUS_NOT_STARTED ->
            Log.d(TAG, "tap-to-focus init")
        CameraController.TAP_TO_FOCUS_STARTED ->
            Log.d(TAG, "tap-to-focus started")
        CameraController.TAP_TO_FOCUS_FOCUSED ->
            Log.d(TAG, "tap-to-focus finished (focus successful)")
        CameraController.TAP_TO_FOCUS_NOT_FOCUSED ->
            Log.d(TAG, "tap-to-focus finished (focused unsuccessful)")
        CameraController.TAP_TO_FOCUS_FAILED ->
            Log.d(TAG, "tap-to-focus failed")
    }
}

cameraController.getTapToFocusState().observe(this, tapToFocusStateObserver)

CameraX: CameraProvider

CameraProvider का इस्तेमाल करते समय, टैप-टू-फ़ोकस पाने के लिए कुछ सेटअप की ज़रूरत होती है काम कर रहे हैं. यह उदाहरण मानता है कि आप PreviewView का इस्तेमाल कर रहे हैं. अगर ऐसा नहीं है, तो आपको इस लॉजिक को पसंद के मुताबिक Surface पर लागू करें.

PreviewView का इस्तेमाल करने के लिए, यह तरीका अपनाएं:

  1. टैप इवेंट मैनेज करने के लिए, हाथ के जेस्चर (हाव-भाव) की पहचान करने वाला डिटेक्टर सेट करें.
  2. टैप इवेंट के साथ, इसका इस्तेमाल करके MeteringPoint बनाएं MeteringPointFactory.createPoint().
  3. MeteringPoint की मदद से, FocusMeteringAction बनाएं.
  4. आपके Camera पर CameraControl ऑब्जेक्ट के साथ (यहां से लौटाया गया bindToLifecycle()), startFocusAndMetering() को कॉल करें, इस नंबर से निकल रहा/रही हूं FocusMeteringAction.
  5. (ज़रूरी नहीं) FocusMeteringResult का जवाब दें.
  6. टच इवेंट का जवाब देने के लिए, जेस्चर डिटेक्टर सेट करें PreviewView.setOnTouchListener().
// CameraX: implement tap-to-focus with CameraProvider.

// Define a gesture detector to respond to tap events and call
// startFocusAndMetering on CameraControl. If you want to use a
// coroutine with await() to check the result of focusing, see the
// "Android development concepts" section above.
val gestureDetector = GestureDetectorCompat(context,
    object : SimpleOnGestureListener() {
        override fun onSingleTapUp(e: MotionEvent): Boolean {
            val previewView = previewView ?: return
            val camera = camera ?: return
            val meteringPointFactory = previewView.meteringPointFactory
            val focusPoint = meteringPointFactory.createPoint(e.x, e.y)
            val meteringAction = FocusMeteringAction
                .Builder(meteringPoint).build()
            lifecycleScope.launch {
                val focusResult = camera.cameraControl
                    .startFocusAndMetering(meteringAction).await()
                if (!result.isFocusSuccessful()) {
                    Log.d(TAG, "tap-to-focus failed")
                }
            }
        }
    }
)

...

// Set the gestureDetector in a touch listener on the PreviewView.
previewView.setOnTouchListener { _, event ->
    // See pinch-to-zooom scenario for scaleGestureDetector definition.
    var didConsume = scaleGestureDetector.onTouchEvent(event)
    if (!scaleGestureDetector.isInProgress) {
        didConsume = gestureDetector.onTouchEvent(event)
    }
    didConsume
}

ज़ूम करने के लिए पिंच करें

पूर्वावलोकन में ज़ूम इन और ज़ूम आउट करना कैमरे की झलक. उपकरणों पर कैमरे की बढ़ती संख्या के साथ, उपयोगकर्ता भी सबसे अच्छी फ़ोकल लंबाई वाले लेंस को अपने-आप ज़ूम करने का नतीजा मिलता है.

कैमरा1

Camera1 का इस्तेमाल करके ज़ूम करने के दो तरीके हैं. Camera.startSmoothZoom() तरीका ऐनिमेशन के ज़रिए, मौजूदा ज़ूम लेवल से आपके पास किए गए ज़ूम लेवल में ऐनिमेशन दिखाया जाता है. कॉन्टेंट बनाने Camera.Parameters.setZoom() तरीका सीधे आपके पास किए गए ज़ूम लेवल पर ले जाता है इंच इनमें से किसी एक का इस्तेमाल करने से पहले, isSmoothZoomSupported() पर कॉल करें या isZoomSupported() का इस्तेमाल करें, ताकि आपको ज़ूम करने के मिलते-जुलते तरीकों का पता चल सके आपके Camera पर उपलब्ध हैं.

पिंच करके ज़ूम करने की सुविधा लागू करने के लिए, इस उदाहरण में setZoom() का इस्तेमाल किया गया है, क्योंकि प्रीव्यू सरफ़ेस पर लिसनर पिंच के रूप में लगातार इवेंट को सक्रिय करता है जेस्चर काम करता है, जिससे हर बार ज़ूम लेवल तुरंत अपडेट हो जाता है. कॉन्टेंट बनाने ZoomTouchListener क्लास की जानकारी नीचे दी गई है. इसे कॉलबैक के तौर पर सेट किया जाना चाहिए के टच लिसनर तक पहुंच सकते हैं.

// Camera1: implement pinch-to-zoom.

// Define a scale gesture detector to respond to pinch events and call
// setZoom on Camera.Parameters.
val scaleGestureDetector = ScaleGestureDetector(context,
    object : ScaleGestureDetector.OnScaleGestureListener {
        override fun onScale(detector: ScaleGestureDetector): Boolean {
            val camera = camera ?: return false
            val parameters = try {
                camera.parameters
            } catch (e: RuntimeException) {
                return false
            }

            // In case there is any focus happening, stop it.
            camera.cancelAutoFocus()

            // Set the zoom level on the Camera.Parameters, and set
            // the Parameters back onto the Camera.
            val currentZoom = parameters.zoom
            parameters.setZoom(detector.scaleFactor * currentZoom)
        camera.setParameters(parameters)
            return true
        }
    }
)

// Define a View.OnTouchListener to attach to your preview view.
class ZoomTouchListener : View.OnTouchListener {
    override fun onTouch(v: View, event: MotionEvent): Boolean =
        scaleGestureDetector.onTouchEvent(event)
}

// Set a ZoomTouchListener to handle touch events on your preview view
// if zoom is supported by the current camera.
if (camera.getParameters().isZoomSupported()) {
    view.setOnTouchListener(ZoomTouchListener())
}

CameraX: CameraController

टैप-टू-फ़ोकस की तरह ही, CameraController, PreviewView के टच को सुनता है इवेंटों को अपने आप पिंच-टू-ज़ूम मैनेज करने के लिए कर सकते हैं. आप इसे चालू और बंद कर सकते हैं इसके साथ ज़ूम करने के लिए पिंच करें setPinchToZoomEnabled() और मिलते-जुलते गैटर की वैल्यू की जांच करें isPinchToZoomEnabled().

कॉन्टेंट बनाने getZoomState() विधिLiveData ZoomState CameraController.

// CameraX: track the state of pinch-to-zoom over the Lifecycle of
// a PreviewView, logging the linear zoom ratio.

val pinchToZoomStateObserver = Observer { state ->
    val zoomRatio = state.getZoomRatio()
    Log.d(TAG, "ptz-zoom-ratio $zoomRatio")
}

cameraController.getZoomState().observe(this, pinchToZoomStateObserver)

CameraX: CameraProvider

CameraProvider के साथ काम करने के लिए, पिंच करके ज़ूम करने की सुविधा चालू करने के लिए, आपको कुछ सेटअप करना होगा. अगर आपने आप PreviewView का इस्तेमाल नहीं कर रहे हैं, तो आपको अपने पसंद के मुताबिक Surface.

PreviewView का इस्तेमाल करने के लिए, यह तरीका अपनाएं:

  1. पिंच इवेंट को मैनेज करने के लिए, स्केल जेस्चर डिटेक्टर सेट अप करें.
  2. Camera.CameraInfo ऑब्जेक्ट से ZoomState पाएं, जहां Camera आपके कॉल करने पर इंस्टेंस वापस दिखाई देता है bindToLifecycle().
  3. अगर ZoomState की वैल्यू zoomRatio है, तो उसे मौजूदा ज़ूम के तौर पर सेव करें अनुपात. अगर ZoomState पर zoomRatio नहीं है, तो कैमरे की डिफ़ॉल्ट सेटिंग इस्तेमाल करें ज़ूम दर (1.0).
  4. मौजूदा ज़ूम अनुपात के गुणनफल को scaleFactor के साथ निकालें नया ज़ूम अनुपात निर्धारित करें, और उसे CameraControl.setZoomRatio() में पास करें.
  5. टच इवेंट का जवाब देने के लिए, जेस्चर डिटेक्टर सेट करें PreviewView.setOnTouchListener().
// CameraX: implement pinch-to-zoom with CameraProvider.

// Define a scale gesture detector to respond to pinch events and call
// setZoomRatio on CameraControl.
val scaleGestureDetector = ScaleGestureDetector(context,
    object : SimpleOnGestureListener() {
        override fun onScale(detector: ScaleGestureDetector): Boolean {
            val camera = camera ?: return
            val zoomState = camera.cameraInfo.zoomState
            val currentZoomRatio: Float = zoomState.value?.zoomRatio ?: 1f
            camera.cameraControl.setZoomRatio(
                detector.scaleFactor * currentZoomRatio
            )
        }
    }
)

...

// Set the scaleGestureDetector in a touch listener on the PreviewView.
previewView.setOnTouchListener { _, event ->
    var didConsume = scaleGestureDetector.onTouchEvent(event)
    if (!scaleGestureDetector.isInProgress) {
        // See pinch-to-zooom scenario for gestureDetector definition.
        didConsume = gestureDetector.onTouchEvent(event)
    }
    didConsume
}

फ़ोटो ली जा रही है

यह सेक्शन फ़ोटो कैप्चर को ट्रिगर करने का तरीका बताता है, क्या आपको टाइमर पूरा होने के बाद, शटर बटन दबाना या चुनने का विकल्प है.

कैमरा1

Camera1 में, आप पहले Camera.PictureCallback अनुरोध किए जाने पर चित्र डेटा को प्रबंधित करने के लिए. यहां उदाहरण के तौर पर, JPEG इमेज डेटा मैनेज करने के लिए PictureCallback:

// Camera1: define a Camera.PictureCallback to handle JPEG data.

private val picture = 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)
    } catch (e: IOException) {
        Log.d(TAG, "error accessing file", e)
    }
}

इसके बाद, जब भी आप तस्वीर लेना चाहें, takePicture() तरीके को कॉल करें आपके Camera इंस्टेंस पर. इस takePicture() तरीके में तीन अलग-अलग पैरामीटर सेट कर सकते हैं. पहला पैरामीटर ShutterCallback (जिसकी जानकारी इस उदाहरण में नहीं दी गई है). दूसरा पैरामीटर है के लिए, PictureCallback का इस्तेमाल करें. तीसरा इस उदाहरण में इसी पैरामीटर का इस्तेमाल किया गया है, क्योंकि इसे हैंडल करने के लिए PictureCallback JPEG इमेज डेटा.

// Camera1: call takePicture on Camera instance, passing our PictureCallback.

camera?.takePicture(null, null, picture)

CameraX: CameraController

CameraX की CameraController, इमेज के लिए Camera1 की आसानी से काम करती है कैप्चर करने के लिए, takePicture() तरीका लागू करें. यहां, फ़ंक्शन का इस्तेमाल, MediaStore एंट्री को कॉन्फ़िगर करने और वहां सेव करने के लिए फ़ोटो लेने के लिए करता है.

// CameraX: define a function that uses CameraController to take a photo.

private val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS"

private fun takePhoto() {
   // Create time stamped name and MediaStore entry.
   val name = SimpleDateFormat(FILENAME_FORMAT, Locale.US)
              .format(System.currentTimeMillis())
   val contentValues = ContentValues().apply {
       put(MediaStore.MediaColumns.DISPLAY_NAME, name)
       put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
       if(Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
           put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/CameraX-Image")
       }
   }

   // Create output options object which contains file + metadata.
   val outputOptions = ImageCapture.OutputFileOptions
       .Builder(context.getContentResolver(),
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
       .build()

   // Set up image capture listener, which is triggered after photo has
   // been taken.
   cameraController.takePicture(
       outputOptions,
       ContextCompat.getMainExecutor(this),
       object : ImageCapture.OnImageSavedCallback {
           override fun onError(e: ImageCaptureException) {
               Log.e(TAG, "photo capture failed", e)
           }

           override fun onImageSaved(
               output: ImageCapture.OutputFileResults
           ) {
               val msg = "Photo capture succeeded: ${output.savedUri}"
               Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
               Log.d(TAG, msg)
           }
       }
   )
}

CameraX: CameraProvider

CameraProvider से फ़ोटो लेने की सुविधा करीब-करीब ठीक वैसे ही काम करती है जैसे कि ऐप में CameraController, लेकिन आपको पहले ImageCapture बनाना होगा और उसे लिंक करना होगा UseCase पर, takePicture() को कॉल करने के लिए ऑब्जेक्ट पाने के लिए:

// CameraX: create and bind an ImageCapture UseCase.

// Make a reference to the ImageCapture UseCase at a scope that can be accessed
// throughout the camera logic in your app.
private var imageCapture: ImageCapture? = null

...

// Create an ImageCapture instance (can be added with other
// UseCase definitions).
imageCapture = ImageCapture.Builder().build()

...

// Bind UseCases to camera (adding imageCapture along with preview here, but
// preview is not required to use imageCapture). This function returns a camera
// object which can be used to perform operations like zoom, flash, and focus.
var camera = cameraProvider.bindToLifecycle(
    this, cameraSelector, preview, imageCapture)

इसके बाद, जब भी आपको फ़ोटो लेनी हो, तब ImageCapture.takePicture(). इस सेक्शन में CameraController कोड देखें takePhoto() फ़ंक्शन के पूरे उदाहरण के लिए.

// CameraX: define a function that uses CameraController to take a photo.

private fun takePhoto() {
    // Get a stable reference of the modifiable ImageCapture UseCase.
    val imageCapture = imageCapture ?: return

    ...

    // Call takePicture on imageCapture instance.
    imageCapture.takePicture(
        ...
    )
}

वीडियो रिकॉर्ड करना

वीडियो को रिकॉर्ड करना, उन स्थितियों की तुलना में ज़्यादा मुश्किल है जिन्हें देखा जा सकता है अभी तक मिले हैं. प्रोसेस के हर हिस्से को ठीक से सेट अप किया जाना चाहिए. आम तौर पर, ऑर्डर को एक खास क्रम में भी सबमिट किया जा सकता है. साथ ही, आपको यह पुष्टि भी करनी पड़ सकती है कि वीडियो और ऑडियो सिंक करने या डिवाइस से जुड़ी अन्य गड़बड़ियों को ठीक करने के लिए किया जा सकता है.

आपको यह दिखेगा कि CameraX, आपके लिए इन मुश्किलों को फिर से हल कर देता है.

कैमरा1

Camera1 का इस्तेमाल करके वीडियो कैप्चर करने के लिए, Camera को सही तरीके से मैनेज करना ज़रूरी है और MediaRecorder, और तरीकों में किसी खास क्रम में कॉल किया जा सकता है. इसके लिए आपको इस ऑर्डर का पालन करना होगा आपका ऐप्लिकेशन ठीक से काम करे:

  1. कैमरा खोलें.
  2. वीडियो की झलक तैयार करें और उसे शुरू करें (अगर आपके ऐप्लिकेशन में वीडियो रिकॉर्ड किया जा रहा है, आम तौर पर, यह तरीका अपनाया जाता है).
  3. MediaRecorder को इस्तेमाल करने के लिए, कैमरा अनलॉक करें. इसके लिए, Camera.unlock() पर कॉल करें.
  4. MediaRecorder पर इन तरीकों को कॉल करके रिकॉर्डिंग को कॉन्फ़िगर करें:
    1. अपने Camera इंस्टेंस को setCamera(camera) से कनेक्ट करें.
    2. setAudioSource(MediaRecorder.AudioSource.CAMCORDER) पर कॉल करें.
    3. setVideoSource(MediaRecorder.VideoSource.CAMERA) पर कॉल करें.
    4. setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_1080P)) पर कॉल करो क्वालिटी सेट की जा सकती है. यहां जाएं: सभी के लिए CamcorderProfile को हाइलाइट कर सकते हैं.
    5. setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString()) पर कॉल करें.
    6. अगर आपके ऐप्लिकेशन में वीडियो की झलक दिखती है, तो कॉल करें setPreviewDisplay(preview?.holder?.surface).
    7. setOutputFormat(MediaRecorder.OutputFormat.MPEG_4) पर कॉल करें.
    8. setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT) पर कॉल करें.
    9. setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT) पर कॉल करें.
    10. अपने MediaRecorder के कॉन्फ़िगरेशन को पूरा करने के लिए, prepare() पर कॉल करें.
  5. रिकॉर्डिंग शुरू करने के लिए, MediaRecorder.start() पर कॉल करें.
  6. रिकॉर्डिंग बंद करने के लिए, इन तरीकों को कॉल करें. दोबारा, इसी क्रम का पालन करें:
    1. MediaRecorder.stop() पर कॉल करें.
    2. वैकल्पिक रूप से, MediaRecorder को कॉल करके मौजूदा कॉन्फ़िगरेशन को हटाएं MediaRecorder.reset().
    3. MediaRecorder.release() पर कॉल करें.
    4. कैमरा लॉक करें, ताकि आने वाले समय में MediaRecorder के सेशन में इसका इस्तेमाल किया जा सके Camera.lock() को कॉल किया जा रहा है.
  7. झलक दिखाना बंद करने के लिए, Camera.stopPreview() पर कॉल करें.
  8. आखिर में, Camera को रिलीज़ करने के लिए, ताकि अन्य प्रोसेस इसका इस्तेमाल कर सकें Camera.release().

इन सभी चरणों को एक साथ यहां दिया गया है:

// Camera1: set up a MediaRecorder and a function to start and stop video
// recording.

// Make a reference to the MediaRecorder at a scope that can be accessed
// throughout the camera logic in your app.
private var mediaRecorder: MediaRecorder? = null
private var isRecording = false

...

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

    // Unlock and set camera to MediaRecorder.
    camera?.unlock()

    mediaRecorder?.run {
        setCamera(camera)

        // Set the audio and video sources.
        setAudioSource(MediaRecorder.AudioSource.CAMCORDER)
        setVideoSource(MediaRecorder.VideoSource.CAMERA)

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

        // Set the output file.
        setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString())

        // Set the preview output.
        setPreviewDisplay(preview?.holder?.surface)

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

        // Prepare configured MediaRecorder.
        return try {
            prepare()
            true
        } catch (e: IllegalStateException) {
            Log.d(TAG, "preparing MediaRecorder failed", e)
            releaseMediaRecorder()
            false
        } catch (e: IOException) {
            Log.d(TAG, "setting MediaRecorder file failed", e)
            releaseMediaRecorder()
            false
        }
    }
    return false
}

private fun releaseMediaRecorder() {
    mediaRecorder?.reset()
    mediaRecorder?.release()
    mediaRecorder = null
    camera?.lock()
}

private fun startStopVideo() {
    if (isRecording) {
        // Stop recording and release camera.
        mediaRecorder?.stop()
        releaseMediaRecorder()
        camera?.lock()
        isRecording = false

        // This is a good place to inform user that video recording has stopped.
    } else {
        // Initialize video camera.
        if (prepareVideoRecorder()) {
            // Camera is available and unlocked, MediaRecorder is prepared, now
            // you can start recording.
            mediaRecorder?.start()
            isRecording = true

            // This is a good place to inform the user that recording has
            // started.
        } else {
            // Prepare didn't work, release the camera.
            releaseMediaRecorder()

            // Inform user here.
        }
    }
}

CameraX: CameraController

CameraX की CameraController से, ImageCapture को टॉगल किया जा सकता है, VideoCapture और ImageAnalysis UseCases अलग से, जब तक UseCases की सूची का इस्तेमाल एक साथ किया जा सकता हो. ImageCapture और ImageAnalysis UseCase डिफ़ॉल्ट रूप से चालू होती हैं. यही वजह है कि फ़ोटो खींचने के लिए आपको setEnabledUseCases() को कॉल करने की ज़रूरत नहीं पड़ी.

वीडियो रिकॉर्डिंग के लिए CameraController का इस्तेमाल करने के लिए, आपको पहले VideoCapture UseCase की अनुमति देने के लिए, setEnabledUseCases().

// CameraX: Enable VideoCapture UseCase on CameraController.

cameraController.setEnabledUseCases(VIDEO_CAPTURE);

जब आप वीडियो रिकॉर्डिंग शुरू करना चाहें, तो आप CameraController.startRecording() फ़ंक्शन का इस्तेमाल करना होगा. इस सुविधा की मदद से, रिकॉर्ड किए गए वीडियो को File में सेव किया जा सकता है. जैसे, नीचे दिए गए उदाहरण में देखें. इसके अलावा, आपको एक Executor और एक क्लास पास करनी होगी जो लागू करता है OnVideoSavedCallback का इस्तेमाल करें. रिकॉर्डिंग बंद होने पर, कॉल करें CameraController.stopRecording().

ध्यान दें: अगर CameraX 1.3.0-alpha02 या इसके बाद का वर्शन इस्तेमाल किया जा रहा है, तो आपको AudioConfig पैरामीटर जो आपके वीडियो पर ऑडियो रिकॉर्डिंग को चालू या बंद करने की सुविधा देता है. चालू करने के लिए ऑडियो रिकॉर्डिंग के लिए, आपको यह पक्का करना होगा कि आपके पास माइक्रोफ़ोन की अनुमतियां हैं. इसके अलावा, 1.3.0-alpha02 में stopRecording() तरीका हटा दिया गया है और startRecording() एक Recording ऑब्जेक्ट दिखाता है, जिसका इस्तेमाल रोकने के लिए किया जा सकता है. वीडियो रिकॉर्डिंग को फिर से शुरू और बंद कर सकते हैं.

// CameraX: implement video capture with CameraController.

private val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS"

// Define a VideoSaveCallback class for handling success and error states.
class VideoSaveCallback : OnVideoSavedCallback {
    override fun onVideoSaved(outputFileResults: OutputFileResults) {
        val msg = "Video capture succeeded: ${outputFileResults.savedUri}"
        Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
        Log.d(TAG, msg)
    }

    override fun onError(videoCaptureError: Int, message: String,
                         cause: Throwable?) {
        Log.d(TAG, "error saving video: $message", cause)
    }
}

private fun startStopVideo() {
    if (cameraController.isRecording()) {
        // Stop the current recording session.
        cameraController.stopRecording()
        return
    }

    // Define the File options for saving the video.
    val name = SimpleDateFormat(FILENAME_FORMAT, Locale.US)
        .format(System.currentTimeMillis())

    val outputFileOptions = OutputFileOptions
        .Builder(File(this.filesDir, name))
        .build()

    // Call startRecording on the CameraController.
    cameraController.startRecording(
        outputFileOptions,
        ContextCompat.getMainExecutor(this),
        VideoSaveCallback()
    )
}

CameraX: CameraProvider

अगर CameraProvider का इस्तेमाल किया जा रहा है, तो आपको VideoCapture बनाना होगा UseCase दबाएं और Recorder ऑब्जेक्ट को पास करें. Recorder.Builder पर, ये काम किए जा सकते हैं वीडियो की क्वालिटी सेट कर सकते हैं और वैकल्पिक रूप से, FallbackStrategy, जो ऐसे मामलों को हैंडल करता है जब कोई डिवाइस आपकी क्वालिटी से जुड़ी ज़रूरी शर्तों को पूरा नहीं करता. इसके बाद VideoCapture इंस्टेंस को CameraProvider से अपने दूसरे इंस्टेंस से बाइंड करें UseCase सेकंड.

// CameraX: create and bind a VideoCapture UseCase with CameraProvider.

// Make a reference to the VideoCapture UseCase and Recording at a
// scope that can be accessed throughout the camera logic in your app.
private lateinit var videoCapture: VideoCapture
private var recording: Recording? = null

...

// Create a Recorder instance to set on a VideoCapture instance (can be
// added with other UseCase definitions).
val recorder = Recorder.Builder()
    .setQualitySelector(QualitySelector.from(Quality.FHD))
    .build()
videoCapture = VideoCapture.withOutput(recorder)

...

// Bind UseCases to camera (adding videoCapture along with preview here, but
// preview is not required to use videoCapture). This function returns a camera
// object which can be used to perform operations like zoom, flash, and focus.
var camera = cameraProvider.bindToLifecycle(
    this, cameraSelector, preview, videoCapture)

इसके बाद, Recorder को videoCapture.output से ऐक्सेस किया जा सकता है प्रॉपर्टी. Recorder, File में सेव की गई वीडियो रिकॉर्डिंग शुरू कर सकता है, ParcelFileDescriptor या MediaStore. इस उदाहरण में MediaStore का इस्तेमाल किया गया है.

Recorder पर, इसे तैयार करने के लिए कई तरीके उपलब्ध हैं. कॉल करें MediaStore आउटपुट के विकल्प सेट करने के लिए, prepareRecording(). अगर आपके ऐप्लिकेशन में को डिवाइस के माइक्रोफ़ोन का इस्तेमाल करने की अनुमति देनी होगी, तो withAudioEnabled() पर भी कॉल करें. इसके बाद, रिकॉर्डिंग शुरू करने, किसी कॉन्टेक्स्ट में पास करने औरstart() वीडियो रिकॉर्ड इवेंट मैनेज करने के लिए, Consumer<VideoRecordEvent> इवेंट लिसनर. अगर आपने हो जाता है, तो लौटाए गए Recording का इस्तेमाल रिकॉर्डिंग शामिल है.

// CameraX: implement video capture with CameraProvider.

private val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS"

private fun startStopVideo() {
   val videoCapture = this.videoCapture ?: return

   if (recording != null) {
       // Stop the current recording session.
       recording.stop()
       recording = null
       return
   }

   // Create and start a new recording session.
   val name = SimpleDateFormat(FILENAME_FORMAT, Locale.US)
       .format(System.currentTimeMillis())
   val contentValues = ContentValues().apply {
       put(MediaStore.MediaColumns.DISPLAY_NAME, name)
       put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4")
       if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
           put(MediaStore.Video.Media.RELATIVE_PATH, "Movies/CameraX-Video")
       }
   }

   val mediaStoreOutputOptions = MediaStoreOutputOptions
       .Builder(contentResolver, MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
       .setContentValues(contentValues)
       .build()

   recording = videoCapture.output
       .prepareRecording(this, mediaStoreOutputOptions)
       .withAudioEnabled()
       .start(ContextCompat.getMainExecutor(this)) { recordEvent ->
           when(recordEvent) {
               is VideoRecordEvent.Start -> {
                   viewBinding.videoCaptureButton.apply {
                       text = getString(R.string.stop_capture)
                       isEnabled = true
                   }
               }
               is VideoRecordEvent.Finalize -> {
                   if (!recordEvent.hasError()) {
                       val msg = "Video capture succeeded: " +
                           "${recordEvent.outputResults.outputUri}"
                       Toast.makeText(
                           baseContext, msg, Toast.LENGTH_SHORT
                       ).show()
                       Log.d(TAG, msg)
                   } else {
                       recording?.close()
                       recording = null
                       Log.e(TAG, "video capture ends with error",
                             recordEvent.error)
                   }
                   viewBinding.videoCaptureButton.apply {
                       text = getString(R.string.start_capture)
                       isEnabled = true
                   }
               }
           }
       }
}

अन्य संसाधन

हमारे पास कई सारे CameraX ऐप्लिकेशन हैं, जो कैमरे के सैंपल GitHub रिपॉज़िटरी. इन सैंपल से पता चलता है कि इस गाइड में बताए गए मामले, पूरी तरह से Android ऐप्लिकेशन.

अगर आपको CameraX पर माइग्रेट करने के लिए और मदद चाहिए या आपका कोई सवाल है Android Camera API के सुइट के बारे में ज़्यादा जानने के लिए, कृपया CameraX चर्चा ग्रुप.