Android官方开发文档Training系列课程中文版:调用相机之控制相机
原文地址:http://android.xsoftlab.net/training/camera/cameradirect.html
在這節(jié)課,我們會討論如何使用Android框架API來直接控制相機硬件。
直接控制設備的相機拍照或者攝像的代碼遠比通過其他相機應用來完成要多得多。然而,如果你想構建一個專業(yè)的相機應用或者在APP的UI中完全集成相機的話,這節(jié)課展示了如何去做。
開啟相機對象
直接控制相機的第一步就是獲得Camera對象的實例。和Android自身的相機應用相同,推薦訪問相機的方式就是在獨立的線程打開Camera,這種方式是應對阻塞UI線程的一個好的解決方法。在更加基礎化的實現(xiàn)當中,開啟相機這一步操作可以推遲到onResume()方法中執(zhí)行,這樣可以促使代碼重用并且保持簡單的控制流。
如果相機已經正在被其它應用所使用,那么調用Camera.open()方法會拋出一個異常,所以我們需要使用try控制塊包裹住它:
private boolean safeCameraOpen(int id) {boolean qOpened = false;try {releaseCameraAndPreview();mCamera = Camera.open(id);qOpened = (mCamera != null);} catch (Exception e) {Log.e(getString(R.string.app_name), "failed to open Camera");e.printStackTrace();}return qOpened; } private void releaseCameraAndPreview() {mPreview.setCamera(null);if (mCamera != null) {mCamera.release();mCamera = null;} }從API 9開始,相機框架支持多個相機。如果你使用的是過去的API,然后調用了沒有參數(shù)的open()方法,那么你會獲得后置面板的相機。
創(chuàng)建相機預覽
拍照通常需要可以使用戶能看到目標的預覽圖。你可以使用SurfaceView來繪制相機傳感器捕獲到的圖像。
預覽類
為了可以顯示預覽,你需要預覽類。預覽需要一個android.view.SurfaceHolder.Callback接口的實現(xiàn),它被用來從相機硬件給應用傳遞圖像數(shù)據(jù)。
class Preview extends ViewGroup implements SurfaceHolder.Callback {SurfaceView mSurfaceView;SurfaceHolder mHolder;Preview(Context context) {super(context);mSurfaceView = new SurfaceView(context);addView(mSurfaceView);// Install a SurfaceHolder.Callback so we get notified when the// underlying surface is created and destroyed.mHolder = mSurfaceView.getHolder();mHolder.addCallback(this);mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);} ... }在開始預覽之前,必須將預覽對象傳遞給Camera對象,就像下面部分展示的那樣。
設置并開始預覽
相機實例的創(chuàng)建于相關預覽對象創(chuàng)建必須是以指定順序進行的,從相機對象開始。在下面的代碼中,實例化相機對象的過程被封裝起來了,所以Camera.startPreview()是可以通過setCamera()調用的,每當用戶做了什么事情使相機發(fā)生了改變。預覽也必須在預覽類的surfaceChanged()回調方法重新啟動。
public void setCamera(Camera camera) {if (mCamera == camera) { return; }stopPreviewAndFreeCamera();mCamera = camera;if (mCamera != null) {List<Size> localSizes = mCamera.getParameters().getSupportedPreviewSizes();mSupportedPreviewSizes = localSizes;requestLayout();try {mCamera.setPreviewDisplay(mHolder);} 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();} }修改相機設置
相機設置可以改變相機拍照的方式,從縮放等級到曝光補償?shù)鹊取O旅娴氖纠皇歉牧祟A覽的大小;請查看相機應用的源代碼獲取更多可能。
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(mPreviewSize.width, mPreviewSize.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(); }設置預覽方向
大多數(shù)的相機應用將展示鎖定在了水平方向,因為這是相機傳感器的自然方向。這個設置并不能阻止你在垂直方向上拍攝,因為相機的方向會被記錄到EXIF的頭部。setCameraDisplayOrientation()方法允許你改變如何展示預覽,而不受圖像記錄方向的影響。然而,在API14之前,在改變方向之前必須停止預覽,然后在重新啟動它。
拍照
一旦預覽啟動后,可以使用Camera.takePicture()方法來拍一張照片。你可以創(chuàng)建Camera.PictureCallback對象和Camera.ShutterCallback對象然后將它們傳遞給Camera.takePicture()方法。
重啟預覽
在拍了一張照片之后,你必須在用戶拍另一張照片之前重新啟動預覽。在這個例子中,通過重寫快門按鈕來完成重啟。
@Override public void onClick(View v) {switch(mPreviewState) {case K_STATE_FROZEN:mCamera.startPreview();mPreviewState = K_STATE_PREVIEW;break;default:mCamera.takePicture( null, rawCallback, null);mPreviewState = K_STATE_BUSY;} // switchshutterBtnConfig(); }停止預覽并且釋放相機
一旦你的程序不再需要使用相機,這時就需要執(zhí)行清理工作。尤其是你需要釋放相機對象,否則會使其它程序面臨崩潰的風險,包括你自己程序中新的實例。
何時應該停止預覽并釋放相機呢?好吧,當預覽界面被銷毀的時候便是停止預覽并釋放相機的最佳時機,就像下面Preview類中顯示的那樣:
public void surfaceDestroyed(SurfaceHolder holder) {// Surface will be destroyed when we return, so stop the preview.if (mCamera != null) {// Call stopPreview() to stop updating the preview surface.mCamera.stopPreview();} } /*** When this function returns, mCamera will be null.*/ private void stopPreviewAndFreeCamera() {if (mCamera != null) {// Call stopPreview() to stop updating the preview surface.mCamera.stopPreview();// Important: Call release() to release the camera for use by other// applications. Applications should release the camera immediately// during onPause() and re-open() it during onResume()).mCamera.release();mCamera = null;} }在上面的課程中,這段程序也是setCamera()方法的一部分,所以實例化一個相機總是從停止這段預覽開始的。
總結
以上是生活随笔為你收集整理的Android官方开发文档Training系列课程中文版:调用相机之控制相机的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【JavaWeb】JDBC的基本操作和事
- 下一篇: GNN学习二