Please Help Debug - Camera + display.save() + Android == ?

@All,

Thanks for taking the time to read this.  I’m looking for a little help hunting down a problem.

Problem System and Version Information:

  • Corona SDK 2014.2189 (2013.2100 and 2014.2189 too)
  • Nexus 7 Gen 1 Hardware running Android 4.4.2

What I am doing:

  1. I take a picture with an image,
  2. save it with ‘display.save()’, and then
  3. try to use the saved image via ‘display.newImage()’ or ‘display.newImageRect’

What I expect to see:

I expect to see my original snap-shot image (upper half of screen as positioned by my code) and a second copy of the image with a yellow border on the (lower half of screen as positioned by my code).

What I am seeing:

  • OS X 10.9 - It works and I see what I expect.  :slight_smile:
  • iOS 7.1.1  on iPad Air - It works and I see what I expect.  :slight_smile:
  • Android 4.4.2 on Nexus 7 Gen 1 - It fails and I see the top image, but the bottom image is just a black rectangle with a yellow border.  :frowning:
  • Graphics 1.0 Build 2013.1257 tested on  Android 4.4.2 on Nexus 7 Gen 1 - Works w/ legacy ‘display.save()’. :mellow:

What I Suspect Is Wrong (in this order)

  1. Dumb error in my code or build.settings file. - OR - 
  2. Corona Bug for Android devices. - OR - 
  3. Issue with Android 4.4.2.

What I Need From You

  1. Folks to take a look at the code below and find a stupid error on my part (totally possible).             - AND / OR -
  2. Folks to run the sample on their own Android devices to verify the issue.

You can get the full sample HERE.

Here are my individual files:

main.lua

local doSave = true local sessionComplete = function(event) local image = event.target print( "Camera ", (image and "returned an image") or "session was cancelled" ) print( "event name: " .. event.name ) print( "target: " .. tostring( image ) ) if ( image ) then local group = display.newGroup() group:insert( image ) image.xScale = 0.1 image.yScale = 0.1 group.x = 160 group.y = 120 if( doSave ) then display.save( group, { filename="thePicture.png",                    baseDir = system.DocumentsDirectory,                    isFullResolution = true,                    backgroundColor = { 0, 0, 0, 1 } } ) timer.performWithDelay( 100,  function() local tmp = display.newImageRect( "thePicture.png", system.DocumentsDirectory, 50, 50  ) tmp.x = 160 tmp.y = 360 tmp:setStrokeColor(1,1,0) tmp.strokeWidth = 2 end ) end end end if media.hasSource( media.Camera ) then media.show( media.Camera, sessionComplete ) end

build.settings

settings = { orientation = { default = "portrait", supported = { "portrait" } }, android = { usesPermissions = { "android.permission.CAMERA", "android.permission.WRITE\_EXTERNAL\_STORAGE", }, usesFeatures = { { name = "android.hardware.camera", required = true }, { name = "android.hardware.camera.front", required = false }, }, }, }

Thanks in advance to all takers.

Not answering your original question, but throwing out another idea.

Have you tried the new media.* apis? The selectPhoto one in particular? Not sure if the outcome will be any different, but potentially worth a shot.

Edit: also, is the image fully visible on screen in its entirety, when you call display.save?

I will look into using the media API, but in the interim, this is what I’ve discovered so far:

  1. The code fails for Graphics 2.0 builds:  2013.2100,  2014.2189, and  2014.2289.

  2. The code works (when written in the legacy format) for Graphics 1.0 build 2013.1257

    display.save( group, “thePicture.png”, system.DocumentsDirectory )-- legacy format

Now, onward to trying the media API.

-Ed

Did you see my edit? You must have missed it as you didn’t answer :slight_smile:

Roger that.  The image is fully visible when I try to do the save.  Android is the only hold out right now.  It works find on iOS and OS X simulator.

Right, well that rules out something i was going to say.

Let me know how the other media api’s work for you. Iiirc, they can just save the image to a file, without displaying it first. so they sound like an even better fit for your use case. that is… If i am understanding your use case correctly :wink:

