2016-03-30 119 views
4

我正在使用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); 
} 

相機可用並且預覽顯示沒有問題,異常只扔在三星設備。

+0

看來,'startPreview()'方法是不在拍照之前被呼叫。拍攝照片後,您可能需要再次調用它。看看這個'Camera'類的8個頂級步驟:http://developer.android.com/reference/android/hardware/Camera.html –

+0

嗨,Jon,預覽開始。你可以在我上面發佈的代碼中看到這一點。 –

回答

2

當三星Galaxy手機第一次無法自動對焦時,會引發異常 - 而大多數設備只會嘗試對焦一次,Samsung 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 
} 
+0

在'OnAutoFocus()'的所有調用中''成功'返回'true'? – allgood

+0

對於遲到的回覆抱歉,但在其他人感興趣的情況下:如果相機成功對焦則返回true,否則返回false。 在自動對焦失敗的情況下,可能會跳過對TakePicture的調用,但不知道您的特定硬件將嘗試多少次,您有可能會冒着用戶點擊快門按鈕的風險以及永遠不會拍攝的圖像,所以我會建議拍攝模糊的照片(正如我的代碼所做的那樣),或者僅在首次自動對焦失敗時顯示錯誤,並忽略對{{OnAutoFocus}}的後續調用。 –