Android 相机 takePicture() 失败

Posted

技术标签:

【中文标题】Android 相机 takePicture() 失败【英文标题】:Android Camera takePicture() failed 【发布时间】:2016-04-05 19:26:01 【问题描述】:

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

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

这里是活动变量、图片方法和相机拍照代码(在 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$5.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)

在论坛搜索了几个小时后,我完全迷失了方向,我们将不胜感激。

【问题讨论】:

【参考方案1】:

相机操作不是即时的,而且通常不是同步的。一些设备需要在 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();

【讨论】:

【参考方案2】:

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

您可以看看这个CameraFragment Sample 作为开始相机预览等的参考。

【讨论】:

以上是关于Android 相机 takePicture() 失败的主要内容,如果未能解决你的问题,请参考以下文章

mCamera.takePicture(null, null, mPicture) 不起作用

Cordova 和 proguard:takePicture 上的相机插件 NPE

android静音相机快门声音?

致命异常:java.lang.RuntimeException:takePicture 失败

在android中使用自定义相机拍照

Android中的相机,如何获得最佳尺寸,预览尺寸,图片尺寸,视图尺寸,图像失真