Monday, July 2, 2012

Change to Camera code in PhoneGap 1.9.0

With the release of PhoneGap 1.9.0 I've checked in some improvements to the Camera.getPicture() functionality. First a bit of an explanation as to why there are so many issues with the Camera code.

One of the major causes of issues is that as new devices get released the cameras in them get better and better allowing you to take very high resolution images. Now when you specify a few parameters to our getPicture method like quality or targetWidth/targetHeight you can get out of memory errors. Why do you get out of memory errors you ask? Well in my honest opinion it is because Android does a real poor job of handling Bitmaps. In order to do any manipulation on an image like scaling or compression you need to load the entire image into memory.

Let's take a look at a real world example. My Samsung Galaxy Note has an 8MP camera with a resolution of 3264 by 2448. So in memory that picture assuming ARGB_8888 will be:

3264 pixels x 2448 pixels x 4 bytes/pixel = approximately 30 megabytes 

Let that sink in, approximately 30 megabytes. Considering that I read somewhere the default heap size for an app running in Dalvik is 48 megabytes you can see how you can quickly run out of memory taking pictures.

Fixing the Best Case Scenario 

I've added some code to detect the best case scenario and not load the image into memory. Here is the getPicture method to call if you want to use the best case all the time.
var options = {
    quality: 100,
    destinationType : navigator.camera.DestinationType.FILE_URI,
    sourceType: navigator.camera.PictureSourceType.CAMERA,
    encodingType: navigator.camera.EncodingType.JPEG,
  }
  navigator.camera.getPicture(win, fail, options);
The important part about the options is that you specify a quality of 100. This along with accepting the default width and height will skip the need to load the image in memory.

Reducing Memory when using targetWidth/targetHeight

Okay but if you do specify a targetWidth/targetHeight the image has to be loaded into memory. Now we do a bit of math to figure out the smallest multiple of the image that can be loaded that isn't smaller than the requested width and height. You see the Bitmap.createScaledBitmap() method allows you to specify that the bitmap be load at half, quarter, etc. size. Now if you request a 900x900 image from a 2000x2000 original image it will be loaded into memory as 1000x1000 and scaled from that point. It saves about 11 megabytes of memory doing it this way.

Respects the saveToPhotoAlbum option

Up until 1.9.0 each picture taken automatically gets added to the Android photo album/gallery. As of 1.9.0 if you want that type of behaviour to continue you need to set this option to true as the default is false.

Respects the correctOrientation option

One of the other big problems with our Camera functionality is that pictures taken in portrait mode were always displayed on their side when you attempted to view them in your app. Remember your app is based off of a WebView and the web view does not care about the exif orientation parameter. Now if correctOrientation is set to true we rotate the image so that it will show up properly in the WebView and we reset the orientation parameter to normal so it'll show up properly in desktop image viewers.

If you run into problems using the Camera in 1.9.0 please raise a bug on JIRA and give a detailed  reproduction scenario. I want to make sure this functionality is rock solid for the upcoming 2.0.0 release.

118 comments:

jax said...

There's no stopping Simon it seems! :) Well done and thanks.

steve-c said...

Thanks, but I have problem about display photo and send it to server.

path return "file:///data/data/com.xxx.xxxx/.Pic.jpg?12345678" in 1.9


img src="path" cannot display

but I can display and send the photo using path in 1.8.1

path return content://media/external/images/media/xxxx
in 1.8.1


my problem same as following link:
https://groups.google.com/group/phonegap/browse_thread/thread/b580a165da9a64b2/ad4749e9a55bb716?lnk=raot

Summved Jain said...

Hi Simon,

Hope you are doing well

I have a query if you can help me.

I am using phonegap 1.3 and created Android plugin with the help of the document given http://tinyurl.com/42sa79b . Now I am trying to update to Phonegap 1.9 but it is giving me an error that
import com.phonegap.api.PluginResult.Status;
Status in the above statement cant be resolved. I have read the documentation of phonegap 1.9 release and it says that some of the Android plugin will not work properly.

Please help me and provide some suggestions why it is not working?

Thanks in advance
Summved

Simon MacDonald said...

@Summved Jain

Just change references to "com.phonegap" to "org.apache.cordova" as the package of the classes has changed.

Simon MacDonald said...

@steve-c

Yeah, if you set saveToPhotoAlbum to true in your options it will get back to providing you the content:// type uri. There is no reason why you shouldn't be able to see the image in your own /data/data directory. I've put in a small fix for this issue and I'll post to the PG group thread where you can pick up a jar to test.

Summved Jain said...

Thanks Simon,

Could you please also let me know what does cordova means here? Is the name has changed from phonegap to Cordova?


Summved

Simon MacDonald said...

@Summved Jain

Yes, the name has changed. We moved the project to Apache for safe keeping so the package name of the Java classes changed.

admins said...

Great article, but it didn't stop crashing the app with me.
Now it doesn't crash when taking a picture, but when choosing a picture from your folders, it still crashes.

My settings:

quality: 100,
destinationType: navigator.camera.DestinationType.FILE_URI,
sourceType: source,
encodingType: navigator.camera.EncodingType.JPEG


On success, I put the imageURI to another variable, and then I have another button to send the image.
It crashes after choosing the picture, so I think it doesn't have anything to do with the sending etc.

