

Me kaikki käytämme kameraa puhelimissamme ja käytämme sitä l-o-t. Jotkut sovellukset ovat jopa integroineet kameran ominaisuutena.
Toisessa päässä on tavallinen tapa olla vuorovaikutuksessa kameran kanssa. Toisaalta on tapa mukauttaa vuorovaikutustasi kameran kanssa. Tämä ero on tärkeä tehdä. Ja tässä Camera2 tulee mukaan.
Mikä on Camera2?
Vaikka se on ollut saatavilla API-tasosta 21 lähtien, Camera2 API:n on oltava yksi monimutkaisimmista arkkitehtuurikehittäjien osista.
Tämä API ja sen edeltäjä otettiin käyttöön, jotta kehittäjät voivat hyödyntää sovellustensa sisällä olevan kameran vuorovaikutuksen voimaa.
Samoin kuin on tapa olla vuorovaikutuksessa mikrofonin tai laitteen äänenvoimakkuuden kanssa, Camera2 API tarjoaa työkalut vuorovaikutukseen laitteen kameran kanssa.
Yleisesti ottaen, jos haluat käyttää Camera2 API:ta, se olisi todennäköisesti muutakin kuin vain kuvan ottamista tai videon tallentamista. Tämä johtuu siitä, että API antaa sinun hallita kameraa perusteellisesti paljastamalla erilaisia luokkia, jotka on määritettävä tietylle laitteelle.
Vaikka oletkin käsitellyt kameraa aiemmin, se on niin raju muutos entiseen kameran API:hen, että saatat yhtä hyvin unohtaa kaiken, mitä tiedät.
Siellä on paljon resursseja, jotka yrittävät esitellä tämän API:n käyttöä suoraan, mutta jotkut niistä voivat olla vanhentuneita ja jotkut eivät anna koko kuvaa.
Joten sen sijaan, että yrittäisit täyttää puuttuvat kohdat itse, tämä artikkeli on (toivottavasti) sinun keskitetysti vuorovaikutuksessa Camera2 API:n kanssa.
Camera2 käyttökotelot
Ennen kuin sukeltaamme mihinkään, on tärkeää ymmärtää, että jos haluat käyttää kameraa vain kuvan ottamiseen tai videon tallentamiseen, sinun ei tarvitse vaivautua Camera2 API:n kanssa.
Ensisijainen syy Camera2 API:n käyttöön on, jos sovelluksesi vaatii mukautettua vuorovaikutusta kameran tai sen toimintojen kanssa.
Jos olet kiinnostunut tekemään edellisen jälkimmäisen sijaan, suosittelen, että tutustut seuraavaan Googlen dokumentaatioon:
Sieltä löydät kaikki tarvittavat vaiheet, jotka sinun on suoritettava upeiden valokuvien ja videoiden tallentamiseen kamerallasi. Mutta tässä artikkelissa pääpaino on Camera2:n käytössä.
Nyt on joitain asioita, jotka meidän on lisättävä luettelotiedostoomme:
Kameran käyttöoikeudet:
Kameran ominaisuus:
Sinun on tarkistettava, onko kameralupa myönnetty vai ei, mutta koska tätä aihetta on käsitelty laajasti, emme käsittele sitä tässä artikkelissa.
Camera2 API -komponenttien määrittäminen
Camera2 API tuo useita uusia käyttöliittymiä ja luokkia. Erotetaan jokainen niistä, jotta ymmärrämme paremmin, kuinka niitä käytetään.

