views:

1268

answers:

2

Hi,

I have created a CapturePreview class and CameraManager class the following way:

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;
  }

}

The video preview works fine this way until the sub-activity starts in the main activity. When sub-activity starts the CaptureView.surfaceDestroyed(SurfaceHolder holder) is called and the video preview stops. Then when the sub-activity closes the CaptureView.surfaceCreated(SurfaceHolder holder) is executed, but the video preview doesn't start.

Does anyone know how to fix the problem in order to successfully restart video preview after surfaceDestroyed(SurfaceHolder holder) is executed?

Thanks!

+1  A: 

You must release the camera at 'surfaceDestroyed' seeing as you are trying to acquire access to it again in 'surfaceCreated', which would throw you an exception if the camera is already acquired.

WXY
A: 

my "previewcallback" nerver be called in my HTC android phone,but it can in emulator.how can I fix it?

westice