http://pastebin.com/4LBNGxdz
This is my full code at the moment.

Simon MacDonald said...

@admins

The code you are using looks fine but what I really need to see is the error. Can you run "adb logcat" so I can see what is going on?

admins said...

Thanks for the prompt answer Simon!

http://pastebin.com/xmR7Lurx
I pasted the whole LogCat error log there. I hope you can figure out something!

Simon MacDonald said...

@admins

O I C

You are running into an OutOfMemory error when trying to load the image. I think I can do something about this. Please stand by. I may be able to post a .jar for you to test. in 30 minutes.

Simon MacDonald said...

@admins

Please grab a patched jar from:

https://dl.dropbox.com/u/887989/cordova-1.9.0.jar

It should fix the out of memory error you are getting. Let me know what you find and then I'll check in the fix.

admins said...

Thank you so much!
That completely fixed my problem :)

Do you happen to know why the pictures appear sideways when I upload them? This seems to be a usual problem with image uploaders in Android, so I'd like it fixed in my app :P

Summved Jain said...

Thanks Simon,

That was really helpful. Thanks for your prompt reply.

Could you please guide me with some tutorials or books to learn phonegap and JQuery mobile.

Kind Regards,
Summved

Simon MacDonald said...

@admins

I've just checked in the fix.

If you are having orientation problems it is probably because you are taking the picture in portrait mode while most phones expect you to take it in landscape more. You can try setting correctOrientation to true when you use getPicture().

Simon MacDonald said...

@Summved Jain

I don't do jQuery Mobile. I haven't found it to be very good on Android. Look at using Sencha Touch or Dojo Mobile instead.

To learn more about PhoneGap besides my blog posts there are:

http://phonegap.com/blog
http://www.amazon.com/Recipes-Programming-PhoneGap-Cross-Platform-Development/dp/1449319548/ref=sr_1_1?ie=UTF8&qid=1341592909&sr=8-1&keywords=phonegap
http://www.amazon.com/PhoneGap-Essentials-Building-Cross-Platform-Mobile/dp/0321814290/ref=sr_1_3?ie=UTF8&qid=1341592909&sr=8-3&keywords=phonegap
http://www.amazon.com/PhoneGap-Essentials-Building-Cross-Platform-Mobile/dp/0321814290/ref=sr_1_3?ie=UTF8&qid=1341592909&sr=8-3&keywords=phonegap

Summved Jain said...

Hello Simon,

Sorry to bother you again.
Could you please help me with the below query?

I'm using Phonegap to develop my application and I'm trying to get the app to list files on the sdcard. But only specific files, for example mp3 or my own file format. I've been trying to use the Phonegap API as it seems to have a directory reader action, but I don't know how to use it.

Kind Regards,
Summved

Simon MacDonald said...

@Summved Jain

Take a look at this thread. You'll need to check to see if the name of the file ends with .mp3 but other than that the code is written for you.

https://groups.google.com/d/msg/phonegap/jsMF9Qf4918/E9T2g3UsV5YJ

Summved Jain said...

Thanks so much

That was really helpful. Let me test this and will update you.

Kind Regards,
Summved

admins said...

Hi again, Simon.

It seemed that it worked at first, but when I now test to take a picture with camera, it's crashing.

http://pastebin.com/4UmCmiqq
This is the error log again.

Selecting the image from gallery works fine, but taking a new picture crashes the program.

When I first contacted you, selecting a picture crashed, while taking a picture didn't. So this is the opposite of the previous problem.

admins said...

Update to the comment before, it crashes randomly when selecting a image from gallery too :/

http://pastebin.com/6pMstMn0

Simon MacDonald said...

@admins

It looks like it ran out of memory trying to correct the orientation of the picture. What options are you using when calling getPicture from the camera? Are you taking the picture in portrait mode? How good is the camera resolution? You may want to try the same test with correctiOrientaiton set to false.

Basically, I'm trying my hardest to keep memory usage down but Android handles images really poorly.

admins said...

Hey,

I know that it's Android problem, but it seems that you're the one and only person I could contact now.
I'm glad that you still try to figure the problems, even though it's hard.

I'm using Samsung Galaxy S II and camera is 8MP and images 3264x2448.

It really seems that it works when I set correctOrientation to false.
I'm taking pictures in portrait mode.

At the moment, I'm taking pictures with these settings:
{ quality: 100, destinationType: navigator.camera.DestinationType.FILE_URI, sourceType: source, encodingType: navigator.camera.EncodingType.JPEG, correctOrientation: false }

Source is user's choice, you can select between navigator.camera.PictureSourceType.PHOTOLIBRARY/CAMERA

Simon MacDonald said...

@admins

Yeah, that is the same resolution as my Samsung Note. That means the image in memory is about 31 megabytes and then the secondary image to hold the rotation data is another 31 megabytes and boom! Out of memory error.

It looks like we'll need to write our own image manipulation code to get around this issue but that's not going to happen this morning. I wish but other duties call.

In the mean time try requesting a smaller targetWidth and targetHeight will save on memory usage. That might not fit the use case for your app but at least it'll get around most crashes for now.

Talk to you soon.

Duncan said...

Hi Simon,

Just wondering, do you happen to know of any good way of retaining the exif data once you've resized an image?

