【问题标题】:Using android camera2 API to display camera feed使用 android camera2 API 显示相机源
【发布时间】:2015-06-15 19:43:07
【问题描述】:

我正在尝试创建一个非常简单的应用程序,它可以在显示屏上显示从相机接收到的图片。我正在使用 camera2 API,因为我是新手,所以我尝试使用最新的技术。

我到达了我调用createCaptureSession() 的位置,但随后onConfigureFailed() 被调用,我不知道问题是什么或如何找到它。

这是我的来源:

SurfaceView mSurfaceView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Log.d(TAG, "onCreate() start");

    setContentView(R.layout.activity_main);

    mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView);

}

protected void onResume() {
    super.onResume();

    Log.d(TAG, "onResume() start");

    initCamera();
}

private void initCamera() {
    Log.d(TAG, "initCamera() start");
    CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
    Log.d(TAG, "acquired cameraManager: " + cameraManager);

    String[] cameraIdList;
    try {
        cameraIdList = cameraManager.getCameraIdList();
    } catch (CameraAccessException e) {
        Log.e(TAG, "couldn't get camera list", e);
        return;
    }
    Log.d(TAG, "acquired cameraIdList: length: " + cameraIdList.length);

    if (cameraIdList.length == 0) {
        Log.w(TAG, "couldn't detect a camera");
        return;
    }

    String camera0Id = cameraIdList[0];

    Log.d(TAG, "chosen camera: " + camera0Id);

    try {
        cameraManager.openCamera(camera0Id, deviceCallback, null);
    } catch (CameraAccessException e) {
        Log.e(TAG, "couldn't open camera", e);
    }
    Log.d(TAG, "called cameraManager.openCamera()");
}

CameraDevice.StateCallback deviceCallback = new CameraDevice.StateCallback() {

    @Override
    public void onOpened(CameraDevice camera) {
        Log.d(TAG, "deviceCallback.onOpened() start");

        Surface surface = mSurfaceView.getHolder().getSurface();
        Log.d(TAG, "surface: " + surface);

        List<Surface> surfaceList = Collections.singletonList(surface);

        try {
            camera.createCaptureSession(surfaceList, sessionCallback, null);
        } catch (CameraAccessException e) {
            Log.e(TAG, "couldn't create capture session for camera: " + camera.getId(), e);
            return;
        }

    }

    @Override
    public void onDisconnected(CameraDevice camera) {
        Log.d(TAG, "deviceCallback.onDisconnected() start");
    }

    @Override
    public void onError(CameraDevice camera, int error) {
        Log.d(TAG, "deviceCallback.onError() start");
    }

};

CameraCaptureSession.StateCallback sessionCallback = new CameraCaptureSession.StateCallback() {
    @Override
    public void onConfigured(CameraCaptureSession session) {
        Log.i(TAG, "capture session configured: " + session);
    }

    @Override
    public void onConfigureFailed(CameraCaptureSession session) {
        Log.e(TAG, "capture session configure failed: " + session);
    }
};

输出是:

...﹕ onCreate() start
...﹕ onResume() start
...﹕ initCamera() start
...﹕ acquired cameraManager: android.hardware.camera2.CameraManager@5d68786
...﹕ acquired cameraIdList: length: 2
...﹕ chosen camera: 0
...﹕ called cameraManager.openCamera()
...﹕ deviceCallback.onOpened() start
...﹕ surface: Surface(name=null)/@0x52c91e3
...﹕ capture session configure failed: android.hardware.camera2.impl.CameraCaptureSessionImpl@1a8c7a99

以下是我的AndroidManifest.xml:

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera2" />

【问题讨论】:

  • 您在 Android 5.0 上运行吗?
  • @DanielNugent 是的,我的测试设备是 GS4,上面有 5.0.1。

标签: android android-camera surfaceview


【解决方案1】:

你应该设置预览的大小

mSurfaceView.getHolder().setFixedSize(previewSize.getWidth(), previewSize.getHeight());

【讨论】:

    【解决方案2】:

    既然提问者提到他在 Galaxy S4 上进行测试,也许这与三星的一些棒棒糖手机没有实现 Camera2 API 的事实有关。 DPReview

    【讨论】:

      【解决方案3】:

      设置自定义相机代码:

      import java.io.IOException;
      import java.util.List;
      
      import android.annotation.SuppressLint;
      import android.content.Context;
      import android.hardware.Camera;
      import android.hardware.Camera.Parameters;
      import android.hardware.Camera.Size;
      import android.util.Log;
      import android.view.SurfaceHolder;
      import android.view.SurfaceView;
      import android.view.View;
      import android.view.ViewGroup;
      
      @SuppressWarnings("deprecation")
      public class Preview extends ViewGroup implements SurfaceHolder.Callback {
          private final String TAG = "Preview";
      
          SurfaceView mSurfaceView;
          SurfaceHolder mHolder;
          Size mPreviewSize;
          List<Size> mSupportedPreviewSizes;
          Camera mCamera;
      
          public Preview(Context context, SurfaceView sv) {
              super(context);
      
              mSurfaceView = sv;
              // addView(mSurfaceView);
      
              mHolder = mSurfaceView.getHolder();
              mHolder.addCallback(this);
              mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
          }
      
          public void setCamera(Camera camera) {
              mCamera = camera;
              if (mCamera != null) {
                  mSupportedPreviewSizes = mCamera.getParameters()
                          .getSupportedPreviewSizes();
                  requestLayout();
      
                  mCamera.setDisplayOrientation(90);
                  setCamFocusMode();
      
                  // // get Camera parameters
                  // Camera.Parameters params = mCamera.getParameters();
                  //
                  // List<String> focusModes = params.getSupportedFocusModes();
                  // if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
                  // // set the focus mode
                  // params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
                  // // set Camera parameters
                  // mCamera.setParameters(params);
                  //
                  // }
              }
          }
      
          @Override
          protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
              // We purposely disregard child measurements because act as a
              // wrapper to a SurfaceView that centers the camera preview instead
              // of stretching it.
              final int width = resolveSize(getSuggestedMinimumWidth(),
                      widthMeasureSpec);
              final int height = resolveSize(getSuggestedMinimumHeight(),
                      heightMeasureSpec);
              setMeasuredDimension(width, height);
      
              if (mSupportedPreviewSizes != null) {
                  mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width,
                          height);
              }
          }
      
          @Override
          protected void onLayout(boolean changed, int l, int t, int r, int b) {
              if (changed && getChildCount() > 0) {
                  final View child = getChildAt(0);
      
                  final int width = r - l;
                  final int height = b - t;
      
                  int previewWidth = width;
                  int previewHeight = height;
                  if (mPreviewSize != null) {
                      previewWidth = mPreviewSize.width;
                      previewHeight = mPreviewSize.height;
                  }
      
                  // Center the child SurfaceView within the parent.
                  if (width * previewHeight > height * previewWidth) {
                      final int scaledChildWidth = previewWidth * height
                              / previewHeight;
                      child.layout((width - scaledChildWidth) / 2, 0,
                              (width + scaledChildWidth) / 2, height);
                  } else {
                      final int scaledChildHeight = previewHeight * width
                              / previewWidth;
                      child.layout(0, (height - scaledChildHeight) / 2, width,
                              (height + scaledChildHeight) / 2);
                  }
              }
          }
      
          public void surfaceCreated(SurfaceHolder holder) {
              // The Surface has been created, acquire the camera and tell it where
              // to draw.
              try {
                  if (mCamera != null) {
                      mCamera.setPreviewDisplay(holder);
                  }
              } catch (IOException exception) {
                  Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
              }
          }
      
          public void surfaceDestroyed(SurfaceHolder holder) {
              // Surface will be destroyed when we return, so stop the preview.
              if (mCamera != null) {
                  mCamera.stopPreview();
              }
          }
      
          private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
              final double ASPECT_TOLERANCE = 0.1;
              double targetRatio = (double) w / h;
              if (sizes == null)
                  return null;
      
              Size optimalSize = null;
              double minDiff = Double.MAX_VALUE;
      
              int targetHeight = h;
      
              // Try to find an size match aspect ratio and size
              for (Size size : sizes) {
                  double ratio = (double) size.width / size.height;
                  if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
                      continue;
                  if (Math.abs(size.height - targetHeight) < minDiff) {
                      optimalSize = size;
                      minDiff = Math.abs(size.height - targetHeight);
                  }
              }
      
              // Cannot find the one match the aspect ratio, ignore the requirement
              if (optimalSize == null) {
                  minDiff = Double.MAX_VALUE;
                  for (Size size : sizes) {
                      if (Math.abs(size.height - targetHeight) < minDiff) {
                          optimalSize = size;
                          minDiff = Math.abs(size.height - targetHeight);
                      }
                  }
              }
              return optimalSize;
          }
      
          public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
              if (mCamera != null) {
      
                  Camera.Parameters parameters = mCamera.getParameters();
                  List<Camera.Size> previewSizes = parameters
                          .getSupportedPreviewSizes();
      
                  // You need to choose the most appropriate previewSize for your app
                  Camera.Size previewSize;
                  try {
                      previewSize = previewSizes.get(1);
                      parameters.setPreviewSize(previewSize.width, previewSize.height);
                      mCamera.setParameters(parameters);
                      mCamera.startPreview();
                  } catch (Exception e) {
                      previewSize = previewSizes.get(0);
                      parameters.setPreviewSize(previewSize.width, previewSize.height);
                      mCamera.setParameters(parameters);
                      mCamera.startPreview();
                  }
              }
          }
      
          @SuppressLint("InlinedApi")
          private void setCamFocusMode() {
      
              if (null == mCamera) {
                  return;
              }
              /* Set Auto focus */
              Parameters parameters = mCamera.getParameters();
              List<String> focusModes = parameters.getSupportedFocusModes();
              if (focusModes
                      .contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
                  parameters
                          .setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
              } else if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
                  parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
              }
              mCamera.setParameters(parameters);
          }
      
          // Check Flash in Camera or not
          public boolean hasFlash() {
              if (mCamera == null) {
                  return false;
              }
      
              Camera.Parameters parameters = mCamera.getParameters();
              if (parameters.getFlashMode() == null) {
                  return false;
              }
      
              List<String> supportedFlashModes = parameters.getSupportedFlashModes();
              if (supportedFlashModes == null
                      || supportedFlashModes.isEmpty()
                      || supportedFlashModes.size() == 1
                      && supportedFlashModes.get(0).equals(
                              Camera.Parameters.FLASH_MODE_OFF)) {
                  return false;
              }
              return true;
          }
      
          public boolean setFlash(int flashMode) {
              if (mCamera == null) {
                  return false;
              }
      
              Camera.Parameters parameters = mCamera.getParameters();
              if (parameters.getFlashMode() == null) {
                  return false;
              }
      
              List<String> supportedFlashModes = parameters.getSupportedFlashModes();
              if (flashMode == 1 && supportedFlashModes.get(2).equals(
                              Camera.Parameters.FLASH_MODE_AUTO)) {
                  parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
              } else if (flashMode == 2 && supportedFlashModes.get(1).equals(
                              Camera.Parameters.FLASH_MODE_ON)) {
                  parameters.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
              } else if (flashMode == 3 && supportedFlashModes.get(0).equals(
                              Camera.Parameters.FLASH_MODE_OFF)) {
                  parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
              }
              mCamera.setParameters(parameters);
              return true;
          }
      }
      

      您可以在“surfaceChanged()”方法中设置相机预览大小。

      此代码在 Android 5.0.1 和 5.1.1 中也适用于我。

      【讨论】:

      • 这是旧相机 API,现已弃用
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      • 2017-11-10
      • 2020-05-05
      • 1970-01-01
      • 2018-08-16
      • 2014-10-17
      相关资源
      最近更新 更多