Copy link to clipboard
Copied
Hey all,
Going through iOS 8 compatibility checks with our Adobe AIR app (tested with AIR 13 and AIR 14), I'm noticing changes to file storage.
In short, my code has always been as follows for simply storing a player profile file (matching iOS documentation for as fas as I know: File System Programming Guide: File System Basics). And this has worked well to prevent purges when the device is low on storage space as well as keeping the data there when updating the app.
This code only seems to work for iOS 4 to iOS 7:
var storagePath:File = new File(File.applicationDirectory.nativePath + "/\.\./Documents");
try
{
var targetFile:File = storagePath.resolvePath("profile.bin");
var stream:FileStream = new FileStream();
stream.open(targetFile, FileMode.WRITE);
stream.writeBytes(<byteArray here>, 0, 0);
stream.close();
}
catch (err:Error)
{
<informs user something went wrong, retries, etc. basic error handling>
}
Running this on iOS 8 will always throw a SecurityError (#2038) from stream.open.
Now, we can still save data and fix this by replacing the first line by:
var storagePath:File = new File(File.applicationStorageDirectory.nativePath);
But, this leaves me with a few things, in order of descending importance:
1) Reading something like this makes me scared as our game has a large amount of daily players: "I’m using applicationStorageDirectory to store files. The problem is those files get deleted when the user updates his app…" (AIR App Compliance with Apple Data Storage Guidelines, last comment)
2) What has changed in the iOS 8 file system that suddenly makes my original code fail? Apple developer documentation is still outlining this should be valid. Is this a possible AIR bug?
3) I assume I need to set "don't backup" flags on the files when saving to the appStorageDir?
4) Is anyone else running into this?
Thanks in advance!
Does it make a difference if you replace:
var storagePath:File = new File(File.applicationDirectory.nativePath + "/\.\./Documents");
with:
var storagePath:File = File.documentsDirectory;
??
You should really be using File.documentsDirectory and not that assumption about walking up from a relative path from File.applicationDirectory anyway.
Copy link to clipboard
Copied
Does it make a difference if you replace:
var storagePath:File = new File(File.applicationDirectory.nativePath + "/\.\./Documents");
with:
var storagePath:File = File.documentsDirectory;
??
You should really be using File.documentsDirectory and not that assumption about walking up from a relative path from File.applicationDirectory anyway.
Copy link to clipboard
Copied
Thanks for your quick reply!
I agree about not traversing up the directory tree, but a blog post from an Adobe employee I read a long time ago put me on that track: Saumitra Bhave: AIR iOS- Solving [Apps must follow the iOS Data Storage Guidelines]
Anyway, I ran some tests including your suggested solution and it returns an interesting result:
#1 File.documentsDirectory (iOS 8)
Full path = /var/mobile/Containers/Data/Application/<UUID>/Documents
Result: works as expected, no errors thrown!
#2 new File(File.applicationDirectory.nativePath + "/\.\./Documents") (iOS 8)
Full path = /private/var/mobile/Containers/Bundle/Application/<UUID>/Documents
Result: error, no write permission! (as I would expect with 'private' being there)
#3 File.documentsDirectory (iOS 7)
Full path = /var/mobile/Applications/<UUID>/Documents
Result: works as expected!
#4 new File(File.applicationDirectory.nativePath + "/\.\./Documents") (iOS 7)
Full path = /var/mobile/Applications/<UUID>/Documents
Result: works as expected! (notice it's exactly the same as #3)
So, while the storage directory is easily adjustable and #1 should fit the bill nicely, I'm thinking of how to preserve user data when people begin updating from iOS 7 to iOS 8 as it will be kind of hard for me to locate my earlier data on iOS8 unless part of the update process is to also relocate all application data? I mean, even if I had used File.documentsDirectory before, this would still be a potential problem? In any case, it's obvious the iOS8 file system is different.
How is this going to work?
Copy link to clipboard
Copied
Well I think this clearly shows that #1 is the way to go, yes it looks like Apple is moving the location of the apps in iOS 8 on the filesystem, but obviously the update on a device to the new OS version would have to move all apps, otherwise every single app would break.
It is clear that the reason you should always use helper aliases like File.documentsDirectory is that Adobe is properly relying on the native OS to resolve the documents folder no matter what OS version you are running on.
Copy link to clipboard
Copied
You're right. I'll go with your solution and make sure my app update is released before iOS 8 sees the light of day publicly. Should fix this issue. Thanks for your help, the quick replies are much appreciated!
Copy link to clipboard
Copied
A bit late to the party here - but with a related question.
I have an app that makes use of the same ..document path as above. After the upgrade to ios8 is there any way to access the files saved in this manner? (in order to manually relocate them to File.applicationStorageDirectory?
Copy link to clipboard
Copied
If you've been using the document path as I did before, you can simply access the data on any iOS version by using the File.documentsDirectory method. As outlined in a previous post of mine, you'll notice that it gives consistent results.
After which, you can store the data in the File.applicationStorageDirectory if you wish.
Copy link to clipboard
Copied
Hi Eljo - thanks for getting back to me on this...
I am having a really hard time confirming that what you wrote is actually working for me...
Let me just run my setup by you.
In my old version the first thing i do is to save the username in a config.xml
private var docDir:File = new File(File.applicationDirectory.nativePath + "/\.\./Documents");
var configFile:File = docDir.resolvePath("config.xml");
var configXML:XML = new XML("<?xml version='1.0' encoding='utf-8' ?><readapp />");
var fileStream:FileStream = new FileStream();
fileStream.open(configFile, FileMode.WRITE);
fileStream.writeUTFBytes(configXML);
fileStream.close();
Now in my updated version the first thing i do is to trace the different paths and to check if that config file exists
i try both
var docDir:File = new File(File.applicationDirectory.nativePath + "/\.\./Documents");
configFile = docDir.resolvePath("config.xml");
trace("Original config exists: " + configFile.exists.toString());
trace(configFile.nativePath)
trace(configFile.url)
docDir = File.documentsDirectory;
configFile = docDir.resolvePath("config.xml");
trace("documants dir config exists: " + configFile.exists.toString());
trace(configFile.nativePath)
trace(configFile.url)
On my ios7 ipad these two files are at the same position. However when i try this on my ios8 ipad the two files have different paths.
Are you telling me that during the upgrade to iOS8 apple moves the config.xml from: var/mobile/applications/[id]/Documents/config.xml to the new location: var/mobile/Containers/Data/Application/[id]/Documents/config.xml
?
Copy link to clipboard
Copied
Hey fideId, I didn't think it would work like that either at first. But like Jeffrey said: an upgrade to iOS8 will migrate all files to new locations as the folder structure has changed.
As long as you did not create any custom directories (which you didn't, as outlined by your code, you were targeting the official Documents directory), you're good to go by simply using the File.documentsDirectory method.
I can guarantee this works. And you don't necessarily have to move the files to the applicationStorageDirectory, by the way, but maybe you have other reasons for that (automatic iCloud backup, for example).
Only thing that sticks out a little is the path you're tracing. Although the same logic applies, my path included a 'private' folder which prevented writing to that location, but maybe you just left that part out.
Anyway, if you app is live already, the only downside for you right now is that users on iOS8 will probably experience errors as your old code is not compatible with it and the config.xml file cannot be created at that location.
Let me know if you need any more help.
Copy link to clipboard
Copied
Hi Eljo and again thanks again for your help. I don't know how i could leave out private/ as i double checked these urls... Its there as in your tests. I have one little question regarding just using the File.documentsDirectory as you mentioned. Do you know if files in that location are overwritten/removed when updating the app? I have had a hard time finding info on this and have read conflicting advice.
Best regards
Fidel
Copy link to clipboard
Copied
Hey, sorry for not getting back to you in a while. In my experience, the documents directory is perfectly fine and is never purged by the OS. For more information, see File System Programming Guide: File System Basics as it includes everything you need to know about this.
Copy link to clipboard
Copied
Hi Eljo,
No worries - i updated and submitted my app with the new directory.
Thank you very much for your help.
Copy link to clipboard
Copied
Hi Guys,
I have an AIR game that's is loading the data from some json files, like current_score.json.
When i'm compiling using AIR 15.0.0 on IOS8 device i can find my file only using File.applicationDirectory and is siting at private/var/mobile/Containers/....
Because is siting on private in IOS8 I can't override or update it file as I don't have permission in IOS8.
My questions are:
1. File.documentsDirector, File.applicationStorageDirectory or File.userDirectory is not finding my current_score.json file, it should find it?
2. When I install the app the assets files like(.json) files will be copied in
/var/mobile/Containers/Data/Application/713F4EEA-8502-40F6-AA49-B2812E5206F2/Documents
?
3.If not, how can I use this file? do I need to make a copy of it all the time when I start the app? or how this is going to work?
Thanks,
Lucas