0

I'm wanting to have one app (non Unity project) run in the background and write some data to an XML file. This is code I already have. However, for my Unity app I need to know where the file is located so I can read it it.

Does anyone know where iOS automatically saves the XML file it creates?

Sean
  • 897
  • 4
  • 20
  • 42
  • There's no way to do so with simple file reading Unity functions: http://stackoverflow.com/questions/9425706/share-data-between-two-or-more-iphone-applications. This answer http://stackoverflow.com/questions/12561471/how-to-share-files-between-2-local-ios-apps-without-url-scheme-or-external-serve describes good how to share data between two native iOS apps, but i think neither of proposed solutions will work with Unity app. You may consider this using iCloud, Parse, Amazon S3 or some another cloud storage. – Petro Korienev Sep 25 '13 at 09:23
  • Well I know iOS apps can write XML files and I know Unity can read in XML files. So why wouldn't my idea work? Unless the background app can't actively write to the XML whilst its in the background? – Sean Sep 25 '13 at 09:27
  • Didn't you read linked answers? iOS filesystem doesn't allow access to another applications. It is called sandbox. Appllication can read/write files only inside their sandboxes and has no access to another application sandboxes. Basically, filesystem sandbox is a directory protected from another apps. Data sharing between apps is allowed only via system mechanisms e.g. custom URL schemes, custom Document types, keychain groups - not via filesystem mechanisms. It isn't related to XML file - it's about every file. Was i clear? – Petro Korienev Sep 25 '13 at 09:33

1 Answers1

2

The question is kinda old but I will answer it here in case someone might need the guideline.

This is quite possible to do now in iOS8.0+, using new App Group feature. This feature allows 2 or more apps to meet in one shared directory. Here is very brief step to set it up:

  1. Go into your Apple Developer agent account, in the same page where you manage app ID and certificates, create new app group. Let's say group.com.company.myapp
  2. We need 2 apps to share data right? Make sure you have 2 app IDs ready, create new if you don't have. Here you can enable App Group Also create 2 app IDs, let's say com.company.myapp.reader and com.company.myapp.writer. (Can be any, you actually don't have to nest the name like this) You can leave app entitlement for app group unchecked for now, as XCode will do all configuration for us.
  3. Create new project on XCode, one for each project, Single view app is a good project template to try.
  4. Turn on "App group" feature on project setting/capabilities tab. Do not forget to select which app group to use.
  5. Here you must write some objective-C code to fetch that shared folder path. (see NSFileManager containerURLForSecurityApplicationGroupIdentifier) UI's viewDidLoad function is nice place to try your code snippet on.
    • Writer app may concatenate this path with filename and try to write some file to that directory, you can use any file API with this path.
    • Reader app do the same but read from it.
  6. Test until you can make reader app see writer app's file. (I will leave all the work here as an exercise, as I said this will be brief)

Specific to OP's scenario:

  1. Ok, you wanted this functionality in Unity3D. Looks like there is no built-in unity's API or any asset store for this, so you have to write your own iOS native plugin. Read some document if you are not familiar with it. The C# stub on unity side can be something like:

    using UnityEngine;
    using System.Collections;
    using System.Runtime.InteropServices;
    
    public static class AppGroupPlugin
    {
    
        /* Interface to native implementation */
    
        #region Native Link
        #if UNITY_EDITOR
    
        private static string _GetSharedFolderPath( string groupIdentifier )
        {
            // Handle dummy folder in editor mode
            string path = System.IO.Path.Combine( System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop), groupIdentifier );
            if( !System.IO.Directory.Exists( path ) )
                System.IO.Directory.CreateDirectory( path );
    
            return path;
        }
    
        #elif UNITY_IOS
    
        [DllImport ("__Internal")]
        private static extern string _GetSharedFolderPath( string groupIdentifier );
    
        #endif
        #endregion
    
        public static string GetSharedFolderPath( string groupIdentifier )
        {
            return _GetSharedFolderPath( groupIdentifier );
        }
    }
    
  2. Just make objective-C return you that shared path. I have tested that after you obtain this path, you can use this path on any System.IO.File operation to read write file as if they are normal folder. This can be just one single .m file lying in Plugins/iOS folder.

    char* MakeNSStringCopy (NSString* ns)
    {
        if (ns == nil)
            return NULL;
    
        const char* string = [ns UTF8String];
    
        char* res = (char*)malloc(strlen(string) + 1);
        strcpy(res, string);
        return res;
    }
    
    NSString* _GetSharedFolderPathInternal( NSString* groupIdentifier )
    {
        NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:groupIdentifier];
        if( containerURL != nil )
        {
            //NSLog( @"Path to share content is %@", [containerURL path] );
        }
        else
        {
            NSLog( @"Fail to call NSFileManager sharing" );
        }
    
        return [containerURL path];
    }
    
    // Unity script extern function shall call this function, interop NSString back to C-string, 
    // which then scripting engine will convert it to C# string to your script side.
    const char* _GetSharedFolderPath( const char* groupIdentifier )
    {
        NSString* baseurl = _GetSharedFolderPathInternal( CreateNSString( groupIdentifier ) );
        return MakeNSStringCopy( baseurl );
    }
    
  3. After you export XCode project from Unity, do not forget to turn on "App Group" capability again.
Community
  • 1
  • 1
Wappenull
  • 1,181
  • 13
  • 19