nitesh goel
nitesh goel

Reputation: 6406

PhoneGap App Crash when take a new photo with Camera Plugin

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!!!

Upvotes: 11

Views: 5288

Answers (3)

Charles Verge
Charles Verge

Reputation: 1

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;

Upvotes: 0

Mike Dailor
Mike Dailor

Reputation: 1266

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);
}

Upvotes: 3

Karan Maru
Karan Maru

Reputation: 1001

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.

Upvotes: 1

Related Questions