The ones I seem to lose are, well, all of them, but I'm trying to retain the ones related to the datetime of when the image was created and the gps lang and long co-ordinates...Idea is that someone can upload the image at some point in the future and it'll put itself nicely where they took the picture and when, if you see what I mean.

Thanks in advance :)

Roshan Chaudhary said...

the application crashes when trying to access image from es file explorer in android using phonegap camera photolibrary source. can u suggest some solution.

Simon MacDonald said...

@Duncan

The only way for the EXIF info not to be touched is to specify a quality of 100 and a destination of FILE_URI. Don't use any other parameters as that will cause the file to get re-written. I can only keep the following EXIF information as that is what the SDK will allow me to access:

https://developer.android.com/reference/android/media/ExifInterface.html

GPS and Datetime should stick around. They do on my Samsung phone.

Simon MacDonald said...

@Roshan Chaudhary

Use the Gallery app instead. Open an issue on JIRA:

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

and include "adb logcat" so I can see what is going on.

alex said...

Hi simon ... very nice post.
I tell you my scenario.

Mobile: LG3 with Android 4.0
Using PhoneGap 1.9.0
Using this function:

navigator.camera.getPicture(onPhotoDataSuccess, onFail,
{
quality: 80,
destinationType: destinationType.FILE_URI,
encodingType: navigator.camera.EncodingType.JPEG,
mediaType: 0,
targetWidth: 1024,
targetHeight: 768,
correctOrientation: false
}
);

Taking the first picture gives no problem. After second photo, logcat gives this:
http://pastebin.com/WJ2KTBh4
and app is closed.

As you can see I'm using library, no orientation, slow resolution, slow quality ...

Any ideas ?

THANK YOU in advance

Summved Jain said...

Hi Simon,

I am using Camera API with Cordova 1.8.1 but not able to make it work. The same code works with phonegap 1.3.0. The API is not returning the base64 of the image. It returns some text that says "content://media/external/images/media/373". The number 373 is changing everytime when camera clicks. Check the code below: -

navigator.camera.getPicture(onCameraSuccess, onError, { quality: 50, destinationType: Camera.DestinationType.FILE_URL });

function onCameraSuccess(imagedata) {
alert(imagedata);
}

This alert shows the above text in case of 1.8.1 and shows the base64 in case of 1.3.0

Please help me on this as this is on priority

Kind Regards,
Summved

Simon MacDonald said...

@Summved Jain

You are getting a FILE_URI because that is what you specify in your getPicture command. Change FILE_URI to DATA_URL and you will get a base64 encoded image.

Summved Jain said...

Hi Simon,

Thank you so much
It is working fine. Could you please let me know when I click the picture using the API, it stores in phone sd card but when I try to look at that picture, it doesnt show up. It says preview not available and you can not see that image even when you copy it to your computer.

Kind Regards,
Summved

Simon MacDonald said...

@Summved Jain

Sorry, I don't understand what you are asking. Please provide more details over at:

http://www.formspring.me/macdonst

Simon MacDonald said...

@alex

Looking at the stack trace it is an out of memory error. Which I can't do much about. What is the quality of your camera? That is what is the native resolution?

Sazzad-Hossain said...

Hi,

We have implemented the camera capture function in our app with phonegap 1.9 and using it on 30+ device for 30 people. We have specified targetWidth and height of 640 x 800. Most of the time the app works perfectly. But occasionally and randomly we would get thumbnail size photos from the capture function. This is bugging me a lot since we can not reproduce it everytime. We are using Galaxy Tab original with 2.2 and S3 and some Galaxy Notes. And it happens for all the devices on a random basis.

Just wanted to find out if anyone experienced any issues like this. Looks to me that the image we get is the thumbnail image.

Thanks,

Sazzad

Simon MacDonald said...

@Sazzad-Hossain

This is the first I've heard of this type of bug. Can you please open an issue on JIRA?

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

Provide as many details as you can and logs are always good.

megha rathore said...

Hi Simon,

i am using cordova 2.0,in some phones camera.getPicture() directly opens the image gallery but in some it gives an option either to open image gallery or file explorer, if i open file explorer and select a non image file my app crashes saying application not responding.please help.
Thanks,
Megha

Simon MacDonald said...

@megha rathore

I believe I've fixed all those bugs in 2.1.0 as part of this issue:

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

megha rathore said...

Hi Simon,
Thanks for your prompt reply,by the way when will cordova 2.1.0 be released? as we need to fix this bug asap and send the release to client in three days.
Thanks
Megha Rathore

Simon MacDonald said...

@megha rathore

Well we are going through the voting process of getting from incubator to full fledged Apache project. The whole process has taken much longer than I excepted so I hate to comment on a date but I hope to see it early next week.

megha rathore said...

Hey Simon,

