本文介绍了android camera2 api - 在 session.capture 之后不调用 onImageAvailable的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用相机 api2 来捕捉图像.代码在 MOTO g4 上运行良好,但是当我在 NEXUS 6 上测试代码时,在 session.capture 之后没有调用 onImageAvailable,并且没有保存任何图像.真的很沮丧,如果有人能帮忙,不胜感激!非常感谢.

I am trying to use camera api2 to capture images. The code worked fine on MOTO g4, but when I test the code on NEXUS 6, the onImageAvailable is not invoked after session.capture, and no image has been saved. Really frustrated, greatly appreciated if someone could help! Thanks so much.

        ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1);
        List<Surface> outputSurfaces = new ArrayList<Surface>(2);
        outputSurfaces.add(reader.getSurface());
        outputSurfaces.add(new Surface(textureView.getSurfaceTexture()));
        final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
        captureBuilder.addTarget(reader.getSurface());
        captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
        // Orientation
        int rotation = getWindowManager().getDefaultDisplay().getRotation();
        captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
        sendUri = getImageUri();
        final File file = new File(Environment.getExternalStorageDirectory()+"/"  + sendUri +".jpg");
        ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
            @Override
            public void onImageAvailable(ImageReader reader) {
                Image image = null;
                try {
                    image = reader.acquireLatestImage();
                    ByteBuffer buffer = image.getPlanes()[0].getBuffer();
                    byte[] bytes = new byte[buffer.capacity()];
                    buffer.get(bytes);
                    save(bytes);

                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (image != null) {
                        image.close();
                    }
                }
            }
            private void save(byte[] bytes) throws IOException {
                OutputStream output = null;
                try {
                    output = new FileOutputStream(file);
                    output.write(bytes);
                } finally {
                    if (null != output) {
                        output.close();
                    }
                }
            }
        };
        reader.setOnImageAvailableListener(readerListener, mBackgroundHandler);
        final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {

            @Override
            public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
                super.onCaptureCompleted(session, request, result);
                //Toast.makeText(MainActivity.this, "Saved:" + file, Toast.LENGTH_SHORT).show();
                toast1("Saved:"+file);
                //createCameraPreview();
            }
        };
        cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() {
            @Override
            public void onConfigured(CameraCaptureSession session) {
                try {
                    session.capture(captureBuilder.build(), captureListener, mBackgroundHandler);
                } catch (CameraAccessException e) {
                    e.printStackTrace();
                }
            }
            @Override
            public void onConfigureFailed(CameraCaptureSession session) {
            }
        }, mBackgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }

以下是运行相机功能时nexus 6的完整logcat输出,似乎没什么用...

Below is the full logcat output from nexus 6 when run the camera function, seems nothing useful...

03-07 13:04:34.526 1838-1838/examples.hello E/AndroidCameraApi: is camera open
03-07 13:04:34.527 1838-1838/examples.hello I/CameraManagerGlobal: Connecting to camera service
03-07 13:04:34.659 1838-1838/examples.hello E/AndroidCameraApi: openCamera X
03-07 13:04:34.694 1838-1838/examples.hello E/AndroidCameraApi: onOpened
03-07 13:04:34.722 1838-1883/examples.hello D/OpenGLRenderer: endAllActiveAnimators on 0x931bee80 (RippleDrawable) with handle 0x92c2cea0
03-07 13:04:43.952 1838-1838/examples.hello E/AndroidCameraApi: onPause

推荐答案

如果您包含故障设备的完整 logcat 输出会很有帮助,但我怀疑问题是这样的:

It'd be helpful if you included full logcat output from the failing device, but I suspect the problem is this:

ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1);

您正在创建一个本地 ImageReader 对象,而不是保存它以供进一步使用.你确实从中得到了一个 Surface,但 Surface 很像一个弱指针;如果没有引用它,它不会阻止 ImageReader 被 GC(参见 开发人员参考中的注释)

You're creating a local ImageReader object, and not saving it for further use. You do get a Surface from it, but a Surface is much like a weak pointer; it will not keep the ImageReader from getting GC'd if nothing references it (see the note in the developer references)

所以我怀疑如果你只是创建一个类成员 mReader 变量,并将 reader 存储在其中,一切都会正常.

So I suspect if you just create a class member mReader variable, and store reader in that, everything will work OK.

由于GC算法的差异,它可能适用于Moto手机;运行时还没有完全清除读取器对象,所以它有时间调用回调.

It may be working on the Moto phone due to differences in the GC algorithm; the runtime just hadn't gotten around to clearing out the reader object quite yet, so it has time to invoke the callback.

这篇关于android camera2 api - 在 session.capture 之后不调用 onImageAvailable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-19 06:13