0

我創建了一個CameraSurfaceView類,它提供了實現相機預覽的邏輯。一切工作正常我嘗試過的設備上。 Nexus 5,Nexus 5X,Nexus 6P甚至三星Galaxy S5。爲相機擴展android表面視圖以支持所有設備

但在三星Galaxy S6邊緣某種原因,我得到的

android.hardware.Camera.native_setParameters(本機方法)運行時異常

我已經把範圍縮小到以下類

parameters.setPictureSize(mPreviewSize.width,mPreviewSize.height);

這裏是我的類:

public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback { 

    private Camera mCamera; 
    private SurfaceHolder mSurfaceHolder; 
    private List<Camera.Size> mSupportedPreviewSizes; 
    private Camera.Size mPreviewSize; 

    public CameraSurfaceView(Context context, Camera camera) { 
     super(context); 
     mCamera = camera; 
     mSurfaceHolder = getHolder(); 
     mSurfaceHolder.addCallback(this); 
     mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes(); 
    } 

    @Override 
    public void surfaceCreated(SurfaceHolder holder) { 

    } 

    @Override 
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 
     if (mSurfaceHolder.getSurface() == null) { 
      // preview surface does not exist 
      return; 
     } 

     try { 
      // stop preview before making changes 
      mCamera.stopPreview(); 
     } catch (Exception e) { 
      Timber.e(e, e.getMessage()); 
     } 

     // set preview size and make any resize, rotate or reformatting changes here 
     // start preview with new settings 
     try { 
      Camera.Parameters parameters = mCamera.getParameters(); 
      parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height); 
      parameters.setPictureSize(mPreviewSize.width, mPreviewSize.height); 

      if (parameters.getSupportedFocusModes() 
        .contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { 
       parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); 
      } 

      mCamera.setParameters(parameters); 
      mCamera.setPreviewDisplay(mSurfaceHolder); 
      mCamera.startPreview(); 

     } catch (Exception e) { 
      Timber.e(e, "Error starting camera preview: " + e.getMessage()); 
     } 
    } 

    @Override 
    public void surfaceDestroyed(SurfaceHolder holder) { 

    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec); 
     final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec); 

     if (mSupportedPreviewSizes != null) { 
      mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height); 
     } 

     float ratio; 
     if (mPreviewSize.height >= mPreviewSize.width) { 
      ratio = (float) mPreviewSize.height/(float) mPreviewSize.width; 
     } else { 
      ratio = (float) mPreviewSize.width/(float) mPreviewSize.height; 
     } 

     // One of these methods should be used, second method squishes preview slightly 
     setMeasuredDimension(width, (int) (width * ratio)); 
//  setMeasuredDimension((int) (width * ratio), height); 
    } 

    private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) { 
     final double aspectTolerance = 0.1; 
     double targetRatio = (double) h/w; 

     if (sizes == null) { 
      return null; 
     } 

     Camera.Size optimalSize = null; 
     double minDiff = Double.MAX_VALUE; 

     int targetHeight = h; 

     for (Camera.Size size : sizes) { 
      double ratio = (double) size.height/size.width; 
      if (Math.abs(ratio - targetRatio) > aspectTolerance) { 
       continue; 
      } 
      if (Math.abs(size.height - targetHeight) < minDiff) { 
       optimalSize = size; 
       minDiff = Math.abs(size.height - targetHeight); 
      } 
     } 

     if (optimalSize == null) { 
      minDiff = Double.MAX_VALUE; 
      for (Camera.Size size : sizes) { 
       if (Math.abs(size.height - targetHeight) < minDiff) { 
        optimalSize = size; 
        minDiff = Math.abs(size.height - targetHeight); 
       } 
      } 
     } 

     return optimalSize; 
    } 
} 

如何正確將圖像尺寸設置爲這個設備或具有相同問題的任何其他人呢?

有沒有人有相機SurfaceView邏輯的一個很好的例子,適用於大多數設備?

感謝。

+0