in regard with my previous query i updated my phonegap with the latest release(2.1) and found that my app still crashes if i select a non image file (say an audio file or a js file) giving me a message that sorry Unfortunately (my_app_name) has stopped working. :(

Megha Rathore

Simon MacDonald said...

@Megha Rathore

Okay, what app are you using to select the non-image file? Can you post up the crash in "adb logcat" on gist or pastebin so I can see it?

megha rathore said...

Hi Simon,

The app which i am using for selecting a non image file is ES File Explorer (Google market), you can checkout my "adb logcat" here-
https://gist.github.com/3786334

Thanks
Megha

Simon MacDonald said...

@Megha Rathore

Cool, I will try to reproduce.

Simon MacDonald said...

@Megha Rathore

Cool, I will try to reproduce.

Simon MacDonald said...

@Megha Rathore

The normal way works for me but the file way crashes the app. I just checked in a fix to guard against the ES File Explorer returning things the "file way".

Honestly looking at your stack trace it appears you are still using the old 2.0.0 jar file.

megha rathore said...

Hey Simon,
Thanks again for your quick reply, and yeah i am sorry by mistake i sent you the wrong stack trace(2.0), but anyway the same problem is showing up on 2.1.0 as well.
from where can i checkout your fix by the way?
Thanks
Megha

Simon MacDonald said...

@Megha Rathore

Can you show me the stack trace from the 2.1.0 run? It shouldn't be the same at all. If you want to grab the fix it has been checked in to:

https://git-wip-us.apache.org/repos/asf?p=incubator-cordova-android.git;a=summary

megha rathore said...

Hey Simon,

Thanks a lot for the fix, i will try it out and let you know. :)
and here is the error log from cordova 2.1.0 run

https://gist.github.com/3798252

Thanks
Megha

megha rathore said...

Hey Simon,

Just wanted to add that for me app crashes either ways( file way as well as normal way), here is the error log from the run of cordova 2.1.0

https://gist.github.com/3798393

Thanks
Megha

Simon MacDonald said...

@megha rathore

Okay, it is the same error. I think I need a more detailed test case as I'm missing out on the problem. So you use ES File Explorer to get the image and it does matter which option you pick from the dialog. I guess it must be something in the options you are sending to getPicture() that I'm not accounting for. Can you send me the line you use for getPicture with all the options you use?

megha rathore said...

Hey Simon,

here is what i am using

navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 100,
destinationType: destinationType.DATA_URL,
sourceType: source,
targetWidth: 65,
targetHeight: 65
});


Thanks
Megha

Simon MacDonald said...

@megha rathore

Oh, a DATA_URL, never thought to test that. I will give it another try.

Simon MacDonald said...

@megha rathore

Wow, don't know why DATA_URL made a difference but it did and I reproduced then fixed the bug. It'll be in 2.2.0.

Simon MacDonald said...

@megha rathore

Wow, don't know why DATA_URL made a difference but it did and I reproduced then fixed the bug. It'll be in 2.2.0.

megha rathore said...

Hey Simon,

Thanks a lot :) now waiting for cordova 2.2.0

Thanks
Megha

megha rathore said...

Hey Simon,
Can i ask you for the patch required to solve my problem?(PG crash on using DATA_URL for non image files), need it urgently.
Thanks
Megha Rathore

Simon MacDonald said...

@megha rathore

You can grab the latest source from:

https://git-wip-us.apache.org/repos/asf?p=incubator-cordova-android.git;a=summary

and build it yourself. Alternatively we are tagging 2.2.0rc1 on Friday so a release candidate binary should be posted on PhoneGap.com early next week.

vivek s said...

Hi simon,
we are having an serious issue that needs to be fixed ASAP.Please do help us.Using cordova 2.1.0, we face the app getting closed when taking a picture from camera and pressing ok button... what is the real problem here?

Simon MacDonald said...

@vivek s

Not enough info. What do you see in "adb logcat"?

Susanna said...

Hi Simon,

I'm running out of options with a camera bug.
Device: Samsung Galaxy s2
Android: 4.0.4
Phonegap: 2.0.0

The camera crashes the whole application when I click save.

I couldn't find a MemoryOutOfBounds error which I had with the 1.8.0, but the behaviour of the camera is the same.

call after deviceready:

https://friendpaste.com/2CRvGWUP2BPYF3k4nIYbFC

Adb logcat:

https://friendpaste.com/2CRvGWUP2BPYF3k4nIYcTC

Simon MacDonald said...

@Susanna

What Camera app are you using? I'm seeing a weird return value for the requestCode.

Susanna said...

@Simon I'm using the default one, Camera version 1.0

Susanna said...

@ Simon

and as additional info, the log of a test run with taking only black pictures. I managed to get the crash after 5 pictures.

adb logcat:
https://friendpaste.com/2CRvGWUP2BPYF3k4nIpY9j

Simon MacDonald said...

@Susanna

I'm at a loss to explain what is going on. When you say it crashes do you mean the application restarts? If so the app may be cleared up by the OS while you are in the Camera app to reduce memory usage.

Susanna said...

@Simon

So the application closes completely. It happens between navigator.camera.getPicture and the success callback. So I get the console logs before and after navigator.camera.getPicture but never the one at the first line of success callback when the app crashes.

Susanna said...

@ Simon

Solved the problem.

and it was:

adding this to android manifest
android:configChanges="orientation|screenSize|keyboardHidden"
AND
because the application is using backbone I navigate on success to the same page I came from through the router.

Before I just saved the image to a model and through a change in the model rendered the view again.

I still don't throughly understand why, but hey, it works!

and thanks, "If so the app may be cleared up by the OS while you are in the Camera app to reduce memory usage." led me to the right track :D