Ensinnäkin aloitammeTextureView.
Camera2 TextureView -komponentti
TextureView on käyttöliittymäkomponentti, jota käytät sisältövirran näyttämiseen (ajattele videota). Meidän on käytettävä TextureView'ta näyttääksemme syötteen kamerasta, olipa kyseessä esikatselu tai ennen kuvan/videon ottamista.
Kaksi ominaisuutta, joita on tärkeää käyttää TextureView'n suhteen, ovat:
- Pintateksti-kenttä
- SurfaceTextureListener-käyttöliittymä
Ensimmäinen on paikka, jossa sisältö näytetään, ja toisessa on neljä takaisinsoittoa:
- onSurfaceTextureAvailable
- onSurfaceTextureSizeChanged
- onSurfaceTextureUpdated
- onSurfaceTextureDestroyed
private val surfaceTextureListener = objekti : TextureView.SurfaceTextureListener { override fun onSurfaceTextureAvailable(tekstuuri: SurfaceTexture, leveys: Int, korkeus: Int) { } ohita hauska onSurfaceTextureSizeChanged(tekstuuri: Pintatekstuuri, leveys: Inttrodeteksti) tekstuuri: SurfaceTexture) { } override fun onSurfaceTextureUpdated(tekstuuri: SurfaceTexture) { }}
Ensimmäinen takaisinsoitto on erittäin tärkeä kameraa käytettäessä. Tämä johtuu siitä, että haluamme saada ilmoituksen, kun SurfaceTexture on saatavilla, jotta voimme alkaa näyttää syötettä siinä.
Huomaa, että vasta kun TextureView on liitetty ikkunaan, se tulee saataville.
Vuorovaikutus kameran kanssa on muuttunut edellisen API:n jälkeen. Nyt meillä onKameranhallinta. Tämä on järjestelmäpalvelu, jonka avulla voimme olla vuorovaikutuksessaKameralaiteesineitä.
Menetelmät, joihin haluat kiinnittää erityistä huomiota, ovat:
Kun tiedämme, että TextureView on saatavilla ja valmis, meidän on soitettava openCameralle avataksemme yhteyden kameraan. Tämä menetelmä sisältää kolme argumenttia:
- Kameratunnus – merkkijono
- CameraDevice.StateCallback
- Käsittelijä
CameraId-argumentti ilmaisee, mihin kameraan haluamme muodostaa yhteyden. Puhelimessasi on pääasiassa kaksi kameraa, etu- ja takakamera. Jokaisella on oma yksilöllinen tunnus. Yleensä se on joko nolla tai ykkönen.
Miten saamme kameran tunnuksen? Käytämme CameraManagerin getCamerasIdList-menetelmää. Se palauttaa merkkijonotyypin kaikista laitteesta tunnistetuista kameratunnuksista.
val cameraManager: CameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManagerval cameraIds: Array = cameraManager.cameraIdListvar cameraId: String = ""for (id in cameraIds) { val cameraCharacteristics = cameraManager.getCamera(we wantCharacteristics) valitaksesi takakameran etukameran sijaan if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) jatka } val previewSize = cameraCharacteristics.get(CameraCharacteristics.get(CameraCharacteristics)!! izes(ImageFormat.JPEG) .maxByOrNull { it.height * it.width }!! val imageReader = ImageReader.newInstance(previewSize.width, previewSize.height, ImageFormat.JPEG, 1) imageReader.setOnImageAvailableListener(onImageAvailableListener, backgroundHandler) cameraId = id}
Seuraavat argumentit ovat takaisinkutsuja kameran tilaan, kun yritämme avata sen. Jos ajattelet sitä, tällä toiminnolla voi olla vain useita tuloksia:
- Kamera avautuu onnistuneesti
- Kamera katkeaa
- Jokin virhe tapahtuu
Ja se on mitä löydät CameraDevice.StateCallbackin sisältä:
yksityinen val cameraStateCallback = objekti : CameraDevice.StateCallback() { override fun onOpened(camera: CameraDevice) { } override fun onDisconnected(cameraDevice: CameraDevice) { } override fun onError(cameraDevice: CameraDevice, error: Int) { when val(Ms) virhe) { ERROR_CAMERA_DEVICE -> "Fatal (laite)" ERROR_CAMERA_DISABLED -> "Laitekäytäntö" ERROR_CAMERA_IN_USE -> "Kamera käytössä" ERROR_CAMERA_SERVICE -> "Kuolemallinen (palvelu)" ERROR_MAX_CAMERAS_INxUSE m ->kamerat "Unknown other" -> " } Log.e(TAG, "Virhe yritettäessä yhdistää kameraa $errorMsg") } }
Kolmas argumentti koskee sitä, missä tämä työ tapahtuu. Koska emme halua miehittää pääsäiettä, on parempi tehdä tämä työ taustalla.
Siksi meidän on välitettävä käsittelijä sille. Olisi viisasta, että tämä käsittelijäinstanssi instantoidaan valitsemallamme säikeellä, jotta voimme delegoida sille työtä.
yksityinen lateinit var backgroundHandlerThread: KäsittelijäThreadprivate lateinit var backgroundHandler: Käsittelijä yksityinen hauska aloitusBackgroundThread() { backgroundHandlerThread = HandlerThread("CameraVideoThread") backgroundHandlerThread.start() backgroundHandler = OperaattoriThread. { backgroundHandlerThread.quitSafely() backgroundHandlerThread.join()}
Kaiken, mitä olemme tehneet, voimme nyt kutsua openCameraksi:
cameraManager.openCamera(cameraId, cameraStateCallback,backgroundHandler)
Sitten sisälläonOpened takaisinsoitto, voimme alkaa käsitellä logiikkaa, miten kameran syöte esitetään käyttäjälle TextureView-sovelluksen kautta.

Kuinka näyttää syötteen esikatselu
Meillä on kameramme (cameraDevice) ja TextureView, jotka näyttävät syötteen. Mutta meidän on yhdistettävä ne toisiinsa, jotta voimme näyttää syötteen esikatselun.
Tätä varten käytämme TextureView:n SurfaceTexture-ominaisuutta ja rakennamme CaptureRequestin.
val surfaceTexture : Pintatekstuuri? = textureView.surfaceTexture // 1val cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId) //2val previewSize = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)!! .getOutputSizes (imageFormat.jpeg) .Maxbyornull {it.height * it.width} !! SurfaceTexture? .setDefaultBuffersize (esikatselusta. CameraDevice.TEMPLATE_PREVIEW) //4captureRequestBuilder.addTarget(previewSurface) //5cameraDevice.createCaptureSession(listOf(previewSurface, imageReader.surface), captureStateCallback, null) //6
Yllä olevassa koodissa saamme ensin pintatekstuurin TextureView-näkymästämme. Sitten käytämme cameraCharacteristics-objektia saadaksemme luettelon kaikista lähtökooista. Halutun koon saamiseksi asetamme sen pintatekstuurille.
Seuraavaksi luomme captureRequest-pyynnön, johon siirrymmeTEMPLATE_PREVIEW. Lisäämme syöttöpinnamme captureRequestiin.
Lopuksi aloitamme captureSessionin syöttö- ja lähtöpinnoillamme, captureStateCallback ja annamme käsittelijälle nollan.
Joten mikä tämä captureStateCallback on? Jos muistat kaavion tämän artikkelin alusta, se on osa CameraCaptureSession-ohjelmaa, jonka aloitamme. Tämä objekti seuraa captureRequestin edistymistä seuraavilla takaisinkutsuilla:
- onConfigured
- onConfigureFailed
yksityinen val captureStateCallback = objekti : CameraCaptureSession.StateCallback() { override fun onConfigureFailed(session: CameraCaptureSession) { } override fun onConfigured(session: CameraCaptureSession) { }}
KuncameraCaptureSessionon määritetty onnistuneesti, asetimme istunnolle toistuvan pyynnön, jotta voimme näyttää esikatselun jatkuvasti.
Tätä varten käytämme takaisinkutsussa saatua istuntoobjektia:
session.setRepeatingRequest(captureRequestBuilder.build(), null, backgroundHandler)
Tunnistat aiemmin luomamme captureRequestBuilder-objektin ensimmäisenä argumenttina tälle menetelmälle. Otamme käyttöön koontimenetelmän, joten viimeinen välitetty parametri on CaptureRequest.
Toinen argumentti on CameraCaptureSession.captureCallback-kuuntelija, mutta koska emme halua tehdä mitään kaapatuilla kuvilla (koska tämä on esikatselu), välitämme tyhjän.
Kolmas argumentti on käsittelijä, ja tässä käytämme omaa taustakäsittelijäämme. Tästä syystä jätimme edellisessä osiossa tyhjäksi, koska toistuva pyyntö suoritetaan taustasäikeessä.

Kuinka ottaa kuva
Kameran live-esikatselu on mahtavaa, mutta useimmat käyttäjät haluavat todennäköisesti tehdä sen kanssa jotain. Osa logiikasta, jonka kirjoitamme ottaaksesi kuvan, on samanlainen kuin mitä teimme edellisessä osiossa.
- Luomme sieppauspyynnön
- Käytämme ImageReaderia ja sen kuuntelijaa otetun kuvan keräämiseen
- Käytämme cameraCaptureSession-ohjelmaamme kaappausmenetelmän
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)} createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE)captureRequestBuilder.addTarget(imageReader.surface)val rotation = windowManager.defaultDisplay.rotationcaptureRequestBuilder.set(CaptureRequest.JPEG-rootationS(CaptureRequest.JPEGapture.sactures_ORIENTATION) aptureRequestBuilder.build(), captureCallback, null)
Mutta mikä tämä onImageReader? No, ImageReader tarjoaa pääsyn kuvatietoihin, jotka renderöidään pinnalle. Meidän tapauksessamme se on TextureView'n pinta.
Jos katsot koodinpätkää edellisestä osiosta, huomaat, että olemme jo määrittäneet ImageReaderin sinne.
val cameraManager: CameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManagerval cameraIds: Array = cameraManager.cameraIdListvar cameraId: String = ""for (id in cameraIds) { val cameraCharacteristics = cameraManager.getCameraf(we wantCharacteristics jos haluat valita takakameran etukameran sijaan if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) jatka } val previewSize = cameraCharacteristics.get(CameraCharacteristics.get(CameraCharacteristics)!! izes(ImageFormat.JPEG) .maxByOrNull { it.height * it.width }!! val imageReader = ImageReader.newInstance(previewSize.width, previewSize.height, ImageFormat.JPEG, 1) imageReader.setOnImageAvailableListener(onImageAvailableListener, backgroundHandler) cameraId = id}
Kuten yllä näet, instantoimme ImageReaderin antamalla leveyden ja korkeuden, kuvamuodon, jossa haluamme kuvamme olevan, ja kuvien määrän, jonka se voi ottaa.
ImageReader-luokan ominaisuus on kuuntelija nimeltä onImageAvailableListener. Tämä kuuntelija käynnistyy, kun valokuva on otettu (koska menimme sen pintaan sieppauspyyntömme lähtölähteenä).
val onImageAvailableListener = objekti: ImageReader.OnImageAvailableListener{ ohittaa hauska onImageAvailable(lukija: ImageReader) { val image: Image = reader.acquireLatestImage() } }
⚠️Muista sulkea kuva käsittelyn jälkeen, muuten et voi ottaa toista kuvaa.

