11

I'm developing a mobile app with cordova/phonegap and I've installed Camera plugin. I am able to open the camera and click the image but after that app crashes. here is the crash log:

    java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=34, result=-1, data=null} to activity {com.phonegap.helloworld/com.phonegap.helloworld.CordovaApp}: java.lang.IllegalArgumentException: filename cannot be null
    E/AndroidRuntime(22226):    at android.app.ActivityThread.deliverResults(ActivityThread.java:3510)
    E/AndroidRuntime(22226):    at android.app.ActivityThread.handleSendResult(ActivityThread.java:3553)
    E/AndroidRuntime(22226):    at android.app.ActivityThread.access$1200(ActivityThread.java:165)
    E/AndroidRuntime(22226):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1374)
    E/AndroidRuntime(22226):    at android.os.Handler.dispatchMessage(Handler.java:99)
    E/AndroidRuntime(22226):    at android.os.Looper.loop(Looper.java:176)
    E/AndroidRuntime(22226):    at android.app.ActivityThread.main(ActivityThread.java:5455)
    E/AndroidRuntime(22226):    at java.lang.reflect.Method.invokeNative(Native Method)
    E/AndroidRuntime(22226):    at java.lang.reflect.Method.invoke(Method.java:525)
    E/AndroidRuntime(22226):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1209)
    E/AndroidRuntime(22226):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1025)
    E/AndroidRuntime(22226):    at dalvik.system.NativeStart.main(Native Method)
    E/AndroidRuntime(22226): Caused by: java.lang.IllegalArgumentException: filename cannot be null
    E/AndroidRuntime(22226):    at android.media.ExifInterface.<init>(ExifInterface.java:121)
    E/AndroidRuntime(22226):    at org.apache.cordova.camera.ExifHelper.createOutFile(ExifHelper.java:66)
    E/AndroidRuntime(22226):    at org.apache.cordova.camera.CameraLauncher.processResultFromCamera(CameraLauncher.java:430)
    E/AndroidRuntime(22226):    at org.apache.cordova.camera.CameraLauncher.onActivityResult(CameraLauncher.java:610)
    E/AndroidRuntime(22226):    at org.apache.cordova.CordovaActivity.onActivityResult(CordovaActivity.java:784)
    E/AndroidRuntime(22226):    at android.app.Activity.dispatchActivityResult(Activity.java:5563)
    E/AndroidRuntime(22226):    at android.app.ActivityThread.deliverResults(ActivityThread.java:3506)
    E/AndroidRuntime(22226):    ... 11 more

code that I have used to open the camera is :

   var pictureSource; // picture source
var destinationType; // sets the format of returned value
document.addEventListener("deviceready", onDeviceReady, false);

function onDeviceReady() {
  // alert("ready-----")
  pictureSource = navigator.camera.PictureSourceType;
  destinationType = navigator.camera.DestinationType;
}

function capturePhoto() {
  alert(navigator.camera);
  navigator.camera.getPicture(onPhotoDataSuccess, onFail, {
    quality: 20,
    destinationType: destinationType.FILE_URI,
    targetWidth: 200,
    targetHeight: 200,
    saveToPhotoAlbum: true,
    sourceType: pictureSource.CAMERA
  });
}

function onPhotoDataSuccess(imageURI) {
  // alert("success--");
  var smallImage = document.getElementById('smallImage');
  smallImage.style.display = 'block';
  smallImage.src = imageURI;
  // smallImage.src = "data:image/jpeg;base64," + imageData;
}

function onFail(message) {
  alert('Failed because: ' + message);
}

The bug is already logged in Apache Cordova.

Help!!!

nitesh goel
  • 6,338
  • 2
  • 29
  • 38
  • Your sample code is the same as in `Phonegap's` documentation. It's also similar to `Cordova's` documentation, where the only difference is this line: `destinationType: Camera.DestinationType.FILE_URI, sourceType: Camera.pictureSource.CAMERA` in options object. Have you tried those instead? Which version of cordova or phonegap are you using? – JcDenton86 Jun 12 '15 at 06:48

3 Answers3

3

Try replacing your capturePhoto() function with this (this is working code from my own app):

function capturePhoto() {
    var options = {
        quality: 75,
        destinationType: Camera.DestinationType.FILE_URI,
        sourceType: Camera.PictureSourceType.CAMERA,
        mediaType: Camera.MediaType.CAMERA,
        encodingType: Camera.EncodingType.JPEG,
        targetWidth: 200,
        targetHeight: 200,
        saveToPhotoAlbum: true
    };
    navigator.camera.getPicture(onPhotoDataSuccess, onFail, options);
}
Mike Dailor
  • 1,226
  • 8
  • 16
  • I was having a similar problem on my android device and it turned out my encoding type was set to PNG. Changing it to JPEG solved this for me – Kevin Jul 05 '15 at 00:23
  • @Mike Dailor: you saved my day man. I was having issues for ionic v1 app running on android 11. And your config fixed my issue. You are the best. Thanks a lot. – maverickosama92 Sep 14 '21 at 12:46
1

please change your destination type:

destinationType: destinationType.FILE_URI

to

destinationType: Camera.DestinationType.FILE_URI

if you required it as a base64-encoding image, then change destination type as:

destinationType: Camera.DestinationType.DATA_URL

also make sure that you have added the write external storage permission in your manifest file.

Karan Maru
  • 991
  • 6
  • 17
  • I need image in file not as a binary string. – nitesh goel Jun 12 '15 at 06:14
  • did you change your destination type? with a use of destinationType: Camera.DestinationType.FILE_URI, you will get image's file location. – Karan Maru Jun 12 '15 at 06:20
  • May be you can remove target height and target width parameter just give it a try it happens with mine too.. –  Jun 13 '15 at 13:00
0

The plugin is passing a null pointer to ExifInterface causing an exception, which didn't happen in older plugins.

Try applying the following fix, also can you report the device Brand, Model and android version as well ?

https://issues.apache.org/jira/browse/CB-9446

diff --git a/src/android/ExifHelper.java b/src/android/ExifHelper.java
index 5160a2f..0af0fcd 100644
--- a/src/android/ExifHelper.java
+++ b/src/android/ExifHelper.java
@@ -53,7 +53,11 @@ public class ExifHelper {
  * @throws IOException
  */
 public void createInFile(String filePath) throws IOException {
-        this.inFile = new ExifInterface(filePath);
+        if (filePath != null) {
+            this.inFile = new ExifInterface(filePath);
+        } else {
+            throw new IOException("null pointer passed to createInFile");
+        }
 }

 /**
@@ -63,7 +67,11 @@ public class ExifHelper {
  * @throws IOException
  */
 public void createOutFile(String filePath) throws IOException {
-        this.outFile = new ExifInterface(filePath);
+        if (filePath != null) {
+            this.outFile = new ExifInterface(filePath);
+        } else {
+            throw new IOException("null pointer passed to createOutFile");
+        }
 }

 /**
diff --git a/src/android/FileHelper.java b/src/android/FileHelper.java
index 59f890e..cd4b6ef 100644
--- a/src/android/FileHelper.java
+++ b/src/android/FileHelper.java
@@ -33,6 +33,7 @@ import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Locale;
+import android.util.Log;

 public class FileHelper {
 private static final String LOG_TAG = "FileUtils";
@@ -54,9 +55,12 @@ public class FileHelper {
 realPath = FileHelper.getRealPathFromURI_BelowAPI11(cordova.getActivity(), uri);

 // SDK >= 11 && SDK < 19
-        else if (Build.VERSION.SDK_INT < 19)
+        else if (Build.VERSION.SDK_INT < 19) {
 realPath = FileHelper.getRealPathFromURI_API11to18(cordova.getActivity(), uri);
-
+            if (realPath == null) {
+                realPath = getRealPathFallback(uri.toString(), cordova);
+            }
+        }
 // SDK > 19 (Android 4.4)
 else
 realPath = FileHelper.getRealPathFromURI_API19(cordova.getActivity(), uri);
@@ -126,6 +130,47 @@ public class FileHelper {
 return result;
 }

+    /**
+     * Returns the real path of the given URI string.
+     * If the given URI string represents a content:// URI, the real path is retrieved from the media store.
+     *
+     * @param uriString the URI string of the audio/image/video
+     * @param cordova the current application context
+     * @return the full path to the file
+     */
+    @SuppressWarnings("deprecation")
+    public static String getRealPathFallback(String uriString, CordovaInterface cordova) {
+        String realPath = null;
+        try {
+            if (uriString.startsWith("content://")) {
+                String[] proj = { _DATA };
+                Cursor cursor = cordova.getActivity().managedQuery(Uri.parse(uriString), proj, null, null, null);
+                int column_index = cursor.getColumnIndexOrThrow(_DATA);
+                cursor.moveToFirst();
+                realPath = cursor.getString(column_index);
+                Log.d(LOG_TAG, "getRealPath managedQuery success uri " + uriString + " realpath " + realPath);
+                if (realPath == null) {
+                    Log.e(LOG_TAG, "getRealPath Could get real path for URI string " + uriString);
+                }
+            } else if (uriString.startsWith("file://")) {
+                realPath = uriString.substring(7);
+                Log.d(LOG_TAG, "getRealPath file:// " + uriString + " realpath " + realPath);
+                if (realPath.startsWith("/android_asset/")) {
+                    Log.e(LOG_TAG, "getRealPath Cannot get real path for URI string " + uriString + " because it is a file:///android_asset/ URI.");
+                    realPath = null;
+                }
+            } else {
+                realPath = uriString;
+            }
+        } catch (Exception e) {
+            Log.d(LOG_TAG, "getRealPath using uristring could not find real path, uriString: " + uriString + " message: " + e.getMessage());
+            realPath = uriString;
+        }
+
+        return realPath;
+    }
+
+
 public static String getRealPathFromURI_BelowAPI11(Context context, Uri contentUri) {
 String[] proj = { MediaStore.Images.Media.DATA };
 String result = null;
Karthik
  • 4,950
  • 6
  • 35
  • 65