Problems with nativescript-camera plugin

plugins

#1

Hello,
I’ve got this code:

var options = {width: 1280, keepAspectRatio: true, saveToGallery: false};
        camera.takePicture(options)
            .then((imageAsset) => {
                    let source = new imageSource.ImageSource();
                    source.fromAsset(imageAsset).then((source) => {
                                 console.log("OK!");
                        },
                        (reason: any) => {
                            console.log("Rejected: stopping updates");
                        })
                },
                (reason: any) => {
                    console.log("Rejected: stopping updates");
                })
            .catch((err) => {
                console.log("Error -> " + err.message);
            });

if I take the picture it works fine, and I can keep taking pictures…

But if I click the back button (Android) while I am on the camera view, I don’t get any notification that i’ve closed the window cancelling the operation.

Is this possible to intercept the back button close dialog event?

Also, if after I clicked the back button to close the screen I re-execute the code to open it again, and take the picture and confirm, I get the error:

Any suggestion on what’s going on? I’m testing on Android

This is the relevant part of my package.json so you can see my configuration:

{
  "nativescript": {
    "id": "org.nativescript.GasMarketing",
    "tns-ios": {
      "version": "3.3.0"
    },
    "tns-android": {
      "version": "3.3.0"
    }
  },
  "dependencies": {
    "@angular/animations": "^4.4.6",
    "@angular/common": "^4.4.6",
    "@angular/compiler": "^4.4.6",
    "@angular/core": "^4.4.6",
    "@angular/forms": "^4.4.6",
    "@angular/http": "^4.4.6",
    "@angular/platform-browser": "^4.4.6",
    "@angular/router": "^4.4.6",
    "@types/lodash": "^4.14.74",
    "base-64": "^0.1.0",
    "class-transformer": "^0.1.7",
    "lodash": "^4.17.4",
    "nativescript-accelerometer": "^2.0.1",
    "nativescript-angular": "~4.4.1",
    "nativescript-bottombar": "3.0.5",
    "nativescript-camera": "^3.0.1",
    "nativescript-checkbox": "^2.1.8",
    "nativescript-couchbase": "^1.0.18",
    "nativescript-directions": "^1.0.6",
    "nativescript-drop-down": "^3.1.0",
    "nativescript-geolocation": "^3.0.0",
    "nativescript-google-maps-sdk": "^2.3.2",
    "nativescript-loading-indicator": "^2.4.0",
    "nativescript-localstorage": "^1.1.5",
    "nativescript-material-icons": "^1.0.3",
    "nativescript-ngx-fonticon": "^2.2.3",
    "nativescript-permissions": "^1.2.3",
    "nativescript-ripple": "^2.0.0",
    "nativescript-snackbar": "^1.3.0",
    "nativescript-status-bar": "^1.1.1",
    "nativescript-theme-core": "~1.0.2",
    "reflect-metadata": "^0.1.10",
    "rxjs": "~5.3.0",
    "tns-core-modules": "~3.3.0",
    "tns-platform-declarations": "^3.3.0",
    "utf8": "^2.1.2",
    "zone.js": "~0.8.2"
  }
}

Thanks,
Dem


#2

Have you tried the latest version? 3.1.2


#3

Hello, thanks for replying, because of the ^ it downloaded the latest version, so that’s what I’m testing with…

Dem


#4

Issue confirmed

An uncaught Exception occurred on "main" thread.
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=3453, result=-1, data=Intent {  }} to activity {com.anygofitness.anygopartner/com.tns.NativeScriptActivity}: com.tns.NativeScriptException: 
Calling js method onActivityResult failed