Kuinka tallentaa video
Videon tallentamiseksi meidän on oltava vuorovaikutuksessa uuden kohteen kanssaMediaRecorder. Mediatallennusobjekti vastaa äänen ja videon tallentamisesta, ja käytämme sitä juuri niin.
Ennen kuin teemme mitään, meidän on määritettävä mediatallennin. On olemassa erilaisia kokoonpanoja käsitellä janiiden on oltava oikeassa järjestyksessä tai muuten poikkeuksia heitetään.
Alla on esimerkki valikoimasta kokoonpanoja, joiden avulla voimme kaapata videota (ilman ääntä).
fun setupMediaRecorder(leveys: Int, korkeus: Int) { val mediaRecorder: MediaRecorder = MediaRecorder() mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE) mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4) MediaRecorder.OutputFormat.MPEG_4) MediaRecorder.OutputFormat.MPEG_4) MediaRecorder. 64) mediaRecorder.setVideoSize(videoSize.width, videoSize.height) mediaRecorder.setVideoFrameRate(30) mediaRecorder.setOutputFile(PATH_TO_FILE) mediaRecorder.setVideoEncodingBitRate(10_000_000) mediarecorder()}.
Kiinnitä huomiotasetOutputFilemenetelmää, koska se odottaa polun tiedostoon, joka tallentaa videomme. Kaikkien näiden asetusten määrittämisen lopussa meidän on kutsuttava valmistelu.
Huomaa, että mediaRecorderilla on myös käynnistysmenetelmä ja meidän on kutsuttava valmistelu ennen kutsumista.
MediaRecoderin asennuksen jälkeen meidän on luotava sieppauspyyntö ja sieppausistunto.
fun startRecording() { val surfaceTexture : SurfaceTexture? = textureView.surfaceTexture surfaceTexture?.setDefaultBufferSize(previewSize.width, previewSize.height) val previewSurface: Pinta = Pinta(pintatekstuuri) val recordingSurface = mediaRecorder.surface captureRequestBuilder = cameraDevice.createCaptureCapture_DeviceRequest(CORDuCapture_DeviceRequest. dTarget(previewSurface) captureRequestBuilder. addTarget(recordingSurface) cameraDevice.createCaptureSession(listOf(previewSurface, recordingSurface), captureStateVideoCallback, backgroundHandler) }
Samoin kuin esikatselun asettaminen tai valokuvan ottaminen, meidän on määritettävä syöttö- ja tulostuspinnamme.
Tässä luomme pintaobjektin TextureView:n pintatekstuurista ja otamme pinnan myös mediatallentimesta. Kuljemme sisäänTEMPLATE_RECORDarvoa sieppauspyyntöä luotaessa.
CaptureStateVideoCallback on samaa tyyppiä, jota käytimme still-kuvassa, mutta onConfigured-soittopyynnön sisällä kutsumme mediatallentimen käynnistysmenetelmää.
val captureStateVideoCallback = objekti : CameraCaptureSession.StateCallback() { override fun onConfigureFailed(session: CameraCaptureSession) { } override fun onConfigured(session: CameraCaptureSession) { session.setRepeatingRequest(CaptureRequest) mediaRecorder.start() } }
Nyt nauhoitamme videota, mutta kuinka lopetamme nauhoituksen? Tätä varten käytämme mediaRecorder-objektin pysäytys- ja palautusmenetelmiä:
mediaRecorder.stop()mediaRecorder.reset()
Johtopäätös
Siinä oli paljon käsiteltävää. Joten jos pääsit tänne, onnittelut! Sitä ei voi kiertää – vain likaamalla kätesi koodilla alat ymmärtää, kuinka kaikki liittyy toisiinsa.
Sinua rohkaistaan tutustumaan kaikkiin tähän artikkeliin alla olevaan koodiin:
MediumArticles/Camrea2API at master · TomerPacific/MediumArticles
Arkisto, joka sisältää useisiin kirjoittamiini Medium-artikkeleihin liittyvää koodia - MediumArticles/Camrea2API isännässä · TomerPacific/MediumArticles
TomerPacificGitHub
Muista, että tämä on vain jäävuoren huippu Camera2 API:n suhteen. Voit tehdä monia muita asioita, kuten hidastettua videota, vaihtaa etu- ja takakameran välillä, ohjata tarkennusta ja paljon muuta.
MAINOS
MAINOS
MAINOS
MAINOS
MAINOS
MAINOS
MAINOS
MAINOS
MAINOS
MAINOS
MAINOS
MAINOS

Lukealisää postauksia.
Jos tästä artikkelista oli apua, .
Opi koodaamaan ilmaiseksi. freeCodeCampin avoimen lähdekoodin opetussuunnitelma on auttanut yli 40 000 ihmistä saamaan töitä kehittäjänä.Aloittaa
MAINOS
FAQs
What is the use of camera API in Android? ›
This package is the primary API for controlling device cameras. It can be used to take pictures or videos when you are building a camera application.
How to enable Camera2API module in Android? ›- Open terminal emulator app.
- Type su and enter. Give root permissions.
- Type setprop persist.camera.HAL3.enabled 1 and enter.
- Type setprop vendor.persist.camera.HAL3.enabled 1 and enter.
- Reboot your phone.
Camera2 is the low-level Android camera package that replaces the deprecated Camera class. Camera2 provides in-depth controls for complex use cases, but requires you to manage device-specific configurations. For more information, see the Camera2 reference documentation.