直接控制硬件需要比使用相机应用使用更多的代码来实现。但为了实现特定的应用和将一些功能完全的集成到你的应用程序中,你必须要这么做。
1.打开相机对象。
首先需要获得Camera对象实例。就像Android自身的相机应用一样,在OnCreate()方法中,建立新的线程来代开Camera。我们经常在OnResume()方法中实现,在OnResume()方法中实现的好处是使代码可以被在次使用和简化控制流。调用Camera.open(),如果Camera已经在使用,就抛出一个异常:
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.创建相机预览。在拍照之前,我们需要提供预览功能,这个功能由SurfaceView实现。
为了实现预览,我们需要实现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);
}
...
}
设置和开启预览。在开始预览之前,我们必须要将预览类传递给camera对象。
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();
}
}
修改相机设置。下面代码是预览大小的设置代码:
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();
}
使用setCameraDisplayOrientation()设置相机显示的方向。使用Camera.takePicture()来拍照。
重新预览:
@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();
}
停止预览释放相机:
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;
}
}