글
카메라 제어
우선 카메라 Object를 얻어야 한다. Open을 할 때 UI Thread에서 하면 안된다.
다른 앱이 카메라를 사용중이거나 다른 문제가 있을 경우 아래 코드의 try에 걸리게 된다.
API Level 9 이상에서는 멀티 카메라를 지원하므로 ID값을 입력하지만, 그 이전 API에서는 open()하면 첫번째 뒷면 카메라의 Object가 나온다.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;
}
}카메라가 찍는 영상을 화면에 미리보기는 SurfaceView에 하게 되는데, 아래와 같이 구현해주면 된다.
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);
}}
(Preview Class 내부) setCamera()로 카메라 Object를 넘겨주면, startPreview()를 통해 미리보기가 시작된다.
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();
}
}- 카메라 관련 설정(줌 Level 등)이 변경되면, 아래와 같이 setParameters()를 이용해 미리보기를 변경할 수 있다. 아래 예제는 미리보기 View 크기 변경임.
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() 메소드를 사용한다. API Level 14 이전에는 방향 변경전에 미리보기를 중지하고, 설정 후 재시작해야 한다.
아래 코드는 현재 화면과 같은 방향으로 미리보기를 표시하기 위한 방법이다.public static void setCameraDisplayOrientation(Activity activity,
int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.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;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
- 사진은
Camera.takePicture()
을 통해서 찍을 수 있다.Camera.PictureCallback과
Camera.ShutterCallback
으로 결과를 받는다. - 연속적으로 사진 찍기는
Camera.PreviewCallback
을 통해서 할 수 있다. - 사진을 찍은 후에는 미리보기가 멈추므로, 미리보기를 다시 시작해줘야 한다.
카메라 사용 후 Release는 미리보기 SurfaceView가 Destroy 될 때 하면 좋다. 또한, onPause()에서도 Release를 해야 하며, onResume()에서 다시 카메라를 Open해야 한다. 위 setCamera()처럼 카메라 초기화시에도 항상 미리보기 및 카메라를 Release해야 한다.
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
// during onPause() and re-open() it during onResume()).
mCamera.release();
mCamera = null;
}
}
출처 : http://developer.android.com/