Android Camera API使用指南
阿新 • • 發佈:2018-12-12
1. Camera簡介
雖然前文說道Android在5.0之後就推出了Camera2 API,但是各個廠家的基本未適配,導致目前市場上大部分機型使用的仍然是Camera1 API。
PS:Android 9.0 Google強制要求各個平臺廠商(高通/MTK/華為等)支援Camera2,不再相容Camera1。
Camera API是Android非常古老的API,Google在5.0推出Camera2後就再也沒有更新Camera。相比於Camera2來說,Camera API使用非常簡單,由於這套框架使用很久了所以穩定性和相容性還是值得信賴的。另外Camera API只提供基本的功能,其曝光/白平衡/曝光基本無法調節,這是相對於Camera2來說比較弱的地方。
2. Camera使用
有一點需要注意的是: Camera裝置是獨佔,也就是說你的APP在使用Camera裝置的話,其它應用就沒法使用。 所以要求在APP切換到後臺時需要關閉Camera裝置,重入時在重新開啟。
2.1 Camera主要類
Camera
Camera可以說是底層相機裝置的對映,所有對相機裝置的操作都是通過Camera這個類完成。 常用方法:
- open 開啟相機裝置,並返回一個Camera物件。
- getParameters 獲取Camera.Parameters
- setParameters 設定Camera.Parameters
- setPreviewTexture 設定用於輸出的SurfaceTexture
- startPreview 開始預覽
- stopPreview 結束預覽
- release 釋放裝置
Camera.Parameters
儲存Camera裝置支援的資料,允許使用者設定響應的引數(主要是影象大小、格式、預覽FPS等)。
2.2 Camera 操作流程
2.2.1 獲取Camera許可權
- APP Manifest 宣告
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.permission.camera"/>
- 程式碼中許可權檢查
/** 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;
}
}
2.2.2 開啟Camera
開啟Camera比較簡單,需要注意兩件事:
- 可以選擇要開啟的是前置還是後置相機,用CameraFacing標識:
public static final int CAMERA_FACING_BACK = 0;
public static final int CAMERA_FACING_FRONT = 1;
- 在開啟Camera之前需要檢查是否已經開啟
try {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.FROYO) {
int numberOfCameras = Camera.getNumberOfCameras();
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == facing) {
mDefaultCameraID = i;
mFacing = facing;
}
}
}
stopPreview();
if (mCameraDevice != null)
mCameraDevice.release();
if (mDefaultCameraID >= 0) {
mCameraDevice = Camera.open(mDefaultCameraID);
} else {
mCameraDevice = Camera.open();
mFacing = Camera.CameraInfo.CAMERA_FACING_BACK; //default: back facing
}
mRotation = setOrientationDegrees(0);
TELogUtil.d(TAG, "Camera rotation = " + mRotation);
} catch (Exception e) {
TELogUtil.e(TAG, "Open Camera Failed!");
e.printStackTrace();
mCameraDevice = null;
return false;
}
2.2.3 配置Camera
Camera開啟後可以配置 Camera.Parameters: 以設定影象大小的操作順序為例:
- 獲取Camera.Parameters
param = camera.getParameters();
- 查詢裝置支援情況
List<Camera.Size> prevSizes = params.getSupportedPreviewSizes();
- 修改Camera.Parameters
prevSize = getBestMatchSize(prevSizes, desireSize);
params.setPreviewSize(prevSize.width, prevSize.height);
- 把Camera.Parameters設定給Camera
camera.setParameters(params);
常用的配置項:
//影象格式
mParams.setPictureFormat(ImageFormat.NV21);
//影象解析度
mParams.setPreviewSize(prevSz.width, prevSz.height);
//預覽幀率
mParams.setPreviewFrameRate(30);
//對焦方式
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
mParams.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
2.2.4 開始預覽
Camera的輸出支援多種方式:
- SurfaceTexture:以紋理的形式輸出 設定Camera.setPreviewTexture(surfaceTexture) 通過SurfaceTexture的onFrameAvailable回撥輸出每一幀
- Buffer:以Buffer形式輸出 通過Camera.setPreviewCallbackWithBuffer(buffer)介面輸出
- Surface:輸出到Surface 通過設定Camera.setPreviewDisplay(surfaceHolder);
下面是SurfaceTexture輸出程式碼示例:
public synchronized void startPreview(SurfaceTexture texture) {
TELogUtil.i(TAG, "Camera startPreview...");
if (mIsPreviewing) {
TELogUtil.w(TAG, "Camera is previewing...");
// stopPreview();
return;
}
if (mCameraDevice != null) {
try {
mCameraDevice.setPreviewTexture(texture);
mCameraDevice.startPreview();
mIsPreviewing = true;
} catch (Exception e) {
e.printStackTrace();
TELogUtil.e(TAG, "startPreview: Error " + e.getMessage());
mIsPreviewing = false;
try {
mCameraDevice.release();
} catch (Exception e2) {
e2.printStackTrace();
}
mCameraDevice = null;
}
}
}
2.2.5 關閉Camera
mCameraDevice.stopPreview();
mCameraDevice.close()