display.captureScreen not saving to Desktop in production build

I have a game that’s pending developer release so I’m testing a live, production build via promo code.  When I built locally, it saved the captured image to Desktop just fine.  But testing the live build isn’t not saving.

On this page:

https://docs.coronalabs.com/api/library/display/captureScreen.html

It says this under “Mac”:

“Saves screen capture images as JPEG files to the current user’s desktop.”

Do I need to have any entitlements set up specifically in build.settings?

Thanks,

Nate

Would I need to add the following?  There’s no real way to test this without submitting as far as I know…  Could really use some help as I’m releasing this app this week!

osx = { entitlements = { ["com.apple.security.temporary-exception.files.home-relative-path.read-write"] = "~/Desktop/" } }

I’m referencing this Apple developer reference link.

Unfortunately that doc entry should include a caveat about sandboxing for Mac App Store apps.  I’ll make sure it gets added.

It’s Apple’s intention that apps only write to their own sandbox and it’s not clear that your app will get approved if it uses Temporary Exception Entitlements (I may be wrong about this).  I’m not sure how others have worked around this.

Thanks Perry.  Interestingly enough, it was approved…  the app doesn’t break at all when trying to save the image, it’s just not there on the Desktop.

So overall in a production Mac app, should display.captureScreen save to the Desktop?  Also, should the following work to enable a production app to have access outside of its sandbox to the Desktop?

osx = { entitlements = { ["com.apple.security.temporary-exception.files.home-relative-path.read-write"] = "~/Desktop/" } }

When I submit the update, I believe inside iTunes there’s an area where I can enable the above entitlement for the specific build…

I just want to make sure that the way that I have the code above will work…  in other words if it’s correct.  Like for “~/Desktop/” does it need the trailing slash or is that formatted correctly?  This is a big feature in the game - without any real way to test this outside of a production build as far as I know, I’d like to ensure that it works ;) 

I had one of our engineers try to explain it to me earlier. The gist of it is there is a difference between macOS apps that you build and distribute yourself and macOS apps that are destined for the Mac App Store. The former don’t have sandbox restrictions that are put on Mac App Store app.  

There are some entitlements that grant access to Downloads and Pictures. (and a couple of other standard locations in either read-only or read-write.), but I’m not 100% sure what you can do to write there. It looks like you have also enable the entitlements in iTunes Connect. You can use the guide on how to code the entitlement, but to make Pictures read/writable by you would be:  com.apple.security.assets.pictures.read-write

I’ve never done this, I don’t know what kind of prompts you’re going to get. 

Thanks Rob.

The issue is that display.captureScreen is set to save to the Desktop.  As far as I know, I can’t change this.

So ultimately I need access to enable saving to the desktop…

Docs say this now…

Mac:

Saves screen capture images as JPEG files to the current user’s desktop (or the appropriate sandbox directory for Mac App Store apps).

If this will save elsewhere, how can I specify that?  I’m just confused how this will work…

Ok, I’m at a loss here.  I _ really _ need to get this to work ASAP.

I can set the following in my build.settings…  But it still saves to the Desktop.  If only display.capture(true) saved to Pictures on Mac as it does in iOS that would be wonderful.

osx = { entitlements = { ["com.apple.security.assets.pictures.read-write"] = true } }

From all I’m reading online, it’s a temporary security exception to save to the Desktop.   Normally it’s not allowed and during the submission process, requires an exception and a request to have it allowed for the app along with a reason why via iTunes Connect.  osx-entitlement.png

Could it be possible to have display.captureScreen write to the Pictures folder by default??

Can you post the code you’re using to write the files now?

Rob

The temporary exceptions have “.temporary.” in their name. I believe com.apple.security.assets.pictures.read-write would pass as a valid item. Since I can’t see your code yet, instead of trying ~/Desktop/ in your path name, what happens if you change it to ~/Pictures/ ?

Rob

Hi Rob,

Yes I do believe that would work - enabling “com.apple.security.assets.pictures.read-write” via iTunes Connect and also having the following set up in build.settings:

osx = { entitlements = { ["com.apple.security.assets.pictures.read-write"] = true } }

The problem is that here’s my code - it’s as simple as this…

display.captureScreen(true)

Which according to the docs for iOS works as it should, saving to the user’s Pictures on their iPhone/iPad - and prompting them beforehand to allow access to Photos.  However, for macOS running via Corona sim or running a build locally, it saves to the Desktop.  As stated above, this is what is specified in the Corona docs on how display.captureScreen(true) works for macOS.

