android camera2 api - onImageAvailable is not invoked after session.capture

让人想犯罪 __ 提交于 2020-08-19 08:48:08

问题


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();
    }

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

回答1:


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);

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)

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

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.




回答2:


Override onConfigureFailed() like this:

   @Override
   public void onConfigureFailed(CameraCaptureSession session) {
       ImageReader mReader = ImageReader.newInstance(640, 480, ImageFormat.JPEG, 1);
       takePicture() // function to get image
       createCameraPreview(); // function to set camera Preview on screen
   }

Call createCameraPreview function to restart the camera, otherwise, it will stay stuck. You can change the ImageReader with new values

ImageReader mReader = ImageReader.newInstance(640, 480, ImageFormat.JPEG, 1);

And call the takePicture() function again so that user don't have to click again to capture image.



来源:https://stackoverflow.com/questions/42585765/android-camera2-api-onimageavailable-is-not-invoked-after-session-capture

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!