I’ve tried a number of additional things now and all of them fail on Android.  I’m pasting the code next, then adding comments after:

local doSave = 4 -- 0, 1, 2, 3 local sessionComplete = function(event) print("Entering sessionComplete event =? ", event ) for k,v in pairs( event ) do print(k,v) end local image = event.target print( "Camera ", ( image and "returned an image" ) or "session was cancelled" ) print( "event name: " .. event.name ) print( "target: " .. tostring( image ) ) if ( image ) then local group = display.newGroup() group:insert( image ) image.xScale = 0.1 image.yScale = 0.1 group.x = 160 group.y = 120 if( doSave == 1 ) then -- Works on Android 4.4.2 for Graphcis 1.0 but not Graphics 2.0 display.save( group, "thePicture.png", system.DocumentsDirectory ) elseif( doSave == 2 ) then -- Only works for OS X and iOS (does not work for Android) display.save( group, { filename="thePicture.png",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; baseDir = system.DocumentsDirectory,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; isFullResolution = true,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; backgroundColor = { 0, 0, 0, 1 } } ) elseif( doSave == 3 ) then &nbsp;-- Only works for OS X and iOS (does not work for Android) media.save( "thePicture.png", system.DocumentsDirectory ) end if( doSave \> 0 ) then timer.performWithDelay( 100,&nbsp; function() local tmp = display.newImageRect( "thePicture.png", system.DocumentsDirectory, 50, 50 &nbsp;) tmp.x = 160 tmp.y = 360 tmp:setStrokeColor(1,1,0) tmp.strokeWidth = 2 end ) end end end if( doSave \< 4 ) then if media.hasSource( media.Camera ) then media.show( media.Camera, sessionComplete ) end else -- Only works for OS X, FAILs on iOS and Android media.capturePhoto( {listener = sessionComplete, destination = {baseDir=system.DocumentsDirectory, filename="thePicture.png", type="image"} } ) end

This code now adds multiple ways to take a picture, save it to an image, and then display that image.

All of them fail on Android.  Also, the media.capturePhoto() method fails on Android and iOS.  It fails as follows:

  • No image stored in file.
  • No image passed to callback. i.e. Callback executes and event.target == nil.

Bugger.   :wacko:

[quote=“roaminggamer,post:7,topic:325169”]

I’ve tried a number of additional things now and all of them fail on Android. I’m pasting the code next, then adding comments after:

local doSave = 4 -- 0, 1, 2, 3 local sessionComplete = function(event) print("Entering sessionComplete event =? ", event ) for k,v in pairs( event ) do print(k,v) end local image = event.target print( "Camera ", ( image and "returned an image" ) or "session was cancelled" ) print( "event name: " .. event.name ) print( "target: " .. tostring( image ) ) if ( image ) then local group = display.newGroup() group:insert( image ) image.xScale = 0.1 image.yScale = 0.1 group.x = 160 group.y = 120 if( doSave == 1 ) then -- Works on Android 4.4.2 for Graphcis 1.0 but not Graphics 2.0 display.save( group, "thePicture.png", system.DocumentsDirectory ) elseif( doSave == 2 ) then -- Only works for OS X and iOS (does not work for Android) display.save( group, { filename="thePicture.png", baseDir = system.DocumentsDirectory, isFullResolution = true, backgroundColor = { 0, 0, 0, 1 } } ) elseif( doSave == 3 ) then -- Only works for OS X and iOS (does not work for Android) media.save( "thePicture.png", system.DocumentsDirectory ) end if( doSave \> 0 ) then timer.performWithDelay( 100, function() local tmp = display.newImageRect( "thePicture.png", system.DocumentsDirectory, 50, 50 ) tmp.x = 160 tmp.y = 360 tmp:setStrokeColor(1,1,0) tmp.strokeWidth = 2 end ) end end end if( doSave \< 4 ) then if media.hasSource( media.Camera ) then media.show( media.Camera, sessionComplete ) end else -- Only works for OS X, FAILs on iOS and Android media.capturePhoto( {listener = sessionComplete, destination = {baseDir=system.DocumentsDirectory, filename="thePicture.png", type="image"} } ) end

