Camera capture not working Android/1.9.0

1,629 views
Skip to first unread message

KenCorey

unread,
Jul 1, 2012, 9:05:43 AM7/1/12
to phonegap
Hi All,

I've seen lots of angst with the PhoneGap Camera functionality on
Android. Perhaps I'm adding more?

Please forgive the length...I wanted to cover all that I've tried and
discovered in the hope that it narrows down the search.

My test devices:
Google Nexus One phone, Cyanogenmod 7.0 (android 2.3.7)
SumVision Cyclone Astro tablet, Android 2.3.4
Ainovo Novo 7 basic, updated to Android 4.0.3

The problem:
On all devices, the picture is taken and stored to "/data/data/
com.flippinbits.cameratest/.Pic.jpg", and the uri that's returned is
similar to:
file:///data/data/com.flippinbits.cameratest/.Pic.jpg?12345678

Back in PhoneGap's WebView when the src of the img is set to the URI,
I get a broken image symbol on the screen. I've tried stripping the /
123457678 bit off, so the URI then is simply:

file:///data/data/com.flippinbits.cameratest/.Pic.jpg

On the Nexus One, and the Cyclone Astro, I can use adb shell to verify
that the image ".Pic.jpg" is, in fact, being created, and is the same
ownership as the other files in that directory (app_106 in this case),
and permissions of 770.

If I then type "cd /data/data/com.flippinbits.cameratest;cat .Pic.jpg
> /mnt/sdcard/Pic.jpg", then file explorer programs can see that file
as a valid .jpg just fine.

Interestingly, when either the Nexus One or the Cyclone Astro can load
images from the photo album and display them in img's on the web page,
but on the Novo 7 when I tap the button to ask for files from the
photo album nothing happens on the screen. I don't have an adb driver
for the Novo 7, so my invesigations there are quite a bit more
limited.

I've tried changing the size, the encodingType, and the quality
settings (most of the rest of the flags seem to be ignored on
Android). No change in behaviour.

When in adb shell on the Nexus One, and I type LogCat, I see this
interesting output:

