IMPORTANT:
With Adobe AIR 3.6 beta, Adobe has introduced an API for cacheDirectory. They also included a property called "preventBackup" to prevent the file from being backed up to iCloud.
Please check out the beta and Release notes. You can also Discuss the feature feedback here.
Many thanks to Pahup for posting the update here.
There are some AIR for iOS applications which got rejected due to following error.
UPDATE: I think above mentioned APIs are used on iOS for varied use-cases ranging from using them as a disk cache to using them for storing App preferences, configuration to saving user's work (Like XMLs, Game state etc.) So before you think that following solution is for you, follow this thumb rule.
"If you are using above mentioned APIs to store any kind of file that
Let me take one more para to explain why. Caches directory is supposed to be used to store files that are actually used as caches and hence those files, if deleted, should not have any impact on the functioning of your application. iOS takes liberty to
There is a quick and clean workaround available for this problem if you were writing to applicationStorageDirectory. Before starting you need to decide the place where the files should go as per the guidelines. I recommend scrolling up again and reading the 3 points in Apple Rejection note, they precisely define the directory you need to use based on the kind of file you are creating.
If you have used Local Shored Objects. The solution is little trickier, because we can not control the location where LSOs are stored. Hence the only way we currently have is to "Not to use LSO" or you may want to create some class like MyLSO which provides the similar functionality using File APIs(which in turn use the following solution)
Following is the code segment that will help you solve the problem. I will, as always, post the code first and then try to explain.
I think this is it. You can use the code snippets at proper places in your applications.and I you should be good to go.
Just for completeness, here you can find the Apple Documentation about Data Handling Categories.
Many thanks to Pahup for posting the update here.
There are some AIR for iOS applications which got rejected due to following error.
Rejection: 2.23 Apps must follow the iOS Data Storage Guidelines or they will be rejectedRecently with the release of iOS 5, Apple updated the Data Storage Guidelines which are mentioned here(Only for the registered developers). The rejection details are similar to the one mentioned at this post. Just to keep you guys reading this article I am quoting the details from the post.
So, to summarize AIR developers may face this problem if they are using Local Shared Objects or AIR File.applicationStorageDirectory API to write/save the data for their application.
We found that your app does not follow the iOS Data Storage Guidelines, which is not in compliance with the App Store Review Guidelines.In particular, we found magazine downloads are not cached appropriately.The iOS Data Store Guidelines specify:"1. Only documents and other data that is user-generated, or that cannot otherwise be recreated by your application, should be stored in the /Documents directory and will be automatically backed up by iCloud.2. Data that can be downloaded again or regenerated should be stored in the /Library/Caches directory. Examples of files you should put in the Caches directory include database cache files and downloadable content, such as that used by magazine, newspaper, and map applications.3. Data that is used only temporarily should be stored in the /tmp directory. Although these files are not backed up to iCloud, remember to delete those files when you are done with them so that they do not continue to consume space on the user’s device."For example, only content that the user creates using your app, e.g., documents, new files, edits, etc., may be stored in the/Documents directory - and backed up by iCloud. Other content that the user may use within the app cannot be stored in this directory; such content, e.g., preference files, database files, plists, etc., must be stored in the /Library/Caches directory.Temporary files used by your app should only be stored in the /tmp directory; please remember to delete the files stored in this location when the user exits the app.It would be appropriate to revise your app so that you store data as specified in the iOS Data Storage Guidelines.
UPDATE: I think above mentioned APIs are used on iOS for varied use-cases ranging from using them as a disk cache to using them for storing App preferences, configuration to saving user's work (Like XMLs, Game state etc.) So before you think that following solution is for you, follow this thumb rule.
"If you are using above mentioned APIs to store any kind of file that
- Can not be re-downloaded or regenerated by your application
- Presence of this stored file is essential for correct functioning your application(For eg. Progress a player has made in your game).
Let me take one more para to explain why. Caches directory is supposed to be used to store files that are actually used as caches and hence those files, if deleted, should not have any impact on the functioning of your application. iOS takes liberty to
- Empty the caches directory in case it finds that device is under low disk space.
- If a user updates to new version of your application. Caches directory is not retained.
There is a quick and clean workaround available for this problem if you were writing to applicationStorageDirectory. Before starting you need to decide the place where the files should go as per the guidelines. I recommend scrolling up again and reading the 3 points in Apple Rejection note, they precisely define the directory you need to use based on the kind of file you are creating.
If you have used Local Shored Objects. The solution is little trickier, because we can not control the location where LSOs are stored. Hence the only way we currently have is to "Not to use LSO" or you may want to create some class like MyLSO which provides the similar functionality using File APIs(which in turn use the following solution)
Following is the code segment that will help you solve the problem. I will, as always, post the code first and then try to explain.
// If the File falls under point 2 of rejection note public var cacheDir:File= null; // If the new File falls under point 3 of rejection note public var tempDir:File=null; //Initialize the Objects with proper paths. var str:String = File.applicationDirectory.nativePath; cacheDir= new File(str +"/\.\./Library/Caches"); tempDir = new File(str +"/\.\./tmp");Here, instead of using the static Directory paths populated by File class' properties, I am creating global File objects that point to the corresponding directories as per the Apple Data Storage guidelines.Now to create/write to any file you can use code that looks similar to following.
var fr:FileStream=new FileStream();
fr.open(cacheDir.resolvePath("myCache.txt"),FileMode.WRITE);
fr.writeUTFBytes("works");
fr.close();
I think this is it. You can use the code snippets at proper places in your applications.and I you should be good to go.
Just for completeness, here you can find the Apple Documentation about Data Handling Categories.
Thanks! This helped me out after two of my apps got rejected for this reason after a small update. Getting them approved now, will let you know if they got accepted.
ReplyDeleteDo you know if the cache directory should be app specific such as /Library/Caches/com.example.myApp
ReplyDeleteAh, never mind. I see in the documentation you linked to that the directory is actually [Application Home]/Library/Caches
ReplyDeleteThanks for the blog post!
There's a fourth point not addressed here:
ReplyDeletehttps://developer.apple.com/library/ios/#qa/qa1719/_index.html
Point 4 is Offline Data, which is supposed to go into the "/Library/Private Documents" directory. This dats will not be backed up by iCloud, but also will not be purged by iOS in a low disk space situation (unlike with the "Caches" and temporary directories, which can be a problem in some situations).
The problem is if you use that "Private Documents" directory you must also mark the file as "do not backup" using native code, so you must use the Native Extension by Jampot:
http://www.jampot.ie/ane/ane-ios-data-storage-set-donotbackup-attribute-for-ios5-native-extension/
I think this should be handled natively by Adobe, instead of having to rely in third party code.
Please fix this in AIR!
I meant <Application_Home>/Library/Private Documents
DeleteHi OMA;
DeleteYou should put this as enhancement request at http://ideas.adobe.com/air , IMO having an actionscript API to set file attributes should be a good idea. API just for do not backup will be very platform specific.
Hi Saumitra. Thanks for your answer! I've submited an enhancement request to both the Ideas site and the Bugbase site:
Deletehttp://ideas.adobe.com/ct/ct_a_view_idea.bix?c=9D564F43-979A-4E35-AA21-85A61B6AB8DE&idea_id=99760394-2A00-4ED6-A61C-1DC016E204F5
https://bugbase.adobe.com/index.cfm?event=bug&id=3104319
For now I'm using Jampot's native extension for the Do Not Backup attribute setting. I hope this can be implemented so this very needed feature for iOS applications (your app might be rejected by Apple otherwise!) doesn't solely rely in a third party native extension.
In the case of storing a flag for an in app purchase that has been purchased, where would you recommend this is saved?
ReplyDeleteNot sure if this is needed. First problem I see is that I can be user "A" while purchasing an item and later when actually playing i can be "B" (A and B being iTunes user account).
DeleteI think the preferred way would be to call restore transactions and let iTunes tell what all goods current user has purchased. You may want to cache that info in Caches folder but you should be dependent on it.
If I use a sharedObject variable to store data between sessions, I haven't specified any specific location, I just declared the variable. Will this sharedObject data remain or will it be overwritten if I supply an updated version of the app, and the user updates to the new version?
ReplyDeleteIt will remain there through updates because LSOs are stored in
Delete/Application Support whose contents are not purged but these
files are considered to be essential for your app to function
properly.
So remember that whenever you are using LSOs you are adhering to the
recommended usage of Application Support directory.
not sure if that answers your question. does it?
It does indeed! Thanks! Just the answer I was hoping for=) Can't tell you how glad I am to hear it, because I was worrying about having to change a lot of the code. =)
DeleteMy app is an educational game and includes a feature where the learners progress is tracked over sessions. I therefore need to store the data for each session somewhere. This data could contain the progress results for many sessions ranging over many months so the data needs to be stored permanently.
ReplyDeleteI currently do this using Shared Objects but from reading this post I think this could result in my app being rejected. Would this kind of data be allowed to be stored in the documents directory? It is user generated in so much that the app stores their scores for each session. If a user installs the app on another device am I right in my assumption that this data could then be available to the new device as the data is downloaded from the cloud?
Is there anywhere a full example of this that can help? cause i'm new to this. A simple example just moving a box and saving its position and load it every time tha application starts. Thank you!
ReplyDeleteI was having problems with this as well, I'll be sure to try this out later. Thanks.
ReplyDeletedocument scanning services
So what if I'm using LSO to save user selection of language? Where should that go?
ReplyDeleteCheers,
Gorka
IMO, You can continue using LSO. If your application has been rejected already, You may try explaining to reviewers that you can not afford losing the language preference and it can not be regenerated by the app(without asking the user again) hence it is essential to be in "Application Support" directory (This is where LSOs are saved on iOS). So that its backed up on iTunes.
DeleteI hope that helps.
Thanks I haven't submitted it yet but I will make sure to add this where needed and if it does get rejected I'll try the approach you defined above.
ReplyDeleteTahnks and I'll let you know...
Cheers,
Gorka
Hello again, I'm having a bit of trouble when compiling for App Store distribution, the Flash IDE seems to be working (and I confirm some temp files are created) but it never ends - and I actually left the pc on for more than half a day working on this.
ReplyDeleteDoes this sound normal?
Thanks,
Gorka
Gorka - do you find it takes a long time to compile your app for testing too? Mine used to take around 10 minutes or more to compile then I discovered that if you turn off show warnings in the publish settings, it reduced the time to less than a minute.
ReplyDeleteFor testing it takes around half an hour, actually to get the projector working it takes around 20 min. I'm guessing it is because I added a folder with 100+ images, is this a good way or should I add those directly in the library?
ReplyDeleteRealized what happened.. a Static Class used for language localization strings grew too big.. reading from xml now..
ReplyDeleteAs soon as I send to App Store will come back and post some feedback.
Cheers,
Gorka
Got it! No rejection! Directly to app store...
ReplyDeleteI did mention in the version notes what you stated about the necessity of the info in the selected folder.. everything worked smoothly..
Cheers and thanks for the moral support!
Gorka
Does this all mean I can do this:
ReplyDeletevar str:String = File.applicationDirectory.nativePath;
docsDir = new File(str +"/\.\./Documents");
And whatever is saved into this folder is then auto-synced to iCloud?
If so, could this work as the only server tech needed for saving game progress?
Yes, Thats correct.. (If I understood your question correctly :) )
DeleteThank-you Sumitra I did what you said but I get this error :
ReplyDelete"SQLError: 'Error #3125: Unable to open the database file.', details:'Connection closed.', operation:'open', detailID:'1001'"
this is my code :
sqlConn = new SQLConnection();
var str:String=File.applicationDirectory.nativePath;
var cacheDir= new File(str +"/\.\./Library/Caches");
var dbFile:File=cacheDir.resolvePath("DB.db");
sqlConn.open(dbFile);
sqlStat = new SQLStatement();
sqlStat.sqlConnection=sqlConn;
if I change it to
sqlConn = new SQLConnection();
var str:String=File.applicationDirectory.nativePath;
var cacheDir= new File(str +"/\.\./Library/Caches");
var dbFile:File=File.applicationStorageDirectory.resolvePath("DB.db");
sqlConn.open(dbFile);
sqlStat = new SQLStatement();
sqlStat.sqlConnection=sqlConn;
it works !
but thats the wrong directory isn't it?
so what should I do ?
thank you
ps. where is you profile picture taken ? looks like an amazing place !
Where are you testing this code? On simulator or actual device? This is expected on Simulators.
DeleteThe photo is taken in Romania Peles castle. :)
Hi mate,
ReplyDeleteThanks for your reply.
Im testing on the actual devices.
-Luke
So, if I am using a SQLite Database and have an option for it in the program to be backed up to a local file, where would I want the local file to be backed up to on iOS 5+?
ReplyDeleteThanks, in advance.
@ Scott - Documents Folder.
ReplyDeleteHey Saumitra, I just uploaded another as3 developed app, do you know of any Adobe showcase website where I can show my work?
I used the same approach as last time, as long as you state in the developer notes that you need the info in the documents folder there shouldn't be any problem..
Cheers,
Gorka
All,
ReplyDeleteWith Adobe AIR 3.6 beta, Adobe has introduced an API for cacheDirectory. They also included a property called "preventBackup" to prevent the file from being backed up to iCloud.
Please check out the beta @ http://labs.adobe.com/technologies/flashruntimes/air/
Release notes @ http://labsdownload.adobe.com/pub/labs/flashruntimes/shared/air3-6_flashplayer11-6_releasenotes.pdf
Discuss the feature feedback @ http://forums.adobe.com/community/labs/flashruntimes/air/
Thanks
-Pahup
Thanks, I updated the article. So the developers are encouraged to use the newer API when available.
DeleteHi,
ReplyDeleteSmall quest. Can i create a sub directory inside the application directory and then store a data.
Hi I have a data file that has everything i need stored, how do i import that into the Library/Caches folder when the app file is created
ReplyDelete