This code now adds multiple ways to take a picture, save it to an image, and then display that image.

All of them fail on Android. Also, the media.capturePhoto() method fails on Android and iOS. It fails as follows:

  • No image stored in file.
  • No image passed to callback. i.e. Callback executes and event.target == nil.
    Bugger. :wacko: [/quote]
    Hmm… I believe that media.capturePhoto doesn’t return event.target as an image, if you pass the destination key, but naturally should be saving the image to a file.

I used that api before with success, on android and ios. In a client app that i was involved in.

Tell you what, i’m not at my computer right now and won’t be until the morning (1.47am here).

But if when i wake up, you have still not got a resolution to this… I will go on my computer and try out the code i had for this before and let you know if it works for me or not (on android/ios)

If it does indeed fail, then i will see if what i had was any different to what you have and report back with my results.

edit: i made edits since posting. Please re-read

Thanks!  I’m going to eat and rest for a bit, then back to coding.  I’ll just test on iOS for now.

Cheers,

Ed

PS - I double checked the listener for capturePhoto() and it should return event.target as the captured image.  It is meant to replace media.show() which is not deprecated.

One more note.  I updated the downloadable code to include all of my above changes.

Cheers,

Ed

Hey Ed.  I don’t have access to my Nexus 7, but this sounds like a bug, either in our code or in Android.  Either way, we need to take a look at it.  Please file a bug report (Make sure to include your build.settings and config.lua) and lets get engineering looking at it.

Rob

Will do.  Thanks Rob.

Not answering your original question, but throwing out another idea.

Have you tried the new media.* apis? The selectPhoto one in particular? Not sure if the outcome will be any different, but potentially worth a shot.

Edit: also, is the image fully visible on screen in its entirety, when you call display.save?

I will look into using the media API, but in the interim, this is what I’ve discovered so far:

  1. The code fails for Graphics 2.0 builds:  2013.2100,  2014.2189, and  2014.2289.

  2. The code works (when written in the legacy format) for Graphics 1.0 build 2013.1257

    display.save( group, “thePicture.png”, system.DocumentsDirectory )-- legacy format

Now, onward to trying the media API.

-Ed

Did you see my edit? You must have missed it as you didn’t answer :slight_smile:

Roger that.  The image is fully visible when I try to do the save.  Android is the only hold out right now.  It works find on iOS and OS X simulator.

Right, well that rules out something i was going to say.

Let me know how the other media api’s work for you. Iiirc, they can just save the image to a file, without displaying it first. so they sound like an even better fit for your use case. that is… If i am understanding your use case correctly :wink:

I’ve tried a number of additional things now and all of them fail on Android.  I’m pasting the code next, then adding comments after:

local doSave = 4 -- 0, 1, 2, 3 local sessionComplete = function(event) print("Entering sessionComplete event =? ", event ) for k,v in pairs( event ) do print(k,v) end local image = event.target print( "Camera ", ( image and "returned an image" ) or "session was cancelled" ) print( "event name: " .. event.name ) print( "target: " .. tostring( image ) ) if ( image ) then local group = display.newGroup() group:insert( image ) image.xScale = 0.1 image.yScale = 0.1 group.x = 160 group.y = 120 if( doSave == 1 ) then -- Works on Android 4.4.2 for Graphcis 1.0 but not Graphics 2.0 display.save( group, "thePicture.png", system.DocumentsDirectory ) elseif( doSave == 2 ) then -- Only works for OS X and iOS (does not work for Android) display.save( group, { filename="thePicture.png",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; baseDir = system.DocumentsDirectory,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; isFullResolution = true,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; backgroundColor = { 0, 0, 0, 1 } } ) elseif( doSave == 3 ) then &nbsp;-- Only works for OS X and iOS (does not work for Android) media.save( "thePicture.png", system.DocumentsDirectory ) end if( doSave \> 0 ) then timer.performWithDelay( 100,&nbsp; function() local tmp = display.newImageRect( "thePicture.png", system.DocumentsDirectory, 50, 50 &nbsp;) tmp.x = 160 tmp.y = 360 tmp:setStrokeColor(1,1,0) tmp.strokeWidth = 2 end ) end end end if( doSave \< 4 ) then if media.hasSource( media.Camera ) then media.show( media.Camera, sessionComplete ) end else -- Only works for OS X, FAILs on iOS and Android media.capturePhoto( {listener = sessionComplete, destination = {baseDir=system.DocumentsDirectory, filename="thePicture.png", type="image"} } ) end