D/CordovaWebView( 4861): >>> loadUrlNow()
D/MediaScannerService( 4762): IMediaScannerService.scanFile:
file:///mnt/sdcard/Android/data/com.flippinbits.cameratest/cache/.Pic.j
pg mimeType: image/*
W/IInputConnectionWrapper( 4771): showStatusIcon on inactive
InputConnection
D/CordovaLog( 4861): file:///data/data/com.flippinbits.cameratest/.Pic.jpg?1341147071049
D/CordovaLog( 4861): : Line 1153915013 :
file:///data/data/com.flippinbits.cameratest/.Pic.jpg?1341147071049
I/Web Console( 4861): file:///data/data/com.flippinbits.cameratest/.Pic.jpg?1341147071049
at :1153915013
E/ ( 4762): can't open 'file:///mnt/sdcard/Android/data/
com.flippinbits.cameratest/cache/.Pic.jpg'
E/MediaScannerService( 4762): Exception in handleMessage
E/MediaScannerService( 4762): java.lang.IllegalStateException: Unable
to create new file: file:///mnt/sdcard/Android/data/com.flippi
nbits.cameratest/cache/.Pic.jpg
E/MediaScannerService( 4762): at
com.android.providers.media.MediaProvider.ensureFile(MediaProvider.java:
1852)
E/MediaScannerService( 4762): at
com.android.providers.media.MediaProvider.insertInternal(MediaProvider.java:
1962)
E/MediaScannerService( 4762): at
com.android.providers.media.MediaProvider.insert(MediaProvider.java:
1893)
E/MediaScannerService( 4762): at android.content.ContentProvider
$Transport.insert(ContentProvider.java:198)
[...]

That directory (/mnt/sdcard/Android/data/com.floippinbits.cameratest/
cache) does exist:
d--xrwxr-x 2 system sdcard_r 32768 Jul 1 13:51 cache

But it's a different set of ownership and permissions. I cannot chmod
or chown these files...I get "Operation not permitted".

I'm afraid I've hit a bit of a dead end here.

Help?

-Ken

P.S. When I type logcat in adb shell on the Cyclone Astra tablet, I
get this log:
D/V4L2Camera( 87): V4L2Camera::Close
I/Overlay ( 115): Destroying overlay/fd=257/obj=004abd48
V/SurfaceView(16902): Layout: x=49 y=3 w=632 h=474
I/WindowManager( 115): MediaPlayer.is not PlayingVideo
D/dalvikvm(18527): GC_EXPLICIT freed 344K, 51% free 2951K/5959K,
external 978K/1396K, paused 32ms
D/CordovaWebView(18527): >>> loadUrlNow()
D/CordovaLog(18527): file:///data/data/com.flippinbits.cameratest/.Pic.png?1341147631614
D/CordovaLog(18527): file:///android_asset/www/index.html: Line 34 :
file:///data/data/com.flippinbits.cameratest/.Pic.png?134114763
1614
I/Web Console(18527): file:///data/data/com.flippinbits.cameratest/.Pic.png?1341147631614
at file:///android_asset/www/index.html:34

D/MediaScannerService( 5230): IMediaScannerService.scanFile:
file:///mnt/sdcard/Android/data/com.flippinbits.cameratest/cache/.Pic.p
ng mimeType: image/*
D/SurfaceFlinger( 115): createNormalSurface set format = 2
D/SurfaceFlinger( 115): createNormalSurface set format = 1
V/SurfaceView(16902): Layout: x=49 y=3 w=632 h=474
E/MediaScannerService( 5230): Exception in handleMessage
E/MediaScannerService( 5230): java.lang.IllegalStateException: Unable
to create new file: file:///mnt/sdcard/Android/data/com.flippi
nbits.cameratest/cache/.Pic.png
E/MediaScannerService( 5230): at
com.android.providers.media.MediaProvider.ensureFile(MediaProvider.java:
1728)
E/MediaScannerService( 5230): at
com.android.providers.media.MediaProvider.insertInternal(MediaProvider.java:
1838)
E/MediaScannerService( 5230): at
com.android.providers.media.MediaProvider.insert(MediaProvider.java:
1769)
E/MediaScannerService( 5230): at android.content.ContentProvider
$Transport.insert(ContentProvider.java:198)

Simon MacDonald

unread,
Jul 2, 2012, 12:03:38 PM7/2/12
to phon...@googlegroups.com
Hey Ken,

Can you share what code you used to call the Camera.getPicture()? I did a lot of work with the camera for 1.9.0 and I'd hate to think I missed a scenario. 

Regarding the IMediaScannerService.scanFile error, I've already created an issue in JIRA to track this. 

Simon Mac Donald
http://hi.im/simonmacdonald


-- You received this message because you are subscribed to the Google
Groups "phonegap" group.
To post to this group, send email to phon...@googlegroups.com
To unsubscribe from this group, send email to
phonegap+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/phonegap?hl=en?hl=en

For more info on PhoneGap or to download the code go to www.phonegap.com

To compile in the cloud, check out build.phonegap.com

KenCorey

unread,
Jul 3, 2012, 5:56:36 PM7/3/12
to phon...@googlegroups.com
Uh...sure...let's see here...


It's the canonical example given for testing the camera functionality, with a bit of logging added in.

Can you see anything obvious here, especially with the LogCat results above?

Thanks!

-Ken

Simon MacDonald

unread,
Jul 4, 2012, 2:46:42 PM7/4/12
to phon...@googlegroups.com
For some reason, that doesn't show up in the emulator or the three
devices I have, the web view is unable to load the .Pic.jpg file from
file:///data/data/com.flippinbits.cameratest folder. It is weird that
you have a permission issue since it is your app directory.

To get back to getting a content:// type URI set saveToPhotoAlbum to
true. That should revert to the pre 1.9.0 behaviour.

Also, I've done a bit of a fix for your issue and if you can grab the .jar from:

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

and give it a try to see if it resolves your problem I'd appreciate
it. Then I'll check the fix in.

Simon Mac Donald
http://hi.im/simonmacdonald


Ken Corey

unread,
Jul 5, 2012, 11:43:11 AM7/5/12
to phon...@googlegroups.com
Hey Simon, thanks for jumping on this!  It's very much appreciated.

In my main app I'm still using 1.8.1 because the plugin I'm depending on is still expecting the "ctx.getApplicationContext" call, that apparently has been removed.  I saw a mention of that somewhere.

*smile*

Any pointers on where the docs are regarding updating a plugin to 1.9.0?  I don't mind changing the plugin, if I only knew how.

On the test app, changing the saveToPhotoAlbum property got proper names (content:[...]123456789.jpg  or some such), but it still didn't work with photo or edit photo.  Because I was shuffling the memory card back and forth, the media scanners on the various devices were going crazy, filling up logcat with random and distracting bumpf.

I don't have a detailed report yet, as my Samsung Galaxy 2 10 tab came today.  For the record, neither the stock 1.9.0 nor the 1.9.0 you sent work with the camera there either.  (Camera takes the picture, logcat reports a reasonable enough set of messages, but the image doesn't appear back in javascript.

I can't believe that /all/ these machines are wrong, or that the cordova code is borked, so that leaves my code to be suspicious of first.

Let me dig a bit deeper and try to get examples of everything, and I'll get back to you.

-Ken

Simon MacDonald

unread,
Jul 5, 2012, 1:04:18 PM7/5/12
to phon...@googlegroups.com
On Thu, Jul 5, 2012 at 11:43 AM, Ken Corey <k...@docrobot.co.uk> wrote:
> Hey Simon, thanks for jumping on this! It's very much appreciated.
>
> In my main app I'm still using 1.8.1 because the plugin I'm depending on is
> still expecting the "ctx.getApplicationContext" call, that apparently has
> been removed. I saw a mention of that somewhere.
>
> *smile*
>
> Any pointers on where the docs are regarding updating a plugin to 1.9.0? I
> don't mind changing the plugin, if I only knew how.

I'm cleaning up some of these outstanding camera issues that slipped
through the cracks then I'm going to get working on making sure
plugins work in 1.9.0/2.0.0. If some documentation needs to be written
to upgrade the plugins I will do it.

> On the test app, changing the saveToPhotoAlbum property got proper names
> (content:[...]123456789.jpg or some such), but it still didn't work with
> photo or edit photo. Because I was shuffling the memory card back and
> forth, the media scanners on the various devices were going crazy, filling
> up logcat with random and distracting bumpf.

The allowEdit option is still not supported on Android. There is a
crop intent in older versions of Android but it was removed out of
3.x/4/x so I'm waiting until I have a solution that works on all
versions.

> I don't have a detailed report yet, as my Samsung Galaxy 2 10 tab came
> today. For the record, neither the stock 1.9.0 nor the 1.9.0 you sent work
> with the camera there either. (Camera takes the picture, logcat reports a
> reasonable enough set of messages, but the image doesn't appear back in
> javascript.
>
> I can't believe that /all/ these machines are wrong, or that the cordova
> code is borked, so that leaves my code to be suspicious of first.
>
> Let me dig a bit deeper and try to get examples of everything, and I'll get
> back to you.

Okay, do a bit more testing and get back to me. I'll be checking in
some code today on Camera that fixes another issue a user found.

Ken Corey

unread,
Jul 7, 2012, 7:49:18 AM7/7/12
to phon...@googlegroups.com
Okay, do a bit more testing and get back to me. I'll be checking in
some code today on Camera that fixes another issue a user found.

Well, this is frustrating.  I'm trying to download the actual source code  for PhoneGap.  Not the .jar file and what not, the actual java behind it.

I can see individual files at:

...but how does one go about downloading the whole tree?

I've got the github client on Windows, and was all prepared to fork my own and have a play, but couldn't see how.

Is that not possible right now?

-Ken

Simon MacDonald

unread,
Jul 7, 2012, 9:32:44 AM7/7/12
to phon...@googlegroups.com
I would do a "git clone
https://git-wip-us.apache.org/repos/asf/incubator-cordova-android.git"
but I'm more of a command line gitter.

See the contributor workflow for more details:

https://wiki.apache.org/cordova/ContributerWorkflow

Simon Mac Donald
http://hi.im/simonmacdonald


Ken Corey

unread,
Jul 7, 2012, 10:35:42 AM7/7/12
to phon...@googlegroups.com
I can see individual files at:

...but how does one go about downloading the whole tree?

*sigh* One clicks on the 'snapshot' link at the far right, silly.  

-Ken 

Ken Corey

unread,
Jul 7, 2012, 11:42:03 AM7/7/12
to phon...@googlegroups.com
*smile* Ah, another nutter working on the weekend.  I *like* that about you.

Okay, I've gotten to the bottom of my troubles.

There were four problems befuddling my simple mind:
1) If you're expecting a base64 encoded string, you need to specify it in the options (watch out for wrap here)

    function capturePhoto() {
      // Take picture using device camera and retrieve image as base64-encoded string
      navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 100, targetWidth: 200, targetHeight: 200, encodingType:encodingType.PNG, saveToPhotoAlbum:false,destinationType:destinationType.DATA_URL });
    }

2) If you're expecting a fileURI, explicitly state that in the options (again, 'ware wrap):
    // A button will call this function
    // 
    function capturePhotoEdit() {
      // Take picture using device camera, allow edit, and retrieve image as base64-encoded string   
      navigator.camera.getPicture(onPhotoURISuccess, onFail, { quality: 100, allowEdit: true, targetWidth: 400, targetHeight: 100,encodingType:encodingType.PNG, saveToPhotoAlbum:false,destinationType:destinationType.FILE_URI }); 
    }

3) Finally, *always* explicitly state the size of the image you want back.  If you give -1 and -1 allowing the camera to default to whatever size, and the user chooses a big size (2048x1536 on my Galaxy 2 10), then the app eventually gets too big, crashes silently, and then all bets are off.  Note in both of the camera calls above I'm stating the targetWidth/Height desired.

4) The docs say that you must use both Width/Height together, but that aspect ratio is retained.  

That's not my experience...the picture seemed to be scaled to the specified size, disregarding the aspect ratio altogether.

When I gave a height but not a width is that I got back a picture 1xheight in size.  Artsy, but not desired behaviour.

If you state 0 for either width/height you get crashes or the new image being ignored.

Looking in the code for getScaledBitmap, I confess I'm not clear on how it works:
1) get size of current image
2) calculate widthHeight respecting aspect ratios
3) calculate the sampling rate
4) sample the original bitmap (doesn't this change the aspect ratio before it is scaled?)
5) resize the new sample to the stated size. (but if the aspect ratio is borked already what are we getting?)


So, the docs are misleading. It does work, but you must sacrifice goats, and dance around fires late at night for it to work "properly".

Could have been (partially) prevented with better docs...can you change the API page at:

-Ken

Ken Corey

unread,
Jul 7, 2012, 1:19:33 PM7/7/12
to phon...@googlegroups.com
Ah, and it's a little more wrinkly...

If I've selected the FILE_URI option, the filename I get back is:

for camera pictures: 
      content://media/external/images/media/47112  
      (This is fine, as I can refer to it later and get the same picture.)
for library photos: 
      file:///mnt/sdcard/Android/data/org.path.to.app/cache/resize.jpg?1341680833109

I'm worried that the file path, with every one pointing to 'resize.jpg', is going to be a problem.  That appears to go away between invocations of the app.

Do I need to take the contents of the url handed to me and do something clever (like save them to a file in permanent storage using the File plugin)?

-Ken

Simon MacDonald

unread,
Jul 7, 2012, 10:23:26 PM7/7/12
to phon...@googlegroups.com
I fixed the aspect ratio bug on Thursday.

CB-1008: Camera with targetHeight, targetWidth loses aspect ratio

and I just fixed that 0 width/height issue:

CB-1016: Zero width or height in getPicture throws java.lang.ArithmeticException

I uploaded a new jar to
https://dl.dropbox.com/u/887989/cordova-1.9.0.jar if you want to test.

Simon Mac Donald
http://hi.im/simonmacdonald


Simon MacDonald

unread,
Jul 7, 2012, 10:25:54 PM7/7/12
to phon...@googlegroups.com
Yes, when you get a resized image I don't want to mess with the
original one. So, if you want to save it for later use the File API to
copy it to a more permanent location.

Simon Mac Donald
http://hi.im/simonmacdonald


Ken Corey

unread,
Jul 8, 2012, 4:42:01 AM7/8/12
to phon...@googlegroups.com
Ah, and another wrinkle: you can't save base64 encoded binary files using the File plugin...only UTF-8 encoded text.  

Hrm...this 'resized.jpg' business for downloading perfectly valid existing image paths from the library seems wrong.  I understand the need to resize overly large images, but once resized they need to have permanent names.

For my code I've given up, not specifying the size of the image.  Though I only need a 48x48 icon from the picture, I need to have a permanent name more.  

So far performance isn't impacted too awfully by using full-sized pictures, but I feel horribly wasteful using a 2000x1500 picture and scaling it down to 48x48, even if the machine can do it acceptably quickly.  

The users of my app might make as many as 8000 of these icons.  It'd be crazy extreme, but it'd be possible.

-Ken

Ken Corey

unread,
Jul 8, 2012, 4:47:35 AM7/8/12
to phon...@googlegroups.com
Before I can test that .jar, I have to update the TextToSpeech plugin to 1.9.0 as well.  I'm still stuck on 1.8.1.

It's easy for me to say, but the plugin semantics shouldn't change between versions. It makes it difficult to keep up with the latest versions of Cordova.

-Ken

Ken Corey

unread,
Jul 8, 2012, 4:55:12 PM7/8/12
to phon...@googlegroups.com
Okay, up to date with 1.9.0, and your new library.

When I take a picture (no matter what resolution), and default to whatever resolution (or format) get two errors:

07-08 19:48:56.012: E/System(6245): Uncaught exception thrown by finalizer
07-08 19:48:56.028: E/System(6245): java.lang.IllegalStateException: Binder has been finalized!
07-08 19:48:56.028: E/System(6245): at android.os.BinderProxy.transact(Native Method)
07-08 19:48:56.028: E/System(6245): at android.database.BulkCursorProxy.close(BulkCursorNative.java:288)
07-08 19:48:56.028: E/System(6245): at android.database.BulkCursorToCursorAdaptor.close(BulkCursorToCursorAdaptor.java:133)
07-08 19:48:56.028: E/System(6245): at android.database.CursorWrapper.close(CursorWrapper.java:49)
07-08 19:48:56.028: E/System(6245): at android.content.ContentResolver$CursorWrapperInner.close(ContentResolver.java:1591)
07-08 19:48:56.028: E/System(6245): at android.content.ContentResolver$CursorWrapperInner.finalize(ContentResolver.java:1604)
07-08 19:48:56.028: E/System(6245): at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:182)
07-08 19:48:56.028: E/System(6245): at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:168)
07-08 19:48:56.028: E/System(6245): at java.lang.Thread.run(Thread.java:856)
07-08 19:48:56.028: E/System(6245): Uncaught exception thrown by finalizer
07-08 19:48:56.028: E/System(6245): java.lang.IllegalStateException: Binder has been finalized!
07-08 19:48:56.028: E/System(6245): at android.os.BinderProxy.transact(Native Method)
07-08 19:48:56.028: E/System(6245): at android.database.BulkCursorProxy.close(BulkCursorNative.java:288)
07-08 19:48:56.028: E/System(6245): at android.database.BulkCursorToCursorAdaptor.close(BulkCursorToCursorAdaptor.java:133)
07-08 19:48:56.028: E/System(6245): at android.database.CursorWrapper.close(CursorWrapper.java:49)
07-08 19:48:56.028: E/System(6245): at android.content.ContentResolver$CursorWrapperInner.close(ContentResolver.java:1591)
07-08 19:48:56.028: E/System(6245): at android.content.ContentResolver$CursorWrapperInner.finalize(ContentResolver.java:1604)
07-08 19:48:56.028: E/System(6245): at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:182)
07-08 19:48:56.028: E/System(6245): at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:168)
07-08 19:48:56.028: E/System(6245): at java.lang.Thread.run(Thread.java:856)

It's not a regression, I got them before too.  At least these don't crash the system.

The files come down, but anything with 'resize' in the name disappears.  I'd /greatly/ like to know how to copy files to permanent storage using the File api.  Any chance you could point to an example?

I could always write a plugin to do this, now that I think about it.  I'll probably take that route over the next couple days.

-Ken
Reply all
Reply to author
Forward
0 new messages