Simon MacDonald said...

@Susanna

ARG!!! Sorry, I should have suggested that earlier. It is a basic step in setting up your PhoneGap app. Without the orientation change Android will restart you app if you switch from portrait to landscape and since you are probably in portrait mode int the app then landscape mode for the camera it all makes sense.

Julien B said...

Hi Simon,
I have an issue when I try to take a picture in my phonegap application.
The picture saved in the Camera folder (Nexus 7 or Samsung Galaxy) seems to be corrupted: the file size is equal to 0kb.

However I can see the picture browsing the gallery on my phone.

I tried a simple project with different options but I didn't find any solution to get a picture saved with its right size.

Here is the javascript code used to take the picture:

destinationType: Camera.DestinationType.FILE_URI,
quality: 100,
allowEdit: false,
correctOrientation: false,
saveToPhotoAlbum: true

(sdk 11, 15 or 16)

Susanna said...

@Simon, no problem. I was the idiot just going android:screenOrientation="portrait"

but still, just adding the orientation change was not enough for the problem to be fixed.

Something with the models and views. However thanks a million times :)

Simon MacDonald said...

@Julien B

Hmmm...can you head over to:

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

and raise an issue? This seems to be a bug but I'd rather collect logs, etc. over there.

Austin said...

Hi Simon.

I have used getPicture successfully on my Galaxy Note running Cordova 2.0, but it has stopped working and I can't figure out why.

The symptoms are 'Camera cancelled.' error. I can't see any memory errors in the logcat output.

I have cut it down to a simple test case, and its still failing, here is the code:-

http://pastebin.com/UpyefMmZ

And the logcat output:-

http://pastebin.com/X4K0YvKU

One thing that caught my eye in the logcat shortly after calling getPicture was the line:

W/ActivityManager( 1854): Activity is launching as a new task, so cancelling activity result.

I wondered if this could be a project manifest setting that is causing the problem. My activity has the following options set

android:name=".RMCv2dev"
android:label="@string/title_activity_rmcv2dev"
android:configChanges="orientation|keyboardHidden|screenSize"
android:screenOrientation="portrait"
android:alwaysRetainTaskState="true"
android:launchMode="singleInstance"
android:hardwareAccelerated="true"

At the moment I am at a loss as to why the camera code has stopped working.

Austin said...

@Simon

I resolved my camera issue. I determined that the the problem was in my activity configuration in my manifest, which had

android:launchMode="singleInstance"

Is there any reason why this should option affect the camera? I had added it because I was sometimes getting multiple instances of my app running, which I don't want either.

vmv said...

u r simply awesome Simon,,,

Oliver Krylow said...

Hi Simon!

After testing this on Android 4.1.2 with Cordova 2.2.0, I have doubts, that your optimization for the "best case scenario" still works.

These are my observations on a Samsung Galaxy SII :

(using the options in your post) --> screen freezes ,after 8MP image was taken and control is passed back to my app. Heap grows by 31961104 bytes.

(extending your options by targetWidth and targetHeight ; 1000px) --> works as expected. Heap grows by 7990288, then by 3000016 bytes.

Now I don't know if anything significant has changed since your post, or if I am doing things wrong.

Should I post this as an issue?

Sandeep Narwal said...


Post its amazing Simon. Please have a look at my error, im have been trying almost everything its to fix the camera Crash, but nothing works for me.

http://pastebin.com/mCv95469

quality: 100,
destinationType : navigator.camera.DestinationType.FILE_URI,
sourceType: navigator.camera.PictureSourceType.PHOTOLIBRARY,
encodingType: navigator.camera.EncodingType.JPEG,
correctOrientation: false,
targetWidth: 1024,
targetHeight: 768

Simon MacDonald said...

@Sandeep Narwal

There is nothing in that log that indicates a crash. I think you may have sent me the wrong link.

Hugo Maia Vieira said...

Hello Simon,

Thanks for the great work (blog, plugins, phonegap etc)!

I'm having a problem that some others already complain. The camera restarts my app 90% of times.

I'm using Phonegap 2.2.0 on android 2.3.4 and 4.0.4.
I have the "android:configChanges="orientation|keyboardHidden" on my android manifest.
I have tried your tips from this post.

Here is a log: http://pastebin.com/Xp5yE9s3

I can't identify a memory problem. The app is killed before a took the picture.

Can you help me?

Thanks!

Simon MacDonald said...

@Hugo Maia Vieira

What camera app are you using? I see that there is an error popping up from the C code. Have you tried a different camera app?

Rahul Mendonca said...

Hi Simon in certain phones i can access photo but not in other albums get error aS UNDEFINED .Im using photo library option and not savedtophotoalbum.How do i solve this problem in order to access photos

Simon MacDonald said...

@Rahul Mendonca

Can you provide me with more details?

Hugo Maia Vieira said...

Simon, I'm using the default camera app. After I install another camera app (http://migre.me/cz3IN) the problem stops with both camera apps.

But this is happening with some users of my app, with different andoid versions and phones models.

There is anything I can do?

Simon MacDonald said...

@Hugo Maia Vieira

You didn't really explain what problem you are running into. Also if you've found a solution by installing a 3rd party app that's great news.

niranjana devi said...

Hi Simon,

I used this code to capture image in my application

