構建一個Camera應用程式
某些開發可能想要在他們的應用中定製Camera的使用者介面,或者要提供一些特殊的功能。建立定製化的Activity比使用Intent需要更多的代碼,但它能夠給你的戶提供更好的體驗。
以下是建立定製化的Camera介面的一般步驟:
1. 檢查和訪問Camera:建立代碼來檢查Camera和所申請訪問的存在性;
2. 建立一個預覽類:繼承SurfaceView來建立一個Camera的預覽類,並實現SurfaceHolder介面。這個類用來預覽來之Camera的實施映像。
3. 構建一個預覽布局:一旦有了Camera預覽類,就可以把這個預覽類和你想要的使用者介面控制結合在一起來建立一個視圖布局。
4. 針對採集建立監聽:把監聽器與響應使用者動作(如按下按鈕)的介面控制串連到一起來啟動映像或視頻的採集。
5. 採集和儲存檔案:針對真正採集的圖片或視頻,以及輸出的儲存來編寫代碼。
6. 釋放Camera:使用Camera之後,你的應用程式必須釋放Camera,以便其他應用程式能夠使用。
Camera硬體是一個必須要認真管理的共用資源,因此你的應用程式在使用它時,不能跟其他應用程式發生衝突。下文將討論如何檢查Camera硬體、如何申請對Camera的訪問,如何採集圖片和視頻,以及在應用使用完成後如何釋放Camera。
警告:在應用程式使用完Camera時,要記住通過調用Camera.release()方法來釋放Camera對象。如果你的應用程式沒有正確的釋放Camera,所有的後續的視圖對Camera的訪問,包括你自己的應用程式,都會失敗,並可能到你的或其他的應用程式關閉。
檢查Camera硬體
如果你的應用程式沒有使用清單特別的聲明要使用Camera,那麼就應該在運行時檢查Camera是否有效。使用PackageManager.hasSystemFeature()方法,來執行這個檢查,如下例代碼所示:
/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
Android裝置能夠有多個Camera,例如用於攝影的背面Camera和用於視頻會話的前面Camera。Android2.3(API Level9)以後的版本允許你使用Camera.getNumberOfCameras()方法來檢查裝置上可用的Camera的數量。
訪問Camera
如果你已經判斷在應用程式所啟動並執行裝置上有Camera,你必須擷取通過Camera執行個體才能申請訪問它(除非使用Intent來訪問Camera)。
使用Camera.open()方法來訪問主Camera,並確保要捕獲任何異常,如下例代碼所示:
/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
}
catch (Exception e){
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}
警告:在使用Camera.open()時,要始終檢查異常。如果沒有檢查Camera是否被使用或是否存在,會導致你的應用程式被系統關閉。
在運行Android2.3(API Level9)以上的裝置上,你能夠使用Camera.open(int)方法來訪問指定的Camera。上面的範例程式碼訪問的是第一個Camera,也就是多個Camera的裝置上背面的那個Camera。
檢查Camera功能
一旦獲得了訪問Camera的許可權,就可以使用Camera.getParameters()方法來擷取更多的有關Camera能力的資訊,這個方法返回一個Camera.Parameters對象。在使用API Level9以上的版本時,使用Camera.getCameraInfo()方法來判斷Camera是在裝置的前面還是後面,以及映像的方向。
建立一個預覽類
對使用者有效拍照或錄影,必須是在裝置的Camera上能夠看到。Camera預覽類是一個SurfaceView類,它能夠即時的顯示來自Camera的映像資料,因此使用者能夠取景和採集圖片或視頻。
下例的範例程式碼示範了如何建立能夠被包含到View布局中的基本的Camera預覽類。為了捕獲建立和銷毀View的回調事件,這個類實現了SurfaceHolder.Callback介面,用於跟Camera的預覽輸入相匹配:
/** A basic Camera preview class */publicclassCameraPreviewextendsSurfaceViewimplementsSurfaceHolder.Callback{ privateSurfaceHolder mHolder; privateCamera mCamera; publicCameraPreview(Context context,Camera camera){ super(context); mCamera = camera; // Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. mHolder = getHolder(); mHolder.addCallback(this); // deprecated setting, but required on Android versions prior to 3.0 mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } publicvoid surfaceCreated(SurfaceHolder holder){ // The Surface has been created, now tell the camera where to draw the preview. try{ mCamera.setPreviewDisplay(holder); mCamera.startPreview(); }catch(IOException e){ Log.d(TAG,"Error setting camera preview: "+ e.getMessage()); } } publicvoid surfaceDestroyed(SurfaceHolder holder){ // empty. Take care of releasing the Camera preview in your activity. } publicvoid surfaceChanged(SurfaceHolder holder,int format,int w,int h){ // 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(mHolder.getSurface()==null){ // preview surface does not exist return; } // stop preview before making changes try{ mCamera.stopPreview(); }catch(Exception e){ // ignore: tried to stop a non-existent preview } // set preview size and make any resize, rotate or // reformatting changes here // start preview with new settings try{ mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); }catch(Exception e){ Log.d(TAG,"Error starting camera preview: "+ e.getMessage()); } }}
如果你要給你Camera預覽視窗設定一個特定的尺寸,可以像上面注釋中標註的那樣,設定surfaceChanged()方法。在設定預覽尺寸的時候,必須使用來自getSupportedPreviewSizes()方法的值,在setPreviewSize()方法中不能使用隨意的值。