編輯:關於Android編程
在這節課程中,我們討論如何使用框架的API來直接控制照相機。
直接控制一個設備的照相機需要比從已經存在的照相機應用程序中請求圖片或者音頻需要更多的代碼。然而,如果你想構建一個指定的照相機應用程序,或者在你的應用程序中完全集成,這節課程向你展示如何實現。
獲取Camera對象的一個實例,是直接控制相機過程的第一步。正如Android自己的相機應用程序,訪問照相機要求的方式是,在onCreate()方法中啟動一個單獨的線程中打開Camera。這種方式是一個好的注意,因為它需要一段時間,並且在UI線程中陷入困境。 在一個更基礎的實現中,打開照相機可以被延期到onResume()方法,促進代碼重用並保持簡單的流控制。
如果照相機已經被其它的應用程序使用,調用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 Level
9開始,照相機框架支持多個照相機。如果你使用遺留額API並不使用參數調用onpen()方法,你第一個後方照相機。
你的用戶在點擊快門之前查看它們的題材的一個預覽,是照相的通常要求。為了實現它,你能使用一個SurfaceView來繪制照相機傳感器抓取的預覽。
為了開始顯示一個預覽,你需要預覽類。預覽要求一個android.view.SurfaceHolder.Callbak接口的實現,它被用戶從照相機硬件往你的應用程序傳遞圖片數據。
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對象,如下面的章節顯示。
一個照相機實例和它的相關的預覽必須在一個指定的順序被創建,照相機對象在先。在下面的代碼塊,初始化照相機的過程被封裝,以至於Camera.startPreview()方法在setCamera()方法中被調用,無論用戶什麼時候改變相機。預覽也必須在預覽類的surfaceChanged()回調方法中被重啟。
public void setCamera(Camera camera) {
if (mCamera == camera) { return; }
stopPreviewAndFreeCamera();
mCamera = camera;
if (mCamera != null) {
List 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();
}
} 修改相機設置
————————————————————————————————————————————————————————————
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頭中被記錄。setCameraDisplayOrientaion()方法讓你改變預覽的顯示,而不影響記錄的圖片。然而,在Android早期API level 14的時候,你必須在改變方向之前停止你的預覽,然後重啟它。
一旦預覽啟動,使用Camera.takePicture()方法來拍一張照片。你能創建Camera.PictureCallback和Camera.ShutterCallbak對象,並將它們傳遞到Camera.tackPicture()方法。
如果你想持續不斷的抓取照片,你可以創建一個Camera.PreviewCallback,它實現了onPreviewFrame()方法。在兩者之間,你能捕獲僅僅被選中的預覽框架,或者在調用tackPicture()方法中設置一個延遲動作。
在拍玩一張照片之後,你必須在用戶拍其它照片的之前重啟預覽。在這個例子中,通過覆蓋快門按鈕執行重啟。
@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對象,或者你可能會是其它應用程序崩潰,包括你自己的應用程序的新的實例。
當你應該停止預覽和釋放照相機的時候?那麼,你的預覽界面被銷毀是一個好的暗示,是停止預覽和釋放照相機的時候,正如在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 in onPause() (and re-open() it in
onResume()).
*/
mCamera.release();
mCamera = null;
}
}
Android Studio 中build.gradle文件的詳細解析
在由Eclipse轉到Android Studio之後,第一個讓我感到困惑的是build.gradle這個文件了,實在話,當時我並不知道這麼寫是幾個意思。 ap
Android Canvas練習(3)自已繪柱形圖
繪完報表,餅圖,接下來就繪制柱形圖,柱形很容易,就是畫線和框就行了。我分別繪制一個豎向的,一個橫向的柱形圖。 效果圖如下: package com.xcl
Android之帶group指示器的ExpandableListView(自寫)
我們都知道Android缺省的ExpandableListView的group header無法固定在界面上,當向下滾動後,不能對當前顯示的那些child 指示出它們歸屬
Android 錯誤集錦(ing...)
系統環境: Windows7 64位 問題描述: Eclipse真機無法打印log信息 錯誤提示: 解決方案: wi