編輯:關於android開發
本節課主要講述怎樣通過調用系統的framework APIs來控制設備的攝像頭操作。
相比調用系統內置的其他相機應用來拍照和攝像,自己編寫代碼來直接控制相機操作需要更多的工作,然而,如果您要設計一款專業的拍照應用,或者相機功能與您的UI界面進行深度整合,那麼您可以從本節課找到所需的知識。
自己編寫代碼控制相機的第一步就是獲得一個 實例對象,與Android系統內置的其他相機應用類似,推薦的方法是在方法中啟動一個新的線程來開啟相機,因為這個過程可能比較耗時,新啟一個線程來處理可以有效避免UI主線程的停頓,另一種方式是將開啟相機的過程推遲到 方法中,這樣便於代碼的重用和簡化流程控制。
如果此時有其他應用正在使用相機,那麼當您的程序調用方法 的時候會出現異常,需要進行捕獲( try block)。
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 level 9 開始,camera framework 支持用戶程序控制多個相機,如果您在調用方法 的時候沒有傳遞任何參數,那麼系統會默認啟動Androd設備的第一個後置攝像頭。
按下快門鍵拍照以前,用戶希望看到當前相機的預覽畫面,要實現此功能,那麼您可以使用SurfaceView,通過獲取實時的相機捕獲的數據並展示到界面上。
自定義預覽界面類型(Preview Class)
要創建一個預覽畫面,需要自定義一個畫面預覽類型(preview class)。您需要實現 android.view.SurfaceHolder.Callback 接口函數,相機捕獲的數據流會通過這個接口傳遞到負責顯示預覽畫面的程序中。
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); } ... }
在開啟相機的預覽操作前,您必須首先將自定義的預覽界面實例對象處傳遞給 實例對象,稍後會有介紹。
設置和開啟預覽(Set and Start the Preview)
創建Camera實例和創建與其綁定的預覽界面實例必須按照一個特定的順序,且創建Camera實例必須是第一步。下面的實例代碼中,將開啟相機的預覽操作封裝在一個函數中,這樣可以保證不論用戶什麼時候只要調用過 setCamera()方法更新了相機參數配置,用來開啟預覽功能的方法就會被調用,同樣在畫面大小變更的回調函數 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(); } }
在控制相機拍照的過程中可以修改相機的配置參數,比如放大倍率,曝光補償等等,示例代碼展示了修改相機的預覽畫面大小,如果想了解更多的配置參數請參閱Camera APP的源代碼。
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 header中。方法 可以用來改變預覽畫面的方向而不影響最終照片的拍攝方向。需要注意的是在API level 14之前,您需要首先停止預覽畫面,切換橫豎屏模式,再重新啟動預覽畫面。
在預覽的過程中,調用方法 來拍攝照片,可以創建 和 實例對象作為參數傳遞給方法 中。想要實現連續拍照,需要實現接口 中的函數,在實現代碼中,您可以捕獲當前選定的預覽幀,或者設定一個延遲時間來調用拍照函數 。
拍攝了一張照片以後,您必須重新啟動畫面預覽才可以繼續拍攝下一張照片,示例代碼展示了用戶按下快門鍵拍照後重新啟動預覽。
@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; } // switch shutterBtnConfig(); }
一旦您的應用使用完了相機,那麼應該及時釋放資源。特別地,需要釋放Camera 實例對象,否則可能會破壞其他應用程序的執行,包括您自己應用的重新啟動。
那麼哪個地方是最合適停止預覽與釋放Camera資源的呢?預覽畫面銷毀的回調函數中是個不錯的選擇。需要參照前面實現的自定義預覽類型( Preview class)。
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 in onPause() (and re-open() it in onResume()). */ mCamera.release(); mCamera = null; } }
本節課的開始部分,setCamera() 方法中,在初始化camera 實例之前總是首先停止預覽。
參考文摘:
原文:http://blog.zhourunsheng.com/2012/01/android-%e7%9b%b8%e7%89%87%e7%ae%a1%e7%90%86%e4%b8%93%e9%a2%98%e4%b9%8b%e7%9b%b8%e6%9c%ba%e6%93%8d%e4%bd%9c/ | 潤物無聲
Android 用Canvas畫textview、bitmap、矩形(裁剪)、橢圓、線、點、弧 初始化對象 private Paint mPaint;//畫筆 pri
Android性能優化之加快應用啟動速度 應用的啟動 啟動方式 通常來說,在安卓中應用的啟動方式分為兩種:冷啟動和熱啟動。 1、冷啟動:當啟動應用時,後台沒有該應用的進
RoundedBitmapDrawable生成圓角圖片, Bitmap src = BitmapFactory.decodeResource(getRes
違章查詢源碼分享,違章查詢源碼 使用快遞100查詢接口實現 源碼地址:https://github.com/chenjie200280/weizhang 測試