efratyo efratyo - 2 months ago 34
Android Question

How do I get metadata using React-Native-Camera capture?

I can't figure out how to get captured image's metadata, using react-native-camera capture method.

I was assuming it's something like:

this.camera.capture({metadata: true})
.then((data) => console.log(data))
.catch(error => alert("error: " + error));


But it only returns the path, so does:

this.camera.capture({metadata: 'location'})
.then((data) => console.log(data))
.catch(error => alert("error: " + error));


The docs metadata usage is unclear to me.
What is the right way to pass the metadata parameter?
Did anyone got this to work?

Answer

This might be a shot in the dark, but if you read the first paragraph of the README.md https://github.com/lwansbrough/react-native-camera it says:

These docs are for the work in progress v1 release. If you want to use the latest and greatest and can deal with significant instability you can install with npm install --save lwansbrough/react-native-camera.

The NPM version of the library is 0.3.8: https://www.npmjs.com/package/react-native-camera.

EDIT:

So I went to install the library at 0.3.8 and went into node_modules to look at the Java code (assuming you're testing this on an Android phone) and searched for the native capture function and there's literally nothing that handles the metadata option, which is sad. Try searching for metadata and you won't find anything for it:

@ReactMethod
public void capture(final ReadableMap options, final Promise promise) {
    int orientation = options.hasKey("orientation") ? options.getInt("orientation") : RCTCamera.getInstance().getOrientation();
    if (orientation == RCT_CAMERA_ORIENTATION_AUTO) {
        _sensorOrientationChecker.onResume();
        _sensorOrientationChecker.registerOrientationListener(new RCTSensorOrientationListener() {
            @Override
            public void orientationEvent() {
                int deviceOrientation = _sensorOrientationChecker.getOrientation();
                _sensorOrientationChecker.unregisterOrientationListener();
                _sensorOrientationChecker.onPause();
                captureWithOrientation(options, promise, deviceOrientation);
            }
        });
    } else {
        captureWithOrientation(options, promise, orientation);
    }
}

private void captureWithOrientation(final ReadableMap options, final Promise promise, int deviceOrientation) {
    Camera camera = RCTCamera.getInstance().acquireCameraInstance(options.getInt("type"));
    if (null == camera) {
        promise.reject("No camera found.");
        return;
    }

    if (options.getInt("mode") == RCT_CAMERA_CAPTURE_MODE_VIDEO) {
        record(options, promise);
        return;
    }

    RCTCamera.getInstance().setCaptureQuality(options.getInt("type"), options.getString("quality"));

    if (options.hasKey("playSoundOnCapture") && options.getBoolean("playSoundOnCapture")) {
        MediaActionSound sound = new MediaActionSound();
        sound.play(MediaActionSound.SHUTTER_CLICK);
    }

    if (options.hasKey("quality")) {
        RCTCamera.getInstance().setCaptureQuality(options.getInt("type"), options.getString("quality"));
    }

    final Boolean shouldMirror = options.hasKey("mirrorImage") && options.getBoolean("mirrorImage");

    RCTCamera.getInstance().adjustCameraRotationToDeviceOrientation(options.getInt("type"), deviceOrientation);
    camera.takePicture(null, null, new Camera.PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {

            if (shouldMirror) {
                data = mirrorImage(data);
                if (data == null) {
                    promise.reject("Error mirroring image");
                }
            }

            camera.stopPreview();
            camera.startPreview();
            WritableMap response = new WritableNativeMap();
            switch (options.getInt("target")) {
                case RCT_CAMERA_CAPTURE_TARGET_MEMORY:
                    String encoded = Base64.encodeToString(data, Base64.DEFAULT);
                    response.putString("data", encoded);
                    promise.resolve(response);
                    break;
                case RCT_CAMERA_CAPTURE_TARGET_CAMERA_ROLL: {
                    File cameraRollFile = getOutputCameraRollFile(MEDIA_TYPE_IMAGE);
                    if (cameraRollFile == null) {
                        promise.reject("Error creating media file.");
                        return;
                    }

                    Throwable error = writeDataToFile(data, cameraRollFile);
                    if (error != null) {
                        promise.reject(error);
                        return;
                    }

                    addToMediaStore(cameraRollFile.getAbsolutePath());
                    response.putString("path", Uri.fromFile(cameraRollFile).toString());
                    promise.resolve(response);
                    break;
                }
                case RCT_CAMERA_CAPTURE_TARGET_DISK: {
                    File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
                    if (pictureFile == null) {
                        promise.reject("Error creating media file.");
                        return;
                    }

                    Throwable error = writeDataToFile(data, pictureFile);
                    if (error != null) {
                        promise.reject(error);
                        return;
                    }

                    addToMediaStore(pictureFile.getAbsolutePath());
                    response.putString("path", Uri.fromFile(pictureFile).toString());
                    promise.resolve(response);
                    break;
                }
                case RCT_CAMERA_CAPTURE_TARGET_TEMP: {
                    File tempFile = getTempMediaFile(MEDIA_TYPE_IMAGE);
                    if (tempFile == null) {
                        promise.reject("Error creating media file.");
                        return;
                    }

                    Throwable error = writeDataToFile(data, tempFile);
                    if (error != null) {
                        promise.reject(error);
                    }

                    response.putString("path", Uri.fromFile(tempFile).toString());
                    promise.resolve(response);
                    break;
                }
            }
        }
    });
}

However, I looked on the iOS side and see that they do handle the metadata object there.

EDIT:

Also, the master branch still does not handle the metadata option. See here. It seems like you have to specify a specific target and depending on what that is, it will return you a specific data type, but nothing related to location unfortunately.

Comments