简体   繁体   中英

Android CAMERA 2 API captures 0kb images & gives a full white preview. Shows no errors or warnings on logcat

I use Android CAMERA 2 API for the camera2 supporting phones on my app. Works great, but some times it captures 0kb images & gives a full white preview . Shows no errors or warnings on logcat. Below is my camera image capture & save code:

protected void takePictureViaCamera2() {
    if (null == cameraDevice) {
        Log.e(TAG, "cameraDevice is null");
        return;
    }
    CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
    try {
        CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraDevice.getId());
        Size[] jpegSizes = null;
        if (characteristics != null) {
            jpegSizes = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(ImageFormat.JPEG);
        }
        int width = 640;
        int height = 480;
        if (jpegSizes != null && 0 < jpegSizes.length) {
            width = jpegSizes[0].getWidth();
            height = jpegSizes[0].getHeight();
        }
        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));
        //final File file = new File(Environment.getExternalStorageDirectory()+"/pic.jpg");
        final File file = createImageFile();
        final String checkPath = file.getParent();
        Log.e("checkPath", checkPath);
        //photoFile = createImageFile();
        //photoFilePath  = photoFile.getParent();
        //Log.e("photoFilePath", photoFilePath);
        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();
                    Log.e("readerListenerFNF_EX", e + "");
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.e("readerListenerIO_EX", e + "");
                } catch (Exception e) {
                    e.printStackTrace();
                    Log.e("readerListener_EX", e + "");
                } finally {
                    if (image != null) {
                        image.close();
                    }
                }
            }

            private void save(byte[] bytes) throws IOException {
                OutputStream output = null;
                try {
                    output = new FileOutputStream(file);
                    //output = new FileOutputStream(photoFile);
                    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(TravelChargesCamera2Activity.this, "Saved***:" + file, Toast.LENGTH_SHORT).show();
                createCameraPreview();
                closeCamera();


                Thread thread = new Thread() {
                    @Override
                    public void run() {
                        try {
                            synchronized (this) {
                                wait(5000);

                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        toolbar.setVisibility(View.VISIBLE);
                                        header.setVisibility(View.VISIBLE);
                                        assessorTraveldetails_scroll.setVisibility(View.VISIBLE);
                                        camera2Layout.setVisibility(View.GONE);

                                        try {

                                            if (!file.getParentFile().isDirectory()) {

                                                travelDirectory = new File(checkPath);
                                                Log.e("travelDir==created==", travelDirectory + "");
                                            } else {

                                                travelDirectory = file.getParentFile();
                                                Log.e("travelDir==exists==", travelDirectory + "");
                                            }

                                            files = travelDirectory.listFiles();
                                            Log.e("files", files + "");

                                            // removes old images from view
                                            // prevents  display duplication
                                            travelGallery.removeAllViews();

                                            // loop displays the photos captured on Horizontal ScrollView
                                            for (File picFile : files) {
                                                travelGallery.addView(insertPhoto(picFile.getAbsolutePath()));

                                                byte[] byteArray = ImageUtils.fileToByteArray(file);
                                                Log.e("byteArray", byteArray + "");
                                            }

                                        } catch (Exception e) {
                                            e.printStackTrace();
                                            Log.e("file", e + "");
                                        }
                                    }
                                });

                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                            Log.e("InterruptedException", e + "");
                        } catch (Exception e) {
                            e.printStackTrace();
                            Log.e("Exception", e + "");
                        }
                    }
                };
                thread.start();

            }
        };
        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();
        Log.e("CameraAccessException", e + "");
    } catch (Exception e) {
        e.printStackTrace();
        Log.e("takePictureViaCamera2", e + "");
    }
}

private File createImageFile() throws IOException {
    // Create an image file name

    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String uniqueId = UUID.randomUUID().toString();
    String imageFileName = "CAP_" + timeStamp + "_" + uniqueId;


    String bCode = "";

    masterMap = (LinkedTreeMap) gson.fromJson(batchMasterObject.getMasterJson(), Object.class);
    auditMap = (LinkedTreeMap) masterMap.get("2001");
    if ((auditMap.get("batchCode") != null && !auditMap.get("batchCode").equals(""))) {
        bCode = auditMap.get("batchCode").toString();
    } else if (auditMap.get("cbc") != null && !auditMap.get("cbc").equals("")) {
        bCode = auditMap.get("cbc").toString();
    }


    File storageDir = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "/" + bCode + "/Travel/");

    if (!storageDir.exists()) {
        storageDir.mkdirs();
    }
    String checkPath = storageDir.getPath();
    Log.e("checkPath", checkPath);

    Toast.makeText(getApplicationContext(), checkPath, Toast.LENGTH_LONG).show();

    File image = File.createTempFile(
            imageFileName,  /* prefix */
            ".jpg",         /* suffix */
            storageDir      /* directory */
    );

    // Save a file: path for use with ACTION_VIEW intents        
    mCurrentPhotoPath = storageDir.getAbsolutePath();
    return image;
}

Could any one help on this?

NOTE: The camera, captures and stores an image file as intended, but the file size is 0kb. When the image file is opened on phone or pc, it says "Unsupported format"

It looks like you're taking your final JPEG capture as the very first frame.

This means the camera's auto-exposure routines have not had any time to work (since you're grabbing the first frame), so the image will be captured with the initial settings hardcoded into the camera driver. This may work for some scenes, but in others, the image will be far too bright or far too dark.

For best results, you should first let the camera meter for a while, until auto-exposure and auto-focus are converged.

Generally, this can be done by setting up a low-resolution preview output (use a SurfaceTexture for example), and running it for a second or two (or wait until a CaptureResult has an AE_STATE of CONVERGED). Then issue the JPEG capture.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM