我已经通过以下方式创建了一个CapturePreview类和CameraManager类:
CapturePreview:
public class CaptureView extends SurfaceView implements Callback{
private final SurfaceHolder surfaceHolder;
FileReaderWriter fileRW;
int frameCount;
private static final int MSG_FRAME_REFRESHED = 1;
private static final int MSG_AUTOFOCUS = 2;
private final CameraManager mCameraManager;
private boolean mRecording;
public CaptureView(Context context, AttributeSet attrs)
{
super(context, attrs);
surfaceHolder = getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
CameraManager.init(context);
mCameraManager = CameraManager.get();
init(context);
}
public CaptureView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
surfaceHolder = getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceHolder.setSizeFromLayout();
CameraManager.init(context);
mCameraManager = CameraManager.get();
init(context);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
mCameraManager.startPreview();
//mCameraManager.requestPreviewFrame(mCameraHandler, MSG_FRAME_REFRESHED);
mCameraManager.requestAutoFocus(mCameraHandler, MSG_AUTOFOCUS);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try
{
mCameraManager.openDriver(surfaceHolder);
}
catch(Exception e)
{
//TODO: display error
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCameraManager.stopPreview();
}
private void init(Context context)
{
setFocusable(true);
mRecording = false;
fileRW = new FileReaderWriter();
frameCount = 0;
}
public void setRecording(boolean isRecording) {
this.mRecording = isRecording;
}
public boolean isRecording() {
return mRecording;
}
private Handler mCameraHandler = new CameraHandler();
private class CameraHandler extends Handler
{
@Override
public void handleMessage(Message msg)
{
switch(msg.what)
{
case MSG_FRAME_REFRESHED:
// String path = "JPGFrame" + frameCount;
// fileRW.setPath(path);
// fileRW.WriteToFile((byte[]) msg.obj);
// frameCount++;
break;
}
}
}
}
CameraManager:
public final class CameraManager {
@Override
protected void finalize() throws Throwable {
closeDriver();
super.finalize();
}
private static final String TAG = "CameraManager";
private static CameraManager mCameraManager;
private Camera mCamera;
private final Context mContext;
private Point mScreenResolution;
private Rect mFramingRect;
private Handler mPreviewHandler;
private int mPreviewMessage;
private Handler mAutoFocusHandler;
private int mAutoFocusMessage;
private boolean mPreviewing;
public static synchronized void init(Context context) {
if (mCameraManager == null) {
mCameraManager = new CameraManager(context);
mCameraManager.getScreenResolution();
}
}
public static CameraManager get() {
return mCameraManager;
}
private CameraManager(Context context) {
mContext = context;
mCamera = null;
mPreviewing = false;
}
public void openDriver(SurfaceHolder holder) throws IOException {
// "throws IOException added to accommodate Android 1.5
if (mCamera == null) {
mCamera = Camera.open();
setCameraParameters();
mCamera.setPreviewDisplay(holder);
}
}
public void closeDriver() {
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
public void startPreview() {
if (mCamera != null && !mPreviewing) {
mCamera.startPreview();
mPreviewing = true;
}
}
public void stopPreview() {
if (mCamera != null && mPreviewing) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mPreviewHandler = null;
mAutoFocusHandler = null;
mPreviewing = false;
}
}
public void requestPreviewFrame(Handler handler, int message) {
if (mCamera != null && mPreviewing) {
mPreviewHandler = handler;
mPreviewMessage = message;
mCamera.setPreviewCallback(previewCallback);
}
}
public void requestAutoFocus(Handler handler, int message) {
if (mCamera != null && mPreviewing) {
mAutoFocusHandler = handler;
mAutoFocusMessage = message;
mCamera.autoFocus(autoFocusCallback);
}
}
public Rect getFramingRect() {
if (mFramingRect == null) {
int size = ((mScreenResolution.x < mScreenResolution.y) ? mScreenResolution.x :
mScreenResolution.y) * 3 / 4;
int leftOffset = (mScreenResolution.x - size) / 2;
int topOffset = (mScreenResolution.y - size) / 2;
mFramingRect = new Rect(leftOffset, topOffset, leftOffset + size, topOffset + size);
}
return mFramingRect;
}
PreviewCallback previewCallback = new PreviewCallback()
{
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
if(mPreviewHandler != null)
{
Message message = mPreviewHandler.obtainMessage(mPreviewMessage,
mScreenResolution.x, mScreenResolution.y, data);
message.sendToTarget();
}
}
};
AutoFocusCallback autoFocusCallback = new AutoFocusCallback()
{
@Override
public void onAutoFocus(boolean success, Camera camera) {
if(mAutoFocusHandler != null)
{
Message message = mAutoFocusHandler.obtainMessage(mAutoFocusMessage, success);
message.sendToTarget();
}
}
};
private void setCameraParameters() {
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mScreenResolution.x, mScreenResolution.y);
parameters.setPictureFormat(PixelFormat.JPEG);
parameters.setPreviewFormat(PixelFormat.JPEG);
mCamera.setParameters(parameters);
}
private Point getScreenResolution() {
if (mScreenResolution == null) {
WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
mScreenResolution = new Point(display.getWidth(), display.getHeight());
}
return mScreenResolution;
}
}
视频预览可以正常工作,直到子活动在主活动中开始。当子活动开始时,将调用CaptureView.surfaceDestroyed(SurfaceHolder holder)
并停止视频预览。然后,当子活动关闭时,执行CaptureView.surfaceCreated(SurfaceHolder holder)
,但视频预览不会启动。
有人知道如何修复问题,以便在执行surfaceDestroyed(SurfaceHolder holder)后成功重启视频预览吗?
谢谢!
答案 0 :(得分:2)
您必须在'surfaceDestroyed'处释放相机,因为您试图在'surfaceCreated'中再次获取对它的访问权限,如果已经获得相机,则会引发异常。