我面臨着同樣的問題,並利用屏幕寬度和高度解決。不要相信預覽尺寸。大多數舊設備可能會出現故障。 – asozcan

回答

0

原來我在使用supportedPreviewSizes設置圖片尺寸,而不是在攝像機參數中設置supportedPictureSizes

下面是我的新CameraSurfaceView類:

public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback { 

    private Camera mCamera; 
    private SurfaceHolder mSurfaceHolder; 
    private List<Camera.Size> mSupportedPreviewSizes; 
    private List<Camera.Size> mSupportedPictureSizes; 
    private Camera.Size mPreviewSize; 
    private Camera.Size mPictureSize; 

    public CameraSurfaceView(Context context, Camera camera) { 
     super(context); 
     mSurfaceHolder = getHolder(); 
     mSurfaceHolder.addCallback(this); 

     mCamera = camera; 
     Camera.Parameters parameters = mCamera.getParameters(); 

     mSupportedPreviewSizes = parameters.getSupportedPreviewSizes(); 
     mSupportedPictureSizes = parameters.getSupportedPictureSizes(); 

     if (parameters.getSupportedFocusModes() 
       .contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { 
      parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); 
     } 

     mCamera.setParameters(parameters); 
    } 

    @Override 
    public void surfaceCreated(SurfaceHolder holder) { 

    } 

    @Override 
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 
     if (mSurfaceHolder.getSurface() == null) { 
      // preview surface does not exist 
      return; 
     } 

     try { 
      // stop preview before making changes 
      mCamera.stopPreview(); 
     } catch (Exception e) { 
      Timber.e(e, e.getMessage()); 
     } 

     // set preview size and make any resize, rotate or reformatting changes here 
     // start preview with new settings 
     try { 
      Camera.Parameters parameters = mCamera.getParameters(); 
      parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height); 
      parameters.setPictureSize(mPictureSize.width, mPictureSize.height); 

      mCamera.setParameters(parameters); 
      mCamera.setPreviewDisplay(mSurfaceHolder); 
      mCamera.startPreview(); 

     } catch (Exception e) { 
      Timber.e(e, "Error starting camera preview: " + e.getMessage()); 
     } 
    } 

    @Override 
    public void surfaceDestroyed(SurfaceHolder holder) { 

    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec); 
     final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec); 

     if (mSupportedPreviewSizes != null) { 
      mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height); 
     } 

     if (mSupportedPictureSizes != null) { 
      mPictureSize = getOptimalPreviewSize(mSupportedPictureSizes, mPreviewSize.width, 
        mPreviewSize.height); 
     } 

     float ratio; 
     if (mPreviewSize.height >= mPreviewSize.width) { 
      ratio = (float) mPreviewSize.height/(float) mPreviewSize.width; 
     } else { 
      ratio = (float) mPreviewSize.width/(float) mPreviewSize.height; 
     } 

     setMeasuredDimension(width, (int) (width * ratio)); 
    } 

    private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) { 
     final double aspectTolerance = 0.1; 
     double targetRatio = (double) h/w; 

     if (sizes == null) { 
      return null; 
     } 

     Camera.Size optimalSize = null; 
     double minDiff = Double.MAX_VALUE; 

     int targetHeight = h; 

     for (Camera.Size size : sizes) { 
      double ratio = (double) size.height/size.width; 
      if (Math.abs(ratio - targetRatio) > aspectTolerance) { 
       continue; 
      } 
      if (Math.abs(size.height - targetHeight) < minDiff) { 
       optimalSize = size; 
       minDiff = Math.abs(size.height - targetHeight); 
      } 
     } 

     if (optimalSize == null) { 
      minDiff = Double.MAX_VALUE; 
      for (Camera.Size size : sizes) { 
       if (Math.abs(size.height - targetHeight) < minDiff) { 
        optimalSize = size; 
        minDiff = Math.abs(size.height - targetHeight); 
       } 
      } 
     } 

     return optimalSize; 
    } 
}