Bu derste, çerçeve API'lerini kullanarak kamera donanımını doğrudan nasıl kontrol edeceğinizi ele alacağız.
Not: Bu sayfada, desteği sonlandırılan Camera sınıfı ele alınmaktadır. CameraX'i veya belirli kullanım alanları için Camera2'yi kullanmanızı öneririz. Hem CameraX hem de Camera2, Android 5.0 (API düzeyi 21) ve sonraki sürümleri destekler.
Camera1'den CameraX'e nasıl geçiş yapacağınızı öğrenmek için
Camera1'den CameraX'e geçiş başlıklı makaleyi inceleyin.
Alternatif olarak, Camera1'den CameraX'e geçiş için temsilci becerisini kullanabilirsiniz.
Cihaz kamerasını doğrudan kontrol etmek, mevcut kamera uygulamalarından resim veya video istemekten çok daha fazla kod gerektirir. Ancak özel bir kamera uygulaması veya uygulama kullanıcı arayüzünüze tamamen entegre bir şey oluşturmak istiyorsanız bu derste bunu nasıl yapacağınız gösterilmektedir.
Aşağıdaki ilgili kaynaklara göz atın:
Kamera nesnesini açma
Camera nesnesinin bir örneğini almak, kamerayı doğrudan kontrol etme sürecinin ilk adımıdır. Android'in kendi Kamera uygulamasında olduğu gibi, kameraya erişmek için önerilen yöntem, onCreate() yönteminden başlatılan ayrı bir iş parçacığında Camera yöntemini açmaktır. Bu yaklaşım, işlem biraz zaman alabileceği ve kullanıcı arayüzü iş parçacığını yavaşlatabileceği için iyi bir fikirdir. Daha basit bir uygulamada, kodun yeniden kullanımını kolaylaştırmak ve kontrol akışını basit tutmak için kameranın açılması onResume() yöntemine ertelenebilir.
Kamera başka bir uygulama tarafından kullanılıyorsa Camera.open() çağrısı bir istisna oluşturur. Bu nedenle, bunu bir try bloğuna sarmalarız.
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; } }
API düzeyi 9'dan itibaren kamera çerçevesi birden fazla kamerayı destekler. Eski API'yi kullanıyor ve bağımsız değişken olmadan open() yöntemini çağırıyorsanız ilk arka kamerayı alırsınız.
Kamera önizlemesini oluşturma
Fotoğraf çekmek için genellikle kullanıcılarınızın deklanşöre basmadan önce nesnenin önizlemesini görmesi gerekir. Bunu yapmak için kamera sensörünün algıladığı önizlemeleri çizmek üzere SurfaceView kullanabilirsiniz.
Önizleme Sınıfı
Önizleme göstermeye başlamak için önizleme sınıfına ihtiyacınız vardır. Önizleme için, kamera donanımından uygulamaya görüntü verilerini aktarmak amacıyla kullanılan android.view.SurfaceHolder.Callback arayüzünün uygulanması gerekir.
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); } ... }
Canlı görüntü önizlemesi başlatılmadan önce önizleme sınıfı, sonraki bölümde gösterildiği gibi Camera nesnesine iletilmelidir.
Önizlemeyi ayarlama ve başlatma
Kamera örneği ve ilgili önizlemesi belirli bir sırayla oluşturulmalıdır. Kamera nesnesi ilk sırada olmalıdır. Aşağıdaki snippet'te, kamerayı başlatma işlemi kapsüllenir. Böylece kullanıcı kamerayı değiştirmek için bir işlem yaptığında Camera.startPreview(), setCamera() yöntemi tarafından çağrılır. Önizleme, önizleme sınıfı surfaceChanged() geri çağırma yönteminde de yeniden başlatılmalıdır.
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(); } }
Kamera Ayarlarını Değiştirme
Kamera ayarları, yakınlaştırma seviyesinden pozlama telafisine kadar kameranın fotoğraf çekme şeklini değiştirir. Bu örnekte yalnızca önizleme boyutu değiştirilmektedir. Daha fazla bilgi için Kamera uygulamasının kaynak koduna bakın.
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(); }
Önizleme yönünü ayarlama
Çoğu kamera uygulaması, kamera sensörünün doğal yönü olduğu için ekranı yatay modda kilitler. Cihazın yönü EXIF başlığına kaydedildiğinden bu ayar, dikey modda fotoğraf çekmenizi engellemez. setCameraDisplayOrientation() yöntemi, görüntünün kaydedilme şeklini etkilemeden önizlemenin nasıl görüntüleneceğini değiştirmenize olanak tanır. Ancak API düzeyi 14'ten önceki Android sürümlerinde, yönü değiştirmeden önce önizlemenizi durdurmanız ve ardından yeniden başlatmanız gerekir.
Fotoğraf Çekme
Önizleme başlatıldıktan sonra fotoğraf çekmek için Camera.takePicture() yöntemini kullanın. Camera.PictureCallback ve Camera.ShutterCallback nesneleri oluşturup bunları Camera.takePicture() nesnesine iletebilirsiniz.
Sürekli olarak görüntü yakalamak istiyorsanız onPreviewFrame() uygulayan bir Camera.PreviewCallback oluşturabilirsiniz. Bu ikisinin arasında bir şey için yalnızca seçili önizleme karelerini yakalayabilir veya takePicture() yöntemini çağırmak için gecikmeli bir işlem ayarlayabilirsiniz.
Önizlemeyi yeniden başlatma
Fotoğraf çekildikten sonra, kullanıcının başka bir fotoğraf çekebilmesi için önizlemeyi yeniden başlatmanız gerekir. Bu örnekte, yeniden başlatma işlemi deklanşör düğmesine aşırı yükleme yapılarak gerçekleştirilir.
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(); }
Önizlemeyi durdurma ve kamerayı serbest bırakma
Uygulamanız kamerayı kullanmayı bitirdikten sonra temizlik yapma zamanı gelmiştir. Özellikle Camera nesnesini serbest bırakmanız gerekir. Aksi takdirde, kendi uygulamanızın yeni örnekleri de dahil olmak üzere diğer uygulamaların kilitlenmesine neden olabilirsiniz.
Önizlemeyi ne zaman durdurup kamerayı serbest bırakmalısınız? Önizleme yüzeyinizin yok edilmesi, önizlemeyi durdurup kamerayı serbest bırakma zamanının geldiğini gösteren iyi bir ipucudur. Bu durum, Preview sınıfındaki yöntemlerde gösterilmiştir.
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; } }
Dersin önceki bölümlerinde bu prosedürün setCamera() yönteminin de bir parçası olduğunu görmüştük. Dolayısıyla, kamerayı başlatma işlemi her zaman önizlemeyi durdurarak başlar.