Please help cocos2d-x to determine what's the correct path to save a file on iOS and Android

Just checked some of the Apps I have on my iPad, all use /Documents as storage path for Purchases and Savegames.
You can use /Library/Caches for temporary data that may get deleted any time (not sure how this is handeled on iOS)

So I think Stuart is right, we may want to introduce a second directory for retrieving a cache directory:

Persistant data like savegames, highscores, replays
Android: Contect.getFilesDir()
iOS: /Documents (Note it is NOT /Library/Documents)

Temporary data like user avatars:
Android: Context.getCacheDir()
iOS: /Library/Caches

Again, for iOS you should query the framework for retrieving the path to the documents and cache directory.

Stuart McGawAndre Rudlaff
Thank you.

#1701 is created for adding getCachePath.

Minggo Zhang wrote:

@Stuart McGaw
Did you mean that /Library/Documents is not suitable for writable path?

Hi Minggo, how to get the in iOS system? thanks!

resolved! :slight_smile:

std::string path = CCFileUtils::sharedFileUtils()->getWriteablePath() + “…/…/Documents/data.csv”;

Having had to rework an iOS project because I was saving files to the wrong location for iCloud backup purposes, I would like to clarify this as i understand it. There are should be 3 different writeablePaths for iOS

  1. /Documents - anything in here should be user generated and thus will be backed up on iCloud if the user is doing so.
  2. /Library/Cache - anything in here should be considered temporary and may be deleted by the OS at any point when the app is not running.
  3. /Library/“Application Support” - anything here will NOT be backed up but is safe from the possibility of being deleted by the OS. This is where persistent downloaded, such as non-consumable IAP, content should go, as it can be re-downloaded if the user restores their device from backup.

See the following for more details:
http://developer.apple.com/library/mac/documentation/FileManagement/Conceptual/FileSystemProgrammingGUide/FileSystemOverview/FileSystemOverview.html#//apple_ref/doc/uid/TP40010672-CH2-SW28

I suggest 3 functions: getDocumentsPath(), getCachePath(), and getSupportPath(). For all other OSs getSupportPath() can return the results from getDocumentsPath(). Alternatively, add a variable to getWriteablePath( bool flag) and on iOS if the flag is true, the return the Documents directory and if false return the “Application Support” directory; on other OSs the flag is ignored.

Hi Mingo,

Just to echo Justin’s experience on this, we have also had app submissions rejected by Apple for storing unnecessary files (e.g. downloadable content files) in /Library/Documents. This directory should only be used for storing persistent data like save game files or user preferences - these can then be backed up automatically via iCloud.

Other files like downloadable content or advertisement assets should go into either /Library/Caches or /Library/Application Support. Note that files in /Library/Caches may be deleted by the operating system if disk space is running low. It would be best to allow developers to choose which of these 3 directories to use.

How about changing getWriteablePath() to take an enum? e.g.

enum ccWriteablePathType
{
kDocuments,
kCaches,
kSupport
};

Cheers!
Chris

I’m currently using CCFileUtils::sharedFileUtils()->getWriteablePath() but as Minggo said before this returns the path to /Caches which is apparently unsafe. Does anyone know how to get the path to /Documents on iOS?

To get the Documents directoy on iOS, I use that method :

CCString* getLocalPath(const char* name)
{
    return CCString::createWithFormat("%s/Documents/%s", getenv("HOME"), name);
}
1 Like

Justin HawkwoodTim Richardson
Thank you for your suggestion.

My opinion is

  1. Does other platform has document path, cache path and support path?
  2. Get writable path just want to return a path that can be written data in.
  3. getWritablePath should keep compatible with previous version, or it will cause application lose data.

is anybody knows how to save and retrieve image file in android…my getwriteablepath return path in format of /data/data/<package/files but i am not able to read it…

@bhavna sahu
Why you said you can not read from /data/data// ?

Hi guys,