This code now adds multiple ways to take a picture, save it to an image, and then display that image.

All of them fail on Android.  Also, the media.capturePhoto() method fails on Android and iOS.  It fails as follows:

  • No image stored in file.
  • No image passed to callback. i.e. Callback executes and event.target == nil.

Bugger.   :wacko:

[quote=“roaminggamer,post:18,topic:325169”]

I’ve tried a number of additional things now and all of them fail on Android. I’m pasting the code next, then adding comments after:

local doSave = 4 -- 0, 1, 2, 3 local sessionComplete = function(event) print("Entering sessionComplete event =? ", event ) for k,v in pairs( event ) do print(k,v) end local image = event.target print( "Camera ", ( image and "returned an image" ) or "session was cancelled" ) print( "event name: " .. event.name ) print( "target: " .. tostring( image ) ) if ( image ) then local group = display.newGroup() group:insert( image ) image.xScale = 0.1 image.yScale = 0.1 group.x = 160 group.y = 120 if( doSave == 1 ) then -- Works on Android 4.4.2 for Graphcis 1.0 but not Graphics 2.0 display.save( group, "thePicture.png", system.DocumentsDirectory ) elseif( doSave == 2 ) then -- Only works for OS X and iOS (does not work for Android) display.save( group, { filename="thePicture.png", baseDir = system.DocumentsDirectory, isFullResolution = true, backgroundColor = { 0, 0, 0, 1 } } ) elseif( doSave == 3 ) then -- Only works for OS X and iOS (does not work for Android) media.save( "thePicture.png", system.DocumentsDirectory ) end if( doSave \> 0 ) then timer.performWithDelay( 100, function() local tmp = display.newImageRect( "thePicture.png", system.DocumentsDirectory, 50, 50 ) tmp.x = 160 tmp.y = 360 tmp:setStrokeColor(1,1,0) tmp.strokeWidth = 2 end ) end end end if( doSave \< 4 ) then if media.hasSource( media.Camera ) then media.show( media.Camera, sessionComplete ) end else -- Only works for OS X, FAILs on iOS and Android media.capturePhoto( {listener = sessionComplete, destination = {baseDir=system.DocumentsDirectory, filename="thePicture.png", type="image"} } ) end

This code now adds multiple ways to take a picture, save it to an image, and then display that image.

All of them fail on Android. Also, the media.capturePhoto() method fails on Android and iOS. It fails as follows:

  • No image stored in file.
  • No image passed to callback. i.e. Callback executes and event.target == nil.
    Bugger. :wacko: [/quote]
    Hmm… I believe that media.capturePhoto doesn’t return event.target as an image, if you pass the destination key, but naturally should be saving the image to a file.

I used that api before with success, on android and ios. In a client app that i was involved in.

Tell you what, i’m not at my computer right now and won’t be until the morning (1.47am here).

But if when i wake up, you have still not got a resolution to this… I will go on my computer and try out the code i had for this before and let you know if it works for me or not (on android/ios)

If it does indeed fail, then i will see if what i had was any different to what you have and report back with my results.

edit: i made edits since posting. Please re-read

Thanks!  I’m going to eat and rest for a bit, then back to coding.  I’ll just test on iOS for now.

Cheers,

Ed

PS - I double checked the listener for capturePhoto() and it should return event.target as the captured image.  It is meant to replace media.show() which is not deprecated.