Android 相机 takePicture() 失败

Android Camera takePicture() failed

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

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

下面是activity变量、图片方法、相机拍照代码(在onResume()中):

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

}

这是错误:

12-31 20:00:15.407    3244-5501/? E/Camera2Client﹕ takePicture: Camera 0: Cannot take picture without preview enabled
12-31 20:00:15.408    6988-6988/? W/System.err﹕ java.lang.RuntimeException: takePicture failed
12-31 20:00:15.408    6988-6988/? W/System.err﹕ at android.hardware.Camera.native_takePicture(Native Method)
12-31 20:00:15.408    6988-6988/? W/System.err﹕ at android.hardware.Camera.takePicture(Camera.java:1434)
12-31 20:00:15.408    6988-6988/? W/System.err﹕ at org.fawkes.fawkesrc.FawkesRCActivity.run(FawkesRCActivity.java:327)
12-31 20:00:15.408    6988-6988/? W/System.err﹕ at android.app.Activity.runOnUiThread(Activity.java:5524)
12-31 20:00:15.408    6988-6988/? W/System.err﹕ at org.fawkes.fawkesrc.FawkesRCActivity.onResume(FawkesRCActivity.java:298)
12-31 20:00:15.408    6988-6988/? W/System.err﹕ at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1258)
12-31 20:00:15.408    6988-6988/? W/System.err﹕ at android.app.Activity.performResume(Activity.java:6327)
12-31 20:00:15.408    6988-6988/? W/System.err﹕ at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3092)
12-31 20:00:15.408    6988-6988/? W/System.err﹕ at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3134)
12-31 20:00:15.408    6988-6988/? W/System.err﹕ at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2481)
12-31 20:00:15.408    6988-6988/? W/System.err﹕ at android.app.ActivityThread.-wrap11(ActivityThread.java)
12-31 20:00:15.408    6988-6988/? W/System.err﹕ at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
12-31 20:00:15.409    6988-6988/? W/System.err﹕ at android.os.Handler.dispatchMessage(Handler.java:102)
12-31 20:00:15.409    6988-6988/? W/System.err﹕ at android.os.Looper.loop(Looper.java:148)
12-31 20:00:15.409    6988-6988/? W/System.err﹕ at android.app.ActivityThread.main(ActivityThread.java:5417)
12-31 20:00:15.409    6988-6988/? W/System.err﹕ at java.lang.reflect.Method.invoke(Native Method)
12-31 20:00:15.409    6988-6988/? W/System.err﹕ at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
12-31 20:00:15.409    6988-6988/? W/System.err﹕ at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

在论坛上搜索了几个小时后,我完全迷路了,如有任何帮助,我们将不胜感激。

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

你可以看看这个CameraFragment Sample作为启动相机预览等的参考。

相机操作不是即时的,而且通常不是同步的。某些设备需要在 startPreview() 和 takePicture() 之间有明显的延迟,例如在 OnePlus One 上你至少需要 100ms。

对您的代码的最小修复可能是

    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();