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

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?