標籤:
郭孝星
微博:郭孝星的新浪微博
郵箱:[email protected]
部落格:http://blog.csdn.net/allenwells
Github:https://github.com/AllenWells
一 啟用相機1.1 請求相機許可權
<manifest ... > <uses-feature android:name="android.hardware.camera" android:required="true" /> ...</manifest>
如果我們的App使用相機,但相機並不是應用的正常運行所必不可少的組件,可以將android:required 設定為false。這樣的話,Google Play也會允許沒有相機的裝置下載該應用。當然在有必要在使用相機之前通過調用以下方法:
hasSystemFeature(PackageManager.FEATURE_CAMERA);
來檢查裝置上是否有相機。如果沒有,我們應該禁用和相機相關的功能。
1.2 建立Intent對象
利用一個描述了做什麼的Intent對象,Android可以將某些執行任務委託給其他應用。整個過程包含三部分:
- Intent本身
- 一個函數調用來啟動外部的 Activity
- 當焦點返回到你的Activity時,處理返回映像資料的代碼。
舉例
發送一個Intent來錄製視頻
static final int REQUEST_VIDEO_CAPTURE = 1;private void dispatchTakeVideoIntent() { Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);//注意在調用startActivityForResult()方法之前,先調用resolveActivity(),這個方法會返回能處理該Intent的第一個Activity,即即檢查有沒有能處理這個Intent的Activity。執行這個檢查是必要的,因為如果你調用startActivityForResult()時,沒有應用能處理該Intent,應用將會崩潰。所以只要返回結果不為null,使用該Intent就是安全的。 if (takeVideoIntent.resolveActivity(getPackageManager()) != null) { startActivityForResult(takeVideoIntent, REQUEST_VIDEO_CAPTURE); }}
1.3 查看視頻
Android的相機程式會把指向視頻儲存地址的Uri添加到Intent中,並傳送給onActivityResult())方法。
舉例
擷取該視頻並顯示到一個VideoView當中。
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_VIDEO_CAPTURE && resultCode == RESULT_OK) { Uri videoUri = intent.getData(); mVideoView.setVideoURI(videoUri); }}
二 控制相機2.1 開啟相機對象
擷取一個Camera對象是直接控制相機的第一步。正如Android內建的相機程式一樣,訪問相機推薦的方式是在onCreate())方法裡面另起一個線程來開啟相機。這種辦法可以避免因為啟動時間較長導致UI線程被阻塞。還有一種更好的方法,可以把開啟相機的操作延遲到onResume())方法裡面去執行,這樣使得代碼更容易重用,並且保持控制流程程簡單。
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; }}
2.2 建立相機預覽介面
拍照通常需要向使用者提供一個預覽介面來顯示待拍攝的事物,我們可以使用SurfaceView來展現照相機採集的映像。
//為了顯示一個預覽介面,我們需要建立一個Preview類。這個類需要實現 android.view.SurfaceHolder.Callback介面,用這個介面把相機硬體擷取的資料傳遞給程式,該Preview類必須在映像即時預覽開始之前傳遞給Camera對象。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); }...}
Preview建立後,接下來我們就可以設定和啟動Preview。Camera執行個體與它相關的Preview必須以特定的順序來建立,其中Camera對象首先被建立。
舉例
將初始化Canera的動作封裝起來
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(); }}
2.3 修改相機設定
相機設定可以改變拍照的方式。
舉例
改變預覽大小,如下所示:
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();}
大多數相機程式會鎖定預覽為橫屏狀態,因為該方向是相機感應器的自然方向。當然這一設定並不會阻止拍豎屏的照片,因為裝置的方向資訊會被記錄在EXIF頭中。setCameraDisplayOrientation())方法可以讓你在不影響照片拍攝過程的情況下,改變預覽的方向。然而,對於Android API Level 14及以下版本的系統,在改變方向之前,必須先停止預覽,然後再去重啟它。
2.4 拍攝照片
預覽開始之後,可以進行照片的拍攝。
拍攝照片:調用Camera.takePicture(),將建立的Camera.PictureCallback與Camera.ShutterCallback對象傳遞到該方法內。
連續拍攝照片:調用Camera.takePicture(),建立一個Camera.PreviewCallback並實現onPreviewFrame()方法。我們可以拍攝選中的預覽幀,或是為調用takePicture())建立一個延遲。
在拍攝好圖片後,你必須在使用者拍下一張圖片之前重啟預覽。
舉例
利用快門來實現重啟,如下所示:
@Overridepublic 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; } // switch shutterBtnConfig();}
2.5 停止預覽並釋放相機
當程式使用相機完畢後,有必要做清理的動作。特別地,必須釋放Camera對象,不然可能會引起其他應用崩潰,包括我們自己應用的新執行個體。在預覽的Surface被銷毀之後,可以做停止預覽並釋放相機的動作。
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; }}
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
【Android應用開發技術:媒體開發】錄影