not sure if this is still an open topic for Cocos2d-x, we at V-Play ( http://v-play.net ) also had a deeper look into the topic of writable paths. Our game engine defines four location types (explanation is iOS-specific as of iOS 5.1 and above):

CacheLocation:     "/var/mobile/Applications//Library/Caches/" -> NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)
DataLocation:      "/var/mobile/Applications//Library/Application Support/" -> NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES)
DocumentsLocation: "/var/mobile/Applications//Documents/" -> NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)
TempLocation:      "/private/var/mobile/Applications//tmp/" -> NSTemporaryDirectory()

The locations can be selected depending on the desired behaviour in respect to BACKUP (iCloud back up), PURGE (auto purging files if the device runs out of memory) and PUBLIC (users can probably read the files with iTunes):

HomeLocation

  • BACKUP
  • PURGE
  • PUBLIC
    For user generated data, backed-up to iCloud, can be read with iTunes

TempLocation

  • BACKUP
  • PURGE
  • PUBLIC
    All application specific files that need not persist between application launches must be put here and should be deleted at application exit.

DataLocation

  • BACKUP
  • PURGE
  • PUBLIC
    For configuration files, backed-up to iCloud, not purged
    ~~> possible to apply the com.apple.MobileBackup extended attribute to prevent from backing up to iCloud
    CacheLocation
    ~~ BACKUP
  • PURGE
  • PUBLIC
    Can be purged when devices run out of (physical) memory, so must be re-downloaded in some cases

So to summarize I would suggest:

  • For save games, screenshots and other user-generated content ~~> DocumentsLocation
    ~~ For downloadable content which can be fetched from web again -> CacheLocation or DataLocation with “no backup” file attribute

On Android there are the methods getFilesDir(), getCacheDir() (and there external representations getExternalFilesDir(), getExternalStoragePublicDirectory(), getExternalCacheDir()) like already stated above.

Hope this helps a little bit, cross-platform storage paths are sometimes a real mess! :slight_smile:

Best,
Alex

I was also having this problem on Android where my file was not created inside getWritablePath. Using a Root Explorer, I’ve found that this path wasn’t being created!
After taking a look at android documentation into file storage, I’ve found that the correct way to get the path is:
Cocos2dxHelper.java

@70
Cocos2dxHelper.sFileDirectory = pContext.getDir("data", Context.MODE_PRIVATE).getAbsolutePath();

This way the file directory will be created if it doesn’t exists already. I’ve tested and it’s working in my test devices. The created path now looks like this:

08-01 14:24:16.832: D/cocos2d-x debug info(10676): Save File Path: /data/data/com.my.game/app_data/my.file

For iOS:
Documents : for some data that created by USER, it means that these data cannot be recreated by program, such as some config files for user.
Library/Caches: some data that can be recreated by program, such as magazines, books.

So , the getWritablePath should return the Library/Caches.

For Android, I have no idea.

Sorry for bumping this topic but… Is this solved? Is it save to use getWritablePath?
edit
I think I should be more specific. I want to save something permanent for android and ios and win32. What Path should i use?

yes, getWritablePath() is what you want.

Hi,

on my device iPad1 with iOS 5.1.latest getWritablePath() will return /var/mobile/Documents which is not writable. I am not able to open a file for writing with fopen. There is also an article on stackoverflow: http://stackoverflow.com/questions/8376035/how-to-create-folder-in-var-mobile-documents-for-jailbroken-ios-device

Any tipps which path to use on iPad1? I am using cocos2d-x 2.2.2

By the way… It is working on win32 and iOS simulator.

hmm, I’m not sure. Can you upgrade to v3.3? There were a lot of changes here.

Maybe post some code and console output and we can figure something out.

Hi, I checked FileUtilsIOS.mm and code for getWritablePath() is same in v3.3 and 2.2.6.
But I figured out, that the directory /var/mobile/Documents was missing on my device. I created the Documents folder in /var/mobile/ and set folder owner to mobile. After that, the file can be created and everything is fine.

Does anybody know why this folder was missing on my device?

I wonder if it has anything to do with Apple requiring sandboxing? What version of ios is it running? Probably not 8 or 7?

I guess I’m late but Google made me.

For some reason cocos2d-x returns the NSDocuments folder for iOS… (for getWritablePath() )

This is ok in many cases, but a better alternative is NSLibrary path (trust me). Can this be achieved without adjusting cocos2d-x in some way?