Android相机takePicture()失败

时间:2016-01-01 01:33:18

标签: android camera android-camera surfaceview

我一直在尝试使用Android中的Surface Preview使用相机拍照。 Surface Preview跨越布局中的整个屏幕。

每当我调用takePicture时,它都会失败并说我没有启用预览。

这里有活动变量,图片方法和摄像头拍照代码(它在onResume()中):

try {
    Parent.class.getMethod("display").invoke(parent);
} catch(SecurityException | NoSuchMethodException | IllegalArgumentException | IllegalAccessException | InvocationTargetException | ex) {
    // oops!
}

这就是错误:

public class FawkesRCActivity extends Activity implements SurfaceHolder.Callback {

  SurfaceView mSurfaceView;
  SurfaceHolder mHolder;
  public Camera mCamera;

  ...


  Camera.PictureCallback camHolla = new Camera.PictureCallback() {
    public void onPictureTaken(byte[] data, Camera camera) {
      String photoFile = "F_Auton.jpg";
      File sdDir = Environment
              .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);

      String filename =sdDir + File.separator + photoFile;

      File pictureFile = new File(filename);

      try {
        FileOutputStream fos = new FileOutputStream(pictureFile);
        fos.write(data);
        fos.close();
      } catch (Exception e) {
        Log.d("Errored:", e.getMessage());
      }

    }
  };

  public void setCamera(Camera camera) {
    if (mCamera == camera) { return; }

    stopPreviewAndFreeCamera();

    mCamera = camera;

    if (mCamera != null) {
      List<Camera.Size> localSizes = mCamera.getParameters().getSupportedPreviewSizes();
      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();
    }
  }

  @Override
  public void surfaceCreated(SurfaceHolder surfaceHolder) {

  }

  public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    mCamera.startPreview();
  }

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


  @Override
  protected void onResume() {
    FawkesRCActivity.this.runOnUiThread(new Runnable() {
      public void run() {
        mSurfaceView = (SurfaceView) findViewById(R.id.cameraPreview);
        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = mSurfaceView.getHolder();
        mHolder.addCallback(FawkesRCActivity.this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        // Search for the front facing camera
        int numberOfCameras = Camera.getNumberOfCameras();
        int camId=0;
        for (int i = 0; i < numberOfCameras; i++) {
          Camera.CameraInfo info = new Camera.CameraInfo();
          Camera.getCameraInfo(i, info);
          if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
            camId=i;
          }
        }
        if (safeCameraOpen(camId))Log.e("Camera","All Good"); else Log.e("Camera","Errored");
        try{
          SurfaceTexture surfaceTexture = new SurfaceTexture(0);
          mCamera.setPreviewTexture(surfaceTexture);
      //    mCamera.startPreview();
        }
        catch(Exception e){
          e.printStackTrace();
        }

        try {
          mCamera.takePicture(null, null, null, camHolla);
        }
        catch(Exception e){
          e.printStackTrace();
        }

      }
    });

    super.onResume();
  }

 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() {
    setCamera(null);
    if (mCamera != null) {
      mCamera.release();
      mCamera = null;
    }
  }

}

在搜索论坛几个小时后,我完全迷失了,任何帮助都会受到赞赏。

2 个答案:

答案 0 :(得分:0)

我不是专家,但我认为你在拍照之前没有给mCamera.startPreview()打电话。您可以尝试在此之前调用它。

您可以查看此CameraFragment Sample作为启动相机预览的参考,依此类推。

答案 1 :(得分:0)

摄像机操作不是即时的,通常不是同步的。一些设备在startPreview()和takePicture()之间需要很长的延迟,例如在OnePlus One上你需要至少100毫秒。

对代码的最小修复可能是

    try{
      SurfaceTexture surfaceTexture = new SurfaceTexture(0);
      mCamera.setPreviewTexture(surfaceTexture);
  //    mCamera.startPreview();
    }
    catch(Exception e){
      e.printStackTrace();
    }

mSurfaceView.postDelayed(new Runnable() {
    @Override
    public void run() {
        try {
            mCamera.takePicture(null, null, null, camHolla);
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }, 100);

        super.onResume();