Как мне заставить CameraDevice работать в camera2?

#android #android-6.0-marshmallow #camera2

#Android #android-6.0-marshmallow #camera2

Вопрос:

Я следил за документацией camera2, пытаясь реализовать камеру без предварительного просмотра с помощью ImageReader, но когда я добираюсь до cameraDevice.createCaptureSession(outputs, mccsStateCallback, cameraHandler); , cameraDevice объект равен нулю, хотя я уверен, что он должен был быть назначен в CameraCaptureSession.StateCallback прослушивателе событий (который также не запускается, потому что сам CameraCaptureSession равен нулю). Либо у меня все совершенно неправильно, либо я пропустил что-то важное. Вот мой код:

 private CameraDevice cameraDevice;
private String cameraId;
private Handler cameraHandler = new Handler();
private CameraCharacteristics cameraCharacteristics;
private ImageReader jpgReader;
Bitmap bitmap;
private Handler imgHandler = new Handler();
private CameraCaptureSession mSession;
private CameraManager cameraManager;

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

    @Override
    public void onDisconnected(@NonNull CameraDevice camera) {
        cameraDevice.close();
    }

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

OnImageAvailableListener imageAvailableListener = new OnImageAvailableListener() {
    @Override
    public void onImageAvailable(ImageReader reader) {
        Image image = reader.acquireLatestImage();
        Image.Plane[] planes = image.getPlanes();
        Buffer buffer = planes[0].getBuffer().rewind();
        bitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);
        bitmap.copyPixelsFromBuffer(buffer);
        mFaceOverlayView.setBitmap(bitmap);

    }
};

private CameraCaptureSession.StateCallback mccsStateCallback = new CameraCaptureSession.StateCallback() {
    @Override
    public void onConfigured(@NonNull CameraCaptureSession session) {
        try {
            if (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(getBaseContext(), android.Manifest.permission.CAMERA)) {
                mSession = session;
                CaptureRequest.Builder request = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
                request.addTarget(jpgReader.getSurface());
                mSession.setRepeatingRequest(request.build(), new CameraCaptureSession.CaptureCallback() {
                    @Override
                    public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
                        super.onCaptureCompleted(session, request, result);
                    }
                }, null);
                cameraManager.openCamera(cameraId, mStateCallback, cameraHandler);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void onConfigureFailed(CameraCaptureSession session) {

    }
};

private void initialiseCamera() {
    cameraManager = (CameraManager) FilesPlayer.this.getSystemService(Context.CAMERA_SERVICE);
    try {
        cameraId = getFrontFacingCameraId(cameraManager);
        if (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA)) {

            cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId);

            StreamConfigurationMap streamConfigurationMap = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            android.util.Size[] jpegSizes = streamConfigurationMap.getOutputSizes(ImageFormat.JPEG);

            Size biggestSize = new Size(0, 0);
            for (Size size : jpegSizes) {
                if (size.getHeight() >= biggestSize.getHeight() amp;amp; size.getWidth() >= biggestSize.getWidth()) {
                    biggestSize = size;
                }
            }
            jpgReader = ImageReader.newInstance(biggestSize.getWidth(), biggestSize.getHeight(), ImageFormat.JPEG, 1);
            jpgReader.setOnImageAvailableListener(imageAvailableListener, imgHandler);
            List<Surface> outputs = Arrays.asList(jpgReader.getSurface());
            cameraDevice.createCaptureSession(outputs, mccsStateCallback, cameraHandler);

        }
        else{
            Log.d("NOOO","NOOOO");
        }

    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

private String getFrontFacingCameraId(CameraManager cameraManager) {
    try {
        for (String id : cameraManager.getCameraIdList()) {
            CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(id);
            Integer cameraOrientation = cameraCharacteristics.get(CameraCharacteristics.LENS_FACING);
            if (cameraOrientation != null amp;amp; cameraOrientation == CameraMetadata.LENS_FACING_FRONT) {
                return id;
            }
        }

    } catch (CameraAccessException ex) {
        ex.printStackTrace();
    }
    return null;
}
  

РЕДАКТИРОВАТЬ: мне удалось заставить CameraDevice назначить себя, поместив cameraManager.openCamera(cameraId,mStateCallback,cameraHandler); перед cameraDevice.createCaptureSession(outputs, mccsStateCallback, cameraHandler); в initialiseCamera() .
Теперь у меня возникла проблема, из-за которой вывод камеры не направляется на поверхность устройства чтения изображений, и я получаю сообщение об ошибке в консоли E/Surface: getSlotFromBufferLocked: unknown buffer: 0xa1ae7000 .

Комментарии:

1. После того, как вы закончили с объектом изображения в методе onImageAvailable, вам нужно освободить его, вызвав image.close(); . Также я не уверен, возможно ли создать растровое изображение из JPEG, просто используя bitmap.copyPixelsFromBuffer(buffer); , потому что JPEG — это сжатый формат.

Ответ №1:

Это краткое замечание.

Обязательно укажите разрешение в манифесте. Также убедитесь, что пользователь может предоставить разрешение приложению через ActivityCompact и ContextCompact. На Android 6.0 и выше разрешения также предоставляются пользователем во время выполнения. Смотрите документы здесь.

 // Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
        Manifest.permission.READ_CONTACTS)
        != PackageManager.PERMISSION_GRANTED) {

    // Permission is not granted
    // Should we show an explanation?
    if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
            Manifest.permission.READ_CONTACTS)) {
        // Show an explanation to the user *asynchronously* -- don't block
        // this thread waiting for the user's response! After the user
        // sees the explanation, try again to request the permission.
    } else {
        // No explanation needed; request the permission
        ActivityCompat.requestPermissions(thisActivity,
                new String[]{Manifest.permission.READ_CONTACTS},
                MY_PERMISSIONS_REQUEST_READ_CONTACTS);

        // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
        // app-defined int constant. The callback method gets the
        // result of the request.
    }
} else {
    // Permission has already been granted
}