navigator.camera.getPicture(onPhotoURISuccess, onFail, { quality: 100,
destinationType: navigator.camera.DestinationType.FILE_URI,
saveToPhotoAlbum: true,
correctOrientation: true,targetWidth: 100,
targetHeight: 100 });


its working. but every time i capture the image, my application size increases for 2MB each time.I think it is storing somewhere along with the application. how to solve this?


Thanks,

Simon MacDonald said...

@niranjana devi

Well each picture is initial saved in your apps temp directory and it is called ".Pic.jpg". The image name is reused each time you take a picture so it shouldn't continue to increase after the first picture taken.

Yuguang Zhao said...

hello! , Simon Mac,sorry to troblue you,please take some time look for my questions,i used cordova-2.0.0.js,but when i taked photos,my app progrom will exit,my logcat is:
https://groups.google.com/forum/#!topic/phonegap-take-picture-error/-Foi6_rOqoM
Thank you !!!

Simon MacDonald said...

@Yuguang Zhao

There is nothing in your logcat that indicates a crash.

Yuguang Zhao said...

When my program crash and then restart eclipse logcat will appear this a hint
Could not find method android.webkit.WebView., referenced from method org.apache.cordova.CordovaWebView.

Simon MacDonald said...

@Yuguang Zhao

I'm looking for a stack trace.

shruti nair said...

Hi Simon,

I'm trying to make camera work on s3, every time i click the save button after capturing the image the app crashes.
This is the code i'm using .

navigator.camera.getPicture(onPhotoURISuccess, onFail, { quality: 20,
sourceType: navigator.camera.PictureSourceType.CAMERA,
mediaType: navigator.camera.MediaType.PICTURE,
destinationType: Camera.DestinationType.FILE_URI,
targetHeight:1024});
I'm using phonegap 1.9.0.

Please help me

Thanks!

Simon MacDonald said...

@shruti nair

First, check "adb logcat" to see if you are getting an out of memory exception. If that is the case you may need to upgrade to 2.4.0 as the camera on the S3 is very good and creates very large images.

Simon MacDonald said...

@Oliver Krylow

Yes, it looks like there was an issue in 2.3.0. It should be resolved in the upcoming 2.4.0.

shruti nair said...

No we are not getting any out of memory exception but can we use any lower cordova version to solve this issue. We have found a solution for that, if we fix the orientation of the application to Landscape mode, the Camera will work in all devices however, our app is only required portrait orientation. Is there a way to fix the orientation on a specific page so we can open camera on landscape orientation and will use the app in portrait on other pages?

Thanks

Simon MacDonald said...

@shruti nair

If your app is crashing then there is definitely a stack trace. What do you see from the stack trace?

ranjjose said...

Hi Simon
Thanks for this post.
Not sure whether you are still looking into this.

I am stuck with this problem for 1 week. I have tried so many things like using different versions of cordova(2.1, 2.5, 2.7, etc.) and some of the configurations like keeping:
quality: 100
Leaving targetWidth, targetHeight so that default values will be taken etc.

The issue is that once I take picture and while returning to the app, it crashes. This is happening only in some phones(Samsung Galaxy ACE, Micromax A87).

The following is the stacktrace:

05-19 18:21:10.449: W/dalvikvm(9945): threadid=1: thread exiting with uncaught exception (group=0x40142560)
05-19 18:21:10.459: E/AndroidRuntime(9945): FATAL EXCEPTION: main
05-19 18:21:10.459: E/AndroidRuntime(9945): java.lang.RuntimeException: Unable to resume activity {com.eiris/com.eiris.InAppTest}: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=33, result=-1, data=Intent { (has extras) }} to activity {com.eiris/com.eiris.InAppTest}: java.lang.NullPointerException
05-19 18:21:10.459: E/AndroidRuntime(9945): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2120)
05-19 18:21:10.459: E/AndroidRuntime(9945): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2135)
05-19 18:21:10.459: E/AndroidRuntime(9945): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1668)
05-19 18:21:10.459: E/AndroidRuntime(9945): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
05-19 18:21:10.459: E/AndroidRuntime(9945): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
05-19 18:21:10.459: E/AndroidRuntime(9945): at android.os.Handler.dispatchMessage(Handler.java:99)
05-19 18:21:10.459: E/AndroidRuntime(9945): at android.os.Looper.loop(Looper.java:130)
05-19 18:21:10.459: E/AndroidRuntime(9945): at android.app.ActivityThread.main(ActivityThread.java:3683)
05-19 18:21:10.459: E/AndroidRuntime(9945): at java.lang.reflect.Method.invokeNative(Native Method)
05-19 18:21:10.459: E/AndroidRuntime(9945): at java.lang.reflect.Method.invoke(Method.java:507)
05-19 18:21:10.459: E/AndroidRuntime(9945): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:875)
05-19 18:21:10.459: E/AndroidRuntime(9945): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:633)
05-19 18:21:10.459: E/AndroidRuntime(9945): at dalvik.system.NativeStart.main(Native Method)
05-19 18:21:10.459: E/AndroidRuntime(9945): Caused by: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=33, result=-1, data=Intent { (has extras) }} to activity {com.eiris/com.eiris.InAppTest}: java.lang.NullPointerException
05-19 18:21:10.459: E/AndroidRuntime(9945): at android.app.ActivityThread.deliverResults(ActivityThread.java:2532)
05-19 18:21:10.459: E/AndroidRuntime(9945): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2107)
05-19 18:21:10.459: E/AndroidRuntime(9945): ... 12 more
05-19 18:21:10.459: E/AndroidRuntime(9945): Caused by: java.lang.NullPointerException
05-19 18:21:10.459: E/AndroidRuntime(9945): at org.apache.cordova.DroidGap.onActivityResult(DroidGap.java:849)
05-19 18:21:10.459: E/AndroidRuntime(9945): at android.app.Activity.dispatchActivityResult(Activity.java:3908)
05-19 18:21:10.459: E/AndroidRuntime(9945): at android.app.ActivityThread.deliverResults(ActivityThread.java:2528)
05-19 18:21:10.459: E/AndroidRuntime(9945): ... 13 more