Error: java.io.FileNotFoundException: /storage/emulated/0/Android/data/com.anygofitness.anygopartner/files/NSIMG_20171101_173244.jpg (No such file or directory)
    java.io.FileInputStream.open(Native Method)
    java.io.FileInputStream.<init>(FileInputStream.java:146)
    java.io.FileInputStream.<init>(FileInputStream.java:99)
    android.media.ExifInterface.<init>(ExifInterface.java:1106)
    com.tns.Runtime.callJSMethodNative(Native Method)
    com.tns.Runtime.dispatchCallJSMethodNative(Runtime.java:1088)
    com.tns.Runtime.callJSMethodImpl(Runtime.java:970)
    com.tns.Runtime.callJSMethod(Runtime.java:957)
    com.tns.Runtime.callJSMethod(Runtime.java:941)
    com.tns.Runtime.callJSMethod(Run

I was able to reproduce the crash that you mentioned.


#5

Same here, using tns 3.2.1…


#7

https://github.com/NativeScript/nativescript-camera/issues/68

Hi @demetrio812
Open node_modules folder,
in the nativescript-camera folder, replace camera.android.js with this code

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var applicationModule = require("tns-core-modules/application/application");
var imageAssetModule = require("tns-core-modules/image-asset/image-asset");
var trace = require("tns-core-modules/trace/trace");
var platform = require("tns-core-modules/platform/platform");
var REQUEST_IMAGE_CAPTURE = 3453;
var REQUEST_REQUIRED_PERMISSIONS = 1234;
exports.takePicture = function(options) {
    return new Promise(function(resolve, reject) {
        try {
            if (
                android.support.v4.content.ContextCompat.checkSelfPermission(
                    applicationModule.android.currentContext,
                    android.Manifest.permission.CAMERA
                ) !== android.content.pm.PackageManager.PERMISSION_GRANTED
            ) {
                reject(
                    new Error(
                        "Application does not have permissions to use Camera"
                    )
                );
                return;
            }
            var types = require("tns-core-modules/utils/types");
            var utils = require("tns-core-modules/utils/utils");
            var saveToGallery_1;
            var reqWidth_1;
            var reqHeight_1;
            var shouldKeepAspectRatio_1;
            var density = utils.layout.getDisplayDensity();
            if (options) {
                saveToGallery_1 = options.saveToGallery ? true : false;
                reqWidth_1 = options.width ? options.width * density : 0;
                reqHeight_1 = options.height
                    ? options.height * density
                    : reqWidth_1;
                shouldKeepAspectRatio_1 = types.isNullOrUndefined(
                    options.keepAspectRatio
                )
                    ? true
                    : options.keepAspectRatio;
            }
            if (
                android.support.v4.content.ContextCompat.checkSelfPermission(
                    applicationModule.android.currentContext,
                    android.Manifest.permission.WRITE_EXTERNAL_STORAGE
                ) !== android.content.pm.PackageManager.PERMISSION_GRANTED
            ) {
                saveToGallery_1 = false;
            }
            var takePictureIntent = new android.content.Intent(
                android.provider.MediaStore.ACTION_IMAGE_CAPTURE
            );
            var dateStamp = createDateTimeStamp();
            var picturePath_1;
            var nativeFile = void 0;
            var tempPictureUri = void 0;
            if (saveToGallery_1) {
                picturePath_1 =
                    android.os.Environment
                        .getExternalStoragePublicDirectory(
                            android.os.Environment.DIRECTORY_DCIM
                        )
                        .getAbsolutePath() +
                    "/Camera/" +
                    "NSIMG_" +
                    dateStamp +
                    ".jpg";
                nativeFile = new java.io.File(picturePath_1);
            } else {
                picturePath_1 =
                    utils.ad
                        .getApplicationContext()
                        .getExternalFilesDir(null)
                        .getAbsolutePath() +
                    "/" +
                    "NSIMG_" +
                    dateStamp +
                    ".jpg";
                nativeFile = new java.io.File(picturePath_1);
            }
            var sdkVersionInt = parseInt(platform.device.sdkVersion);
            if (sdkVersionInt >= 21) {
                tempPictureUri = android.support.v4.content.FileProvider.getUriForFile(
                    applicationModule.android.currentContext,
                    applicationModule.android.nativeApp.getPackageName() +
                        ".provider",
                    nativeFile
                );
            } else {
                tempPictureUri = android.net.Uri.fromFile(nativeFile);
            }
            takePictureIntent.putExtra(
                android.provider.MediaStore.EXTRA_OUTPUT,
                tempPictureUri
            );
            if (options && options.cameraFacing === "front") {
                takePictureIntent.putExtra(
                    "android.intent.extras.CAMERA_FACING",
                    android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT
                );
            }
            if (
                takePictureIntent.resolveActivity(
                    utils.ad.getApplicationContext().getPackageManager()
                ) != null
            ) {
                var appModule_1 = require("tns-core-modules/application");

                // remove existing listeners if any
                appModule_1.android.off("activityResult");

                appModule_1.android.on("activityResult", function(args) {
                    var requestCode = args.requestCode;
                    var resultCode = args.resultCode;
                    if (
                        requestCode === REQUEST_IMAGE_CAPTURE &&
                        resultCode === android.app.Activity.RESULT_OK
                    ) {
                        if (saveToGallery_1) {
                            try {
                                var callback = new android.media
                                    .MediaScannerConnection
                                    .OnScanCompletedListener({
                                    onScanCompleted: function(path, uri) {
                                        if (trace.isEnabled()) {
                                            trace.write(
                                                "image from path " +
                                                    path +
                                                    " has been successfully scanned!",
                                                trace.categories.Debug
                                            );
                                        }
                                    }
                                });
                                android.media.MediaScannerConnection.scanFile(
                                    appModule_1.android.context,
                                    [picturePath_1],
                                    null,
                                    callback
                                );
                            } catch (ex) {
                                if (trace.isEnabled()) {
                                    trace.write(
                                        "An error occurred while scanning file " +
                                            picturePath_1 +
                                            ": " +
                                            ex.message +
                                            "!",
                                        trace.categories.Debug
                                    );
                                }
                            }
                        }
                        var exif = new android.media.ExifInterface(
                            picturePath_1
                        );
                        var orientation_1 = exif.getAttributeInt(
                            android.media.ExifInterface.TAG_ORIENTATION,
                            android.media.ExifInterface.ORIENTATION_NORMAL
                        );
                        if (
                            orientation_1 ===
                            android.media.ExifInterface.ORIENTATION_ROTATE_90
                        ) {
                            rotateBitmap(picturePath_1, 90);
                        } else if (
                            orientation_1 ===
                            android.media.ExifInterface.ORIENTATION_ROTATE_180
                        ) {
                            rotateBitmap(picturePath_1, 180);
                        } else if (
                            orientation_1 ===
                            android.media.ExifInterface.ORIENTATION_ROTATE_270
                        ) {
                            rotateBitmap(picturePath_1, 270);
                        }
                        var asset = new imageAssetModule.ImageAsset(
                            picturePath_1
                        );
                        asset.options = {
                            width: reqWidth_1,
                            height: reqHeight_1,
                            keepAspectRatio: shouldKeepAspectRatio_1
                        };
                        resolve(asset);
                    } else if (
                        resultCode === android.app.Activity.RESULT_CANCELED
                    ) {
                        // User cancelled the image capture
                        reject(new Error("cancelled"));
                    }
                });
                appModule_1.android.foregroundActivity.startActivityForResult(
                    takePictureIntent,
                    REQUEST_IMAGE_CAPTURE
                );
            }
        } catch (e) {
            if (reject) {
                reject(e);
            }
        }
    });
};
exports.isAvailable = function() {
    var utils = require("tns-core-modules/utils/utils");
    return utils.ad
        .getApplicationContext()
        .getPackageManager()
        .hasSystemFeature(android.content.pm.PackageManager.FEATURE_CAMERA);
};
exports.requestPermissions = function() {
    if (
        android.support.v4.content.ContextCompat.checkSelfPermission(
            applicationModule.android.currentContext,
            android.Manifest.permission.WRITE_EXTERNAL_STORAGE
        ) !== android.content.pm.PackageManager.PERMISSION_GRANTED ||
        android.support.v4.content.ContextCompat.checkSelfPermission(
            applicationModule.android.currentContext,
            android.Manifest.permission.CAMERA
        ) !== android.content.pm.PackageManager.PERMISSION_GRANTED
    ) {
        android.support.v4.app.ActivityCompat.requestPermissions(
            applicationModule.android.currentContext,
            [
                android.Manifest.permission.CAMERA,
                android.Manifest.permission.WRITE_EXTERNAL_STORAGE
            ],
            REQUEST_REQUIRED_PERMISSIONS
        );
    }
};
var createDateTimeStamp = function() {
    var result = "";
    var date = new Date();
    result =
        date.getFullYear().toString() +
        (date.getMonth() + 1 < 10
            ? "0" + (date.getMonth() + 1).toString()
            : (date.getMonth() + 1).toString()) +
        (date.getDate() < 10
            ? "0" + date.getDate().toString()
            : date.getDate().toString()) +
        "_" +
        date.getHours().toString() +
        date.getMinutes().toString() +
        date.getSeconds().toString();
    return result;
};
var rotateBitmap = function(picturePath, angle) {
    try {
        var matrix = new android.graphics.Matrix();
        matrix.postRotate(angle);
        var bmOptions = new android.graphics.BitmapFactory.Options();
        var oldBitmap = android.graphics.BitmapFactory.decodeFile(
            picturePath,
            bmOptions
        );
        var finalBitmap = android.graphics.Bitmap.createBitmap(
            oldBitmap,
            0,
            0,
            oldBitmap.getWidth(),
            oldBitmap.getHeight(),
            matrix,
            true
        );
        var out = new java.io.FileOutputStream(picturePath);
        finalBitmap.compress(
            android.graphics.Bitmap.CompressFormat.JPEG,
            100,
            out
        );
        out.flush();
        out.close();
    } catch (ex) {
        if (trace.isEnabled()) {
            trace.write(
                "An error occurred while rotating file " +
                    picturePath +
                    " (using the original one): " +
                    ex.message +
                    "!",
                trace.categories.Debug
            );
        }
    }
};
//# sourceMappingURL=camera.android.js.map

That will fix both the crash, and the back button handling for you.

Remember to tns platform remove android and then making a fresh run, to incorporate the changes :slight_smile:
Cheers!


#8

Thanks a lot! :slight_smile:

Did you fix the crash too??? That’s fantastic! I’ll test it ASAP and let you know!!

Cheers!

Dem


#9

@demetrio812
Yes both issues were fixed. And pr was merged.
And 3.1.3 release was supposed to have the latest changes.
But it doesn’t. So I sent you the code that I’m using.
It’s working well for me :slight_smile:


#10

Thank you very much! I’ve just tested it and it works perfectly! I sense tacos coming in the slack channel :smiley:


#11

3.1.4 version was released! :smiley: