Reputation: 6650
I'm trying to create a very simple app which shows the picture received from the camera on the display. I'm using the camera2 API, because I am new to this, so I try to use the most recent technology.
I reach the point where I call createCaptureSession()
, but then onConfigureFailed()
gets called and I don't know what the problem is or how to find it.
Here is my source:
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);
}
};
And the output is:
...﹕ 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
The following is in my AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera2" />
Upvotes: 2
Views: 15920
Reputation: 585
Since the asker mentioned that he was testing on the Galaxy S4, maybe it had something to do with the fact that some of the Samsung's Lollipop phones haven't implemented the Camera2 API. DPReview
Upvotes: 0
Reputation: 1882
Set Custom camera code:
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;
}
}
You can set camera preview size in "surfaceChanged()" method.
This code is work for me in Android 5.0.1 and 5.1.1 also.
Upvotes: -1
Reputation: 801
you should set the size of preview
mSurfaceView.getHolder().setFixedSize(previewSize.getWidth(), previewSize.getHeight());
Upvotes: 2