This is the problem - I have no way to tell display.captureScreen(true) to save to the Pictures folder on macOS.

Why is it trying to save to the Desktop on macOS?  Shouldn’t it natively be attempting to save to the user’s pictures folder?

Have you tried to use display.save()? You can control the path to the file (somewhat) there.  You may be able to do system.DocumentsDirectory as the base path and then add “Pictures/filename.jpg” as the file name and see if that works.

Rob

Thanks Rob.  Unfortunately, display.save() doesn’t appear to work at all with macOS.   display.capture() only saves to the Desktop.

Also, isn’t system.DocumentsDirectory a buried folder that’s generally nearly impossible to find?

Speaking frankly here, is this just a guessing game?  Do any of the engineers there have any insight as to why display.capture() and display.captureScreen() are saving to the Desktop on macOS, when really that’s not really even allowed by Apple?

I’m running out of time here and could really use some help…  All I need is for display.captureScreen(true) to save by default to the Pictures folder.  OR, if display.capture( displayObject, {saveToPhotoLibrary=true}) would do the same.  The following IS allowed by Apple as a valid entitlement.

osx = { entitlements = { ["com.apple.security.assets.pictures.read-write"] = true } }

Thank you!!

Your sandbox exists in ~/Library/Containers/com.borderleap.harmony3.osx/Data 

Inside that folder are a couple of directories, one named Documents and several symlinks to folders like Desktop, Pictures, etc. The version of your game that I have, doesn’t have the entitlements, but I can’t find my attempts to save your files. In fact I get these errors in the Console app:

ImageIO: IIOImageWriteSession:111: cannot create: ‘/Users/rmiracle/Library/Containers/com.borderleap.harmony3.osx/Data/Desktop/Picture 1.jpg.sb-56f26591-OaTklM’

         error = 1 (Operation not permitted)

SandboxViolation: har•mo•ny 3(5068) deny(1) file-write-create /Users/rmiracle/Desktop/Picture 1.jpg.sb-56f26591-OaTklM

So that looks to me like it is trying to save the image to Desktop, which of course works when not sandboxed. Desktop is not one of the permissible folders when sandboxed. 

I’ll continue the conversation with Engineering, but given the short time I’m not sure what the options might be.

Rob

Thank you Rob - this is very helpful.  How would I access this sandbox folder via Corona? 

~/Library/Containers/com.borderleap.harmony3.osx/

Ok… making progress.  I uninstalled the production version I got via the promo code and double-clicked on the .pkg file… followed through the installation instructions and now I have a fully-sandboxed app.  I might have missed this but I hadn’t seen these instructions anywhere in the docs, but doing this is the only way I know of to test how a macOS app will function in a fully-sandboxed, production mode, WITHOUT having to submit to the App Store.

Secondly, using the sandboxed version I was able to replicate via Console the same errors you got.  Now, I can test entitlements and am working on getting the following to work…  I’ll report back with findings.

osx = { entitlements = { ["com.apple.security.temporary-exception.files.home-relative-path.read-write"] = "/Desktop/" } }

So… unless there’s issues during the approval process, this issue is SOLVED.

I was able to successfully test a fully-sandboxed version with the following added, then commented out.  When added, the file was saved to the desktop.  When commented out, it produced the error in Console that you showed above, Rob.

osx = { entitlements = { ["com.apple.security.temporary-exception.files.home-relative-path.read-write"] = "/Desktop/" } }

Thanks for your help - proved to be exactly what I needed!

Glad you’ve got it working.

You are correct in saying that display.captureScreen() should save to the user’s Pictures folder on macOS.  It’s a bug that it doesn’t and I’ve opened a case for it.

Spoke too soon.  My game, har•mo•ny 3 is featured in the Mac App Store but I had to take out wallpaper saving altogether.  App Review rejected usage of the following, even though it works.

osx = { entitlements = { ["com.apple.security.temporary-exception.files.home-relative-path.read-write"] = "/Desktop/" } }

The only way I believe it will work is to use a non-temporary entitlement, thus this one:

osx = { entitlements = { ["com.apple.security.assets.pictures.read-write"] = true } }

But, that’s out of my hands…  Engineers there will need to make that work.  

Thanks for filing the bug…  would you happen to know when it might be fixed?  I could REALLY use it as soon as it’s ready.  I’m happy to test it out when it is!

This was fixed in CoronaSDK 2017.3025 and captures are now saved in the user’s Pictures folder.