java - 使用 Camera2 拍摄第二张照片时 setPreviewTexture 失败

标签 java android camera android-camera2

我试图在没有预览的情况下配置相机兼容性,但在拍摄第二张照片后,应用程序异常崩溃:

2018-12-27 14:36:20.392 12389-12977/com.example.android.braillefeeder E/RequestThread-0: Received device exception during capture call: java.io.IOException: setPreviewTexture failed at android.hardware.Camera.setPreviewTexture(Native Method) at android.hardware.camera2.legacy.RequestThreadManager.doJpegCapturePrepare(RequestThreadManager.java:298) at android.hardware.camera2.legacy.RequestThreadManager.-wrap1(Unknown Source:0) at android.hardware.camera2.legacy.RequestThreadManager$5.handleMessage(RequestThreadManager.java:830) at android.os.Handler.dispatchMessage(Handler.java:101) at android.os.Looper.loop(Looper.java:164) at android.os.HandlerThread.run(HandlerThread.java:65)

我有这个代码:

我的目标是 28 SDK 版本。我认为问题可能与线程有关,所以我尝试在 main 中初始化线程但没有成功。

public class CameraService {

// Size of taken photo
private static final int IMAGE_WIDTH = 1280;
private static final int IMAGE_HEIGHT = 960;

private CameraDevice mCameraDevice;
private CameraCaptureSession mCameraCaptureSession;

private HandlerThread backgroundThread;
private Handler backgroundHandler;

private ImageReader mImageReader;

private CameraService() {
}

private static class InstanceHolder {
    private static CameraService sCameraService = new CameraService();
}

public static CameraService getInstance() {
    return InstanceHolder.sCameraService;
}

public void initializeCamera(Context context,
                             ImageReader.OnImageAvailableListener onImageAvailableListener) {

    CameraManager cameraManager = (CameraManager) context.getSystemService(CAMERA_SERVICE);
    String[] camIds = {};
    try {
        camIds = cameraManager.getCameraIdList();
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
    if( camIds.length < 1) {
        Log.e("CameraService", "Camera not available.");
        return;
    }

    startBackgroundThread();

    mImageReader = ImageReader.newInstance(IMAGE_WIDTH, IMAGE_HEIGHT, ImageFormat.JPEG, 2);
    mImageReader.setOnImageAvailableListener(onImageAvailableListener, backgroundHandler);

    try {
        cameraManager.openCamera(camIds[0], mStateCallback, backgroundHandler);
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

private void startBackgroundThread() {
    backgroundThread = new HandlerThread("CameraBackground");
    backgroundThread.start();
    backgroundHandler = new Handler(backgroundThread.getLooper());
}

private void stopBackgroundThread() {
    backgroundThread.quitSafely();
    try {
        backgroundThread.join();
        backgroundThread = null;
        backgroundHandler = null;
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
    @Override
    public void onOpened(@NonNull CameraDevice cameraDevice) {
        mCameraDevice = cameraDevice;
    }

    @Override
    public void onDisconnected(@NonNull CameraDevice cameraDevice) {
        cameraDevice.close();
        mCameraDevice = null;
    }

    @Override
    public void onError(@NonNull CameraDevice cameraDevice, int i) {
        cameraDevice.close();
        mCameraDevice = null;
    }

    @Override
    public void onClosed(@NonNull CameraDevice camera) {
        mCameraDevice = null;
    }
};

public void takePicture() {
    Log.d("CameraService", "takePicture()");
    if( mCameraDevice == null) {
        Log.d("CameraService", "Cannot take picture. Camera device is null.");
        return;
    }
    try {
        mCameraDevice.createCaptureSession(Collections.singletonList(mImageReader.getSurface()),
                new CameraCaptureSession.StateCallback() {
                    @Override
                    public void onConfigured(CameraCaptureSession cameraCaptureSession) {
                        if( mCameraDevice == null) {
                            Log.e("mStateCallback", " mStateCallbackCaptureSession configured");
                            return;
                        }
                        Log.d("CameraService", "imageCapture()");
                        mCameraCaptureSession = cameraCaptureSession;
                        imageCapture();
                    }

                    @Override
                    public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
                        Log.e("mStateCallback", "Configure failed");
                    }
                }, null);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

private void imageCapture() {
    Log.d("CameraService", "imageCapture()");
    try {
        final CaptureRequest.Builder builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
        builder.addTarget(mImageReader.getSurface());
        builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
        mCameraCaptureSession.stopRepeating();
        mCameraCaptureSession.capture(builder.build(), mCaptureCallback, null);
    } catch (CameraAccessException e) {
        Log.e("imagecapture()", "KOKOTKO");
        e.printStackTrace();
    }
}

private final CameraCaptureSession.CaptureCallback mCaptureCallback =
        new CameraCaptureSession.CaptureCallback() {
            @Override
            public void onCaptureStarted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, long timestamp, long frameNumber) {
                super.onCaptureStarted(session, request, timestamp, frameNumber);
            }

            @Override
            public void onCaptureProgressed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureResult partialResult) {
                super.onCaptureProgressed(session, request, partialResult);
            }

            @Override
            public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
                if( session != null) {
                     session.close();
                }
            }
};

public void shutdown() {
    Log.d("CameraService", "shutdown()");
    if( mCameraDevice != null) {
        mCameraDevice.close();
    }
    if( mCameraCaptureSession != null) {
        mCameraCaptureSession.close();
    }
    stopBackgroundThread();
}
}

谢谢

最佳答案

我在第二次捕获图像时遇到与 camera2 Api 相同的问题。该问题导致您在获取字节后未在图像阅读器监听器中关闭图像 image.close

希望对你有帮助

关于java - 使用 Camera2 拍摄第二张照片时 setPreviewTexture 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53950457/

相关文章:

android - 如何在 AndroidX 中更改 Android SearchView 的 textcolor 或 queryhint textcolor?

android相机连续对焦(按需)

java - Stomp 拦截器不工作

java - 输入日期 Jan 03 但返回 Jan 02,为什么?

android - 模拟车速表

javascript - 如何为 p5.js 编写一行代码,作为我的播放器的相机跟随器? (var Mover;) 这是一款 2D 游戏

android - 如何在三星 Galaxy Tab 上使用相机闪光灯/led 作为手电筒?

java - Maven 项目问题 - 包命名空间错误?

java - 为什么我的文本文件在每次执行后没有被覆盖?

android - Google map SDK 地理编码