Simon MacDonald said...

@ranjjose

The stack trace helps but I need to know what version of PhoneGap you are using when you reproduce this issue. Then I can line up the NPE with the line in DroidGap that causes it.

ranjjose said...

@Simon:
To follow up,
phonegap 2.7.0 also crashed (same stack-trace). With 2.1.0, however, the app was re-starting while coming back to the app after taking a photo.
Anyway, I could finally get it working by using foreground camera plugin(https://code.google.com/p/foreground-camera-plugin/). Thanks to them. Ref: https://groups.google.com/forum/?fromgroups#!topic/phonegap/S6bu5CSM5mQ

Patchara Lertudomtana said...

Hey Simon I still have this problem can u plz help me

Simon MacDonald said...

@Patchara Lertudomtana

Well I've done the best I can to have this issue happen less frequently but there is no way to completely remove it. What are you seeing?

Dan Smart said...

Hi Simon,

I'm having memory issues with Android 2.3 devices, with PhoneGap 2.8

The error is:

java.lang.RuntimeException: Unable to resume activity {com.dansmart.geosight/com.dansmart.geosight.Geosight}: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=34, result=-1, data=null} to activity {com.dansmart.geosight/com.dansmart.geosight.Geosight}: java.lang.NullPointerException
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2124)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2139)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1672)
at android.app.ActivityThread.access$1500(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3687)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=34, result=-1, data=null} to activity {com.dansmart.geosight/com.dansmart.geosight.Geosight}: java.lang.NullPointerException
at android.app.ActivityThread.deliverResults(ActivityThread.java:2536)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2111)
... 12 more
Caused by: java.lang.NullPointerException
at org.apache.cordova.CordovaActivity.onActivityResult(CordovaActivity.java:866)
at android.app.Activity.dispatchActivityResult(Activity.java:3908)
at android.app.ActivityThread.deliverResults(ActivityThread.java:2532)
... 13 more

This error appears after having taken a photo when you click the ‘Save/ok’ button to accept the picture before resuming with the app. I have 7 reports of this error, 6 of which are this week, so it's happening regularly now with PhoneGap 2.8 whereas it wasn't happening with our previous release which was 2.1.

We're using 100%, JPEG, FILE_URI, and no correction of orientation, as suggested. We also have android:configChanges="orientation|keyboard"

Any ideas? Would upgrading to 3.0 help?

Best regards,

Dan

Simon MacDonald said...

@Dan Smart

Upgrading to 3.0.0 probably won't help. The Camera Intent has been problematic in PhoneGap Android since day one and only gets worse as Camera HW gets better.

For config changes change it to:

android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale"

and give it a try.

dansmart said...

Thanks Simon - the strange thing is that the issue is being reported on older devices (Android 2.3), so it shouldn't be due to camera HW.

I've sent a release out with the update config, and I'll feedback if we get an improvement.

Dan

Austin said...

Could Cordova not access the camera directly rather than using the camera activity?

http://developer.android.com/reference/android/hardware/Camera.html

Also, with html5 coming along, could cordova use the html5 media capture APIs instead?

http://www.w3.org/TR/html-media-capture/

In my case, I got the application to stop crashing by reducing the target image size to quite a low resolution (1024x768 or something) and also upgrading the the next gen phone, so the issue went away, but we still have some bugzilla's open to consider either direct hardware access, or using html5 media to replace the cordova camera API.

Simon MacDonald said...

@Austin

Yes, we could implement our own camera functionality but we are not in the business of writing a Camera app. Personally I wouldn't want to maintain something like that. You can use the ForegroundCamera plugin which provides a simple UI for taking pictures without using an intent.

Well, we've already implemented an earlier version of the media capture API but it again uses intents. Personally I can't wait until the browser/web view natively implements more of the HTML5 API's as then PhoneGap can go away. Remember all of us PhoneGap devs are looking forward to the day where PhoneGap is no longer needed for folks to write HTML5/JS apps and get access to the device API's.

donantidees said...

Hi Simon,

