三星手机拍照失败

5
我正在使用Xamarin为Android编写一个应用程序,其中包括一个自定义活动,用于使用Camera API捕获图片。我已在所有测试设备上成功运行此活动,但是一些用户报告说在尝试拍照时应用程序会完全崩溃。很快就明显这些用户都在使用三星手机,不幸的是我没有可用于测试的三星手机。
谢天谢地,我能够捕获异常和堆栈跟踪,但我对导致这个问题的原因感到困惑。下面是异常、堆栈跟踪和有问题的代码。
这是一个相当简单的活动,具有全屏相机预览、闪光灯切换和捕获按钮。它使用自定义的CameraHelper类来设置和与Camera API交互。在用户能够交互并触发TakePicture方法之前,相机会通过OnSurfaceTextureAvailable方法进行配置,并显示预览。 异常堆栈跟踪
java.lang.RuntimeException: takePicture failed
android.hardware.Camera.native_takePicture(Native Method):0
android.hardware.Camera.takePicture(Camera.java:1523):0
android.hardware.Camera.takePicture(Camera.java:1468):0
md5efa7d89b8a471e1a97a183b83296df21.CameraHelper.n_onAutoFocus(Native Method):0
md5efa7d89b8a471e1a97a183b83296df21.CameraHelper.onAutoFocus(CameraHelper.java:39):0

CameraHelper类中的方法

// Implements Camera.IPictureCallback and Camera.IAutoFocusCallback

public void OnSurfaceTextureAvailable(object sender, TextureView.SurfaceTextureAvailableEventArgs e)
{
  // Get the camera and set its orientation
  try
  {
    _camera = Camera.Open(_cameraInt);
  }
  catch (Exception ex)
  {
    _callback.OnInitializationFailed(ex);
    return;
  }

  var orientation = GetDisplayOrientation();
  _camera.SetDisplayOrientation(orientation);

  // Set the camera parameters
  var cameraParameters = _camera.GetParameters();

  if (cameraParameters.SupportedFocusModes != null && cameraParameters.SupportedFocusModes.Contains(Camera.Parameters.FocusModeContinuousPicture))
    cameraParameters.FocusMode = Camera.Parameters.FocusModeContinuousPicture;

  if (cameraParameters.SupportedFlashModes != null && cameraParameters.SupportedFlashModes.Contains(Camera.Parameters.FlashModeAuto))
  {
    cameraParameters.FlashMode = Camera.Parameters.FlashModeAuto;
    HasFlash = true;
  }

  cameraParameters.JpegQuality = JPEG_QUALITY;

  // Set the picture resolution
  var pictureSize = GetIdealPictureSize(cameraParameters.SupportedPictureSizes, MAX_MEGAPIXELS);
  _imageWidth = pictureSize.Width;
  _imageHeight = pictureSize.Height;
  cameraParameters.SetPictureSize(pictureSize.Width, pictureSize.Height);

  // Set the preview resolution to best match the TextureView
  var previewSize = GetIdealPreviewSize(cameraParameters.SupportedPreviewSizes, _previewTexture.Height, _previewTexture.Width);
  cameraParameters.SetPreviewSize(previewSize.Width, previewSize.Height);

  // Begin outputting camera preview
  _camera.SetParameters(cameraParameters);
  _camera.SetPreviewTexture(_previewTexture.SurfaceTexture);
  _camera.StartPreview();
  UpdatePreviewTextureMatrix(); // Ensure the preview is displayed without warping

  // Wait for the preview
  EventHandler<TextureView.SurfaceTextureUpdatedEventArgs> h = null;
  _previewTexture.SurfaceTextureUpdated += h = (s, e2) =>
  {
    _previewTexture.SurfaceTextureUpdated -= h;
    _callback.OnCameraPreviewReady();
    _ready = true;
  };
}

public void TakePicture()
{
  if (!_ready || _busy)
  {
    var e = new Exception("Camera not ready");
    OnTakePictureFailed(e);
    return;
  }

  _busy = true;

  _camera.AutoFocus(this);
}

public void OnAutoFocus(bool success, Camera camera)
{
  try
  {
    _camera.TakePicture(null, null, this);
  }
  catch (Exception e)
  {
    // On Samsung phones the exception is always thrown here
    OnTakePictureFailed(e);
  }
}

public void OnPictureTaken(byte[] data, Camera camera)
{
  _busy = false;
  var rotation = GetPictureRotation();
  _callback.OnPictureTaken(data, rotation, _imageWidth, _imageHeight);
}

private void OnTakePictureFailed(Exception e)
{
  _busy = false;
  _callback.OnTakePictureFailed(e);
}

相机功能可用,预览无问题,在三星设备上才会出现异常。

在拍照之前似乎没有调用startPreview()方法。您可能需要在拍照后再次调用它。请查看此处有关Camera类的8个顶级步骤:http://developer.android.com/reference/android/hardware/Camera.html - Jon Douglas
嗨Jon,预览已经开始了。你可以在我上面发布的代码中看到。 - Alfie Woodland
1个回答

2
当三星Galaxy手机第一次自动对焦失败时,抛出了异常 - 大多数设备只会尝试对焦一次,而三星Galaxy手机会重新尝试多达三次,并在每次尝试后调用OnAutoFocus回调函数。因为我的代码在回调中调用了Camera.TakePicture,所以它可能会被快速连续地调用两次或更多次,因此它会在拍照时尝试拍摄已经正在进行的照片并抛出异常。
解决方案很简单,只需添加一个布尔值来跟踪自动对焦回调是否已经发生,如果是,则跳过调用Camera.TakePicture
public void OnAutoFocus(bool success, Camera camera)
{
  if (_hasAttemptedFocus) return;
  else _hasAttemptedFocus = true;

  _camera.TakePicture(null, null, this);
}

public void OnPictureTaken(byte[] data, Camera camera)
{
  _busy = _hasAttemptedFocus = false;

  // Do something with the image
}

在调用 OnAutoFocus() 的所有情况下,success 是否都返回 true - allgood
抱歉回复晚了,但如果其他人也感兴趣的话:如果相机成功对焦,则返回true;否则返回false。如果自动对焦失败,可以跳过调用TakePicture。但是,由于不知道您特定硬件尝试对焦的次数,因此有可能用户按下快门按钮,但照片却没有被拍摄,因此我建议要么拍一张模糊的照片(就像我的代码一样),要么在第一次自动对焦失败时显示错误,并忽略后续对{{OnAutoFocus}}的调用。 - Alfie Woodland

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接