Android Camera API和Android版本一樣纯露,也是碎片化比較嚴重剿骨,所以Google官方推出了CameraView,提供給開發(fā)者參考和學(xué)習(xí)埠褪,現(xiàn)在最新的可以使用Jetpack CameraX來開發(fā)浓利,大大簡化了開發(fā)的復(fù)雜度。本系列從Camera1->Camera2->CameraView->CameraX钞速,一步步講解Camera的進化過程贷掖,本篇先介紹Camera1的使用。
相機開發(fā)的流程:
- 檢測設(shè)備攝像頭渴语,打開相機
- 創(chuàng)建預(yù)覽畫面苹威,顯示實時預(yù)覽畫面
- 設(shè)置相機參數(shù),進行拍照監(jiān)聽
- 監(jiān)聽中驾凶,保存圖片資源或者直接操作原始數(shù)據(jù)
- 釋放相機資源
上面的是基本的相機開發(fā)流程屠升,不同的Camera API在實現(xiàn)上會有不同,整體流程上還是統(tǒng)一的狭郑。
Camera1使用
權(quán)限聲明
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
<uses-permission android:name="android.permission.CAMERA" />
相機必須聲明CAMERA
權(quán)限腹暖,在Android6.0上,你還需要在代碼中動態(tài)申請權(quán)限
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA},
REQUEST_CAMERA_PERMISSION);
開發(fā)流程
打開相機
Camera.open()
該方法的系統(tǒng)源碼實現(xiàn)
public static Camera open() {
int numberOfCameras = getNumberOfCameras();
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
return new Camera(i);
}
}
return null;
}
這里會檢查可用的攝像頭翰萨,默認使用的CameraInfo.CAMERA_FACING_BACK
后置攝像頭
創(chuàng)建預(yù)覽畫面
這里使用的是SurfaceView
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
...
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
...
startPreview();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
releaseCamera();
}
});
...
private void startPreview() {
try {
//設(shè)置實時預(yù)覽
mCamera.setPreviewDisplay(mSurfaceHolder);
//Orientation
setCameraDisplayOrientation();
//開始預(yù)覽
mCamera.startPreview();
startFaceDetect();
} catch (Exception e) {
e.printStackTrace();
}
}
設(shè)置預(yù)覽的時候脏答,可以設(shè)置setPreviewCallback
監(jiān)聽預(yù)覽數(shù)據(jù)的回調(diào)
void onPreviewFrame(byte[] data, Camera camera);
設(shè)置相機參數(shù)
設(shè)置相機參數(shù)后,需要重新啟動預(yù)覽,這邊在初始化的時候殖告,已經(jīng)設(shè)置好了阿蝶。
private void initParameters(final Camera camera) {
mParameters = camera.getParameters();
mParameters.setPreviewFormat(ImageFormat.NV21); //default
if (isSupportFocus(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
} else if (isSupportFocus(Camera.Parameters.FOCUS_MODE_AUTO)) {
mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
}
//設(shè)置預(yù)覽圖片大小
setPreviewSize();
//設(shè)置圖片大小
setPictureSize();
camera.setParameters(mParameters);
}
Camera.Parameters可以設(shè)置的參數(shù)非常多,這里就介紹幾個比較常用的
1.setFocusMode
設(shè)置對焦模式
- FOCUS_MODE_AUTO:自動對焦
- FOCUS_MODE_INFINITY:無窮遠
- FOCUS_MODE_MACRO:微距
- FOCUS_MODE_FIXED:固定焦距
- FOCUS_MODE_EDOF:景深擴展
- FOCUS_MODE_CONTINUOUS_PICTURE:持續(xù)對焦(針對照片)
- FOCUS_MODE_CONTINUOUS_VIDEO:(針對視頻)
2.setPreviewSize
設(shè)置預(yù)覽圖片大小
3.setPreviewFormat
支持的格式:
- ImageFormat.NV16
- ImageFormat.NV21
- ImageFormat.YUY2
- ImageFormat.YV12
- ImgaeFormat.RGB_565
- ImageFormat.JPEG
如果不設(shè)置黄绩,默認返回NV21的數(shù)據(jù)
4.setPictureSize
設(shè)置保存圖片的大小
5.setPictureFormat
設(shè)置保存圖片的格式羡洁,格式和setPreviewFormat
一樣
6.setDisplayOrientation
設(shè)置相機預(yù)覽畫面旋轉(zhuǎn)的角度,degress取值0爽丹,90筑煮,180,270
7.setPreviewDisplay
設(shè)置實時預(yù)覽SurfaceHolder
8.setPreviewCallback
監(jiān)聽相機預(yù)覽數(shù)據(jù)回調(diào)
9.setParameters
設(shè)置相機的Parameters
其他一些設(shè)置粤蝎,大家可以查看Android文檔進行相應(yīng)的設(shè)置
設(shè)置方向
設(shè)置相機的預(yù)覽方向真仲,orientation比較詳細的介紹
private void setCameraDisplayOrientation() {
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
Camera.getCameraInfo(mCameraId, cameraInfo);
int rotation = getWindowManager().getDefaultDisplay().getRotation(); //自然方向
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result;
//cameraInfo.orientation 圖像傳感方向
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (cameraInfo.orientation + degrees) % 360;
result = (360 - result) % 360;
} else {
result = (cameraInfo.orientation - degrees + 360) % 360;
}
mOrientation = result;
//相機預(yù)覽方向
mCamera.setDisplayOrientation(result);
}
拍照
private void takePicture() {
if (null != mCamera) {
mCamera.takePicture(new Camera.ShutterCallback() {
@Override
public void onShutter() {
}
}, new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
//base data
}
}, new Camera.PictureCallback() {
@Override
public void onPictureTaken(final byte[] data, Camera camera) {
mCamera.startPreview();
//save data
}
});
}
}
takePicture的源碼實現(xiàn):
public final void takePicture(ShutterCallback shutter, PictureCallback raw,
PictureCallback jpeg) {
takePicture(shutter, raw, null, jpeg);
}
- shutter(ShutterCallback):快門按下后的回調(diào)
- raw(PictureCallback):raw圖像數(shù)據(jù)
- jpeg(PictureCallback):jpeg圖像生成以后的回調(diào)
釋放相機資源
在使用完成后,onPause或者onDestory中進行相機資源的釋放
private void releaseCamera() {
if (null != mCamera) {
mCamera.stopPreview();
mCamera.stopFaceDetection();
mCamera.setPreviewCallback(null);
mCamera.release();
mCamera = null;
}
}
- stopPreview:停止預(yù)覽
- release:釋放資源
Camera1的開發(fā)上初澎,還是相對比較簡單的秸应,需要定制的功能項比較少,下面一篇開始介紹Camera2的使用碑宴。
文章中涉及到的代碼