Congrats for this great blog and your awesome work. I've been reading all your stuff but I can't find a solution for me :(

I've got an app that randomly crashes when selecting a picture from the Gallery. I've got this at manifest.xml:

android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale"

The js to get the picture is this one:
function selectPicture() {
pictureSource=navigator.camera.PictureSourceType;
destinationType=navigator.camera.DestinationType;

// Retrieve image file location from specified source
navigator.camera.getPicture(
onPhotoURISuccess, onFail, { quality: 25,
destinationType: destinationType.FILE_URI,
sourceType: pictureSource.PHOTOLIBRARY });
}

We are using phonegap 2.7, and the error it randomly throws is this one:

java.lang.RuntimeException: Unable to resume activity {com.xmile.events/com.xmile.events.MainActivity}: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=18, result=-1, data=Intent { dat=content://media/external/images/media/2072 }} to activity {com.xmile.events/com.xmile.events.MainActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2765)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2794)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2249)
at android.app.ActivityThread.access$600(ActivityThread.java:149)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1246)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:5092)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:564)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=18, result=-1, data=Intent { dat=content://media/external/images/media/2072 }} to activity {com.xmile.events/com.xmile.events.MainActivity}: java.lang.NullPointerException
at android.app.ActivityThread.deliverResults(ActivityThread.java:3342)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2752)
... 12 more
Caused by: java.lang.NullPointerException
at org.apache.cordova.DroidGap.onActivityResult(DroidGap.java:858)
at android.app.Activity.dispatchActivityResult(Activity.java:5293)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3338)
... 13 more


Please, could you help me? :) many thx

Simon MacDonald said...

@donantidees

I wish I had a solution for you. What is happening here and has been a problem for quite awhile is that Android is clearing out your application from memory. Then when the Intent to select a picture is done there is no app to return the value to. We've been banging our heads against this for awhile but we've got no solution as of yet.

donantidees said...

@Simon MacDonald

Ok :'( And there is no workaround possible to avoid it?

Simon MacDonald said...

@donantidees

Other than pulling in the foreground camera plugin into the code no.

TrialAndError said...

Hi Simon,
Thank you for this great post! I hope you can help me with pictureSourceType. It working perfectly, but I want to know; if I want the photo taken to be saved in gallery as well as local server, which sourcetype should I use? And I wish you write a tutorial on phonegap+picture+localserver+database+android.

I really appreciate your help and intelligent :)

Simon MacDonald said...

@TrialAndError

If you want the picture saved in the gallery you set the "saveToPhotoAlbum" option to "true". To save it on a server you'll need to use the FileTransfer.upload method.

marcos cuesta said...

Hi Simon, I'm using phonegap 2.8.0 and I have some problems when user take a picture from photolibrary.

When user select an image sometimes app crash.

I use this code:

navigator.camera.getPicture(seleccionada2, noseleccionada2, {
sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
quality: 100,
destinationType: Camera.DestinationType.DATA_URI,
allowEdit: true,
encodingType: Camera.EncodingType.PNG
});

The error is:

java.lang.RuntimeException: Unable to resume activity {com.perfilempleo.perfil/com.perfilempleo.perfil.Perfilempleo}: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=18, result=-1, data=Intent { dat=content://media/external/images/media/3186 }} to activity {com.perfilempleo.perfil/com.perfilempleo.perfil.Perfilempleo}: java.lang.NullPointerException
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2141)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2156)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1680)
at android.app.ActivityThread.access$1500(ActivityThread.java:121)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:943)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3701)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:624)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=18, result=-1, data=Intent { dat=content://media/external/images/media/3186 }} to activity {com.perfilempleo.perfil/com.perfilempleo.perfil.Perfilempleo}: java.lang.NullPointerException
at android.app.ActivityThread.deliverResults(ActivityThread.java:2553)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2128)
... 12 more
Caused by: java.lang.NullPointerException
at org.apache.cordova.CordovaActivity.onActivityResult(CordovaActivity.java:866)
at android.app.Activity.dispatchActivityResult(Activity.java:3908)
at android.app.ActivityThread.deliverResults(ActivityThread.java:2549)
... 13 more

Thanks in advance

Alejo Miguel Hernández García said...

Hi simon, Foreground Gallery Plugin is valid for phonegap 2.8.0?

Thanks in advance

Simon MacDonald said...

@marcos cuesta

Using DATA_URL instead of FILE_URI is a sure way to kill your app. You are either going to run out of memory and crash the app or have the calling app get cleared out to save memory.

Simon MacDonald said...

@Alejo Miguel Hernández García

I'm not sure as I did not write it but it should be easy to upgrade if required. Probably just needs a few changes to the Java code to find the right classes.

donantidees said...

@Simon MacDonald

Seems we are quite a few who would like to have the foreground plugin working with newer versions of Phonegap.

I've contacted vinicius but seems they have no time to work on it. So, is there any chance to make a call so someone can recode it? :)

Simon MacDonald said...

@donantidees

If I could make people do things, I'd be a much richer man than I am now :)

Seriously though, it shouldn't be too hard to convert it to 3.0.0. Take a shot at it yourself and let me know if you need help.

Daljeet Singh said...

hi simon

i have problem at camera when i use cordova 3.5 and capture pic from camera the image getting rotate 90 degree at left side

This is happen only at samsung note 2 and samsung grand at rest devices its working properly.

Thanx in advance

Simon MacDonald said...

@Daljeet Singh

Are you using the "correctOrientation" parameter in your call to getPicture?

IIRC sometimes Samsung puts their own bloatware camera on their devices and it is not coded as well as Google's camera.