Android ApiDemos示例解析(57):Graphics->CameraPreview

本例介紹瞭如何使用設備的攝像頭來預覽將要拍攝的照片,本例需要真實的手機來運行:

 

例子中用到兩個方面的知識:SurfaceView 和android.hardware.Camera。

SurfaceView 為View的子類,它提供一個專門用於繪圖的Surface,目的是允許使用工作線程中這個Surface上繪圖,這樣對於應費時的繪圖操作無需放在UI線程中,而是可以在單獨的工作線程中按照自己的節奏來繪圖。

使用SurfaceView時需要從SurfaceView派生一個子類,這個子類需要實現SurfaceHolder.Callback接口,這個接口提供瞭幾個回調函數用於通知應用關於Surface的消息,如什麼時候創建,改變大小,銷毀等。實現這些回調函數非常重要,應用可以在這些回調函數來調整Surface的一些說明,知道何時可以在Surface繪制等。通常在這個SurfaceView的派生類中會定義一個工作線程用於繪圖。

在Surface上繪圖時,不是通過直接的函數調用,而是通過獲取Surface句柄(SurfaceHolder)的間接方法.因此在Surface初始化時,調用getHolder()來獲取Surface的句柄。通常是在獲取SurfaceHolder之後,再調用mHolder.addCallback(this)來響應SurfaceHolder.Callback事件。

如何使用工作線程中Surface 的Canvas上繪制圖形本例沒有涉及,將在後面的例子說明。

下面代碼定義瞭SurfaceView子類並實現SurfaceHolder.Callback接口。

[java] 
class Preview extends SurfaceView implements SurfaceHolder.Callback {  
 SurfaceHolder mHolder;  
 Camera mCamera;  
…  
public void surfaceCreated(SurfaceHolder holder) {  
 // The Surface has been created, acquire the   
 // camera and tell it where   
 // to draw.   
 mCamera = Camera.open();  
 try {  
 mCamera.setPreviewDisplay(holder);  
 } catch (IOException exception) {  
 mCamera.release();  
 mCamera = null;  
 // TODO: add more exception handling logic here   
 }  
}  
   
public void surfaceDestroyed(SurfaceHolder holder) {  
 // Surface will be destroyed when we return,   
 //    so stop the preview.   
 // Because the CameraDevice object is not a   
 //shared resource, it's very   
 // important to release it when the activity is paused.   
 mCamera.stopPreview();  
 mCamera.release();  
 mCamera = null;  
}  
   
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();  
   
 List<Size> sizes = parameters.getSupportedPreviewSizes();  
 Size optimalSize = getOptimalPreviewSize(sizes, w, h);  
 parameters.setPreviewSize(optimalSize.width, optimalSize.height);  
   
 mCamera.setParameters(parameters);  
 mCamera.startPreview();  

class Preview extends SurfaceView implements SurfaceHolder.Callback {
 SurfaceHolder mHolder;
 Camera mCamera;

public void surfaceCreated(SurfaceHolder holder) {
 // The Surface has been created, acquire the
 // camera and tell it where
 // to draw.
 mCamera = Camera.open();
 try {
 mCamera.setPreviewDisplay(holder);
 } catch (IOException exception) {
 mCamera.release();
 mCamera = null;
 // TODO: add more exception handling logic here
 }
}
 
public void surfaceDestroyed(SurfaceHolder holder) {
 // Surface will be destroyed when we return,
 //    so stop the preview.
 // Because the CameraDevice object is not a
 //shared resource, it's very
 // important to release it when the activity is paused.
 mCamera.stopPreview();
 mCamera.release();
 mCamera = null;
}
 
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();
 
 List<Size> sizes = parameters.getSupportedPreviewSizes();
 Size optimalSize = getOptimalPreviewSize(sizes, w, h);
 parameters.setPreviewSize(optimalSize.width, optimalSize.height);
 
 mCamera.setParameters(parameters);
 mCamera.startPreview();
}

 

Camera 這裡使用的Camera類是定義在android.hardware包中代表的是攝像頭硬件設備,Camera類可以用來設置設備攝像頭的配置,開始/停止預覽,拍照或是視頻。這個類是Camera服務(用來管理實際設備的服務)的客戶端。

為瞭能使用設備的攝像頭,必須在AndroidManifest.xml中定義對應的權限permission和uses-feature如下:

<uses-permission android:name=”android.permission.CAMERA” />
<uses-feature android:name=”android.hardware.camera” />
<uses-feature android:name=”android.hardware.camera.autofocus” android:required=”false” />

使用Camera拍照的一般步驟如下:

調用open(int)獲取一個Camera的示例對象.
使用getParameters()獲取Camera 的缺省配置參數.
如果有需要,調用setParameters(Camera.Parameters)修改Camera的參數.
如果有需要,可以調用setDisplayOrientation(int)設置取景為縱向或是橫向。
將一個初始化過的SurfaceHolder通過setPreviewDisplay(SurfaceHolder),如果沒有指定Surface,Camera將無法開始預覽。
調用startPreview()開始屏幕預覽,拍照之前必須先開始預覽。
如需拍照可以調用takePicture(Camera.ShutterCallback, Camera.PictureCallback, Camera.PictureCallback, Camera.PictureCallback),拍照完成事件將以回調函數的方式通知應用。
拍照完成時,Camera自動停止預覽狀態,需調用startPreview來拍新的照片。
調用stopPreview()停止預覽。
最後不在使用Camera調用release()釋放資源以便其它應用可以使用Camera。
作者:mapdigit
 

發佈留言