Saving Files Doesn't Work

I recently upgraded our project from Unity 5.5.0p3 to Unity 2017.1.0f3 today. I noticed one action in our game was causing it to crash on Android. I isolated it down to saving some data to a file after doing that action (essentially visual data for what they have equipped). Once I commented out the saving it was fine and didn’t crash.

To test this a bit more, I created a function to see if saving anything crashes. So I used this function:

private void TestSave()
{
    try
    {
        string filename = Application.persistentDataPath + "/test.txt";
        Debug.Log("Writing to " + filename);

        if (!File.Exists(filename))
        {
            Debug.Log("File doesnt exist, creating it");
            File.Create(filename).Close();
        }

        File.WriteAllText(filename, "test");
    }
    catch(Exception e)
    {
        Debug.LogError("Error writing to file: " + e.ToString());
    }
}

And nothing happened. There was no exception, and I didn’t see the actual file on the device. I hooked up the device to Android Studio and saw which file it was writing to, and “File doesnt exist, creating it” was also logged out. But no actual file was created.

Has anyone ever seen this happen before? Does anyone have any suggestions or ideas on what is going on?

Just an update to this. Turns out the above code is working when saving text. I came across this post on Stack Overflow which was the behaviour I was noticing:

After the above code ran, I was looking in Windows File Explorer to see if the file was created, I didn’t even think to look on the File Manager on the device. I checked File Manager on the device and saw the file was created. So that part of the issue is solved.

However…

There is still the crash issue that I am experiencing with our saving code that we use. I added extra log lines to see where it crashed:

[Serializable]
public class PlayerDisplayData
{
    public string name;
    public string gender;
    public int skinColorId;
    public int hairColorId;
    public int hairStyleId;
    public int favouriteColorId;
    public int classDefId;
    public int level;
    public int weaponDefId;
    public int armorDefId;
    public int helmetDefId;
}

void SaveCharacterDisplayDataToDisk(PlayerDisplayData displayData)
{
    try
    {
        BinaryFormatter bf = new BinaryFormatter();
        Debug.Log("Trying to create file stream");
        string filename = Application.persistentDataPath + "/display.dat";
        FileStream file = File.Create(filename);
        Debug.Log("Trying to serialize display data");
        bf.Serialize(file, displayData);
        Debug.Log("Trying to close file stream");
        file.Close();
        Debug.Log("DONE");
    }
    catch (Exception e)
    {
        Debug.LogError("Error saving display data to the device: " + e.ToString());
    }
}

And here is the crash I am seeing in the logs in Android Studio (I replaced our app identifier with [GAME] in the logs):

08-04 10:46:18.769 11268-11293/[GAME] I/Unity: Trying to create file stream
08-04 10:46:18.781 11268-11293/[GAME] I/Unity: Trying to serialize display data
08-04 10:46:18.856 11268-11293/[GAME] A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x5c in tid 11293 (main)
08-04 10:46:18.965 191-191/? A/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
08-04 10:46:18.965 191-191/? A/DEBUG: Build fingerprint: 'google/razor/flo:6.0.1/MOB30J/2775141:user/release-keys'
08-04 10:46:18.965 191-191/? A/DEBUG: Revision: '0'
08-04 10:46:18.966 191-191/? A/DEBUG: ABI: 'arm'
08-04 10:46:18.966 191-191/? A/DEBUG: pid: 11268, tid: 11293, name: main  >>> [GAME] <<<
08-04 10:46:18.966 191-191/? A/DEBUG: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x5c
08-04 10:46:18.964 191-191/? W/debuggerd: type=1400 audit(0.0:37): avc: denied { search } for name="[GAME]" dev="mmcblk0p30" ino=106519 scontext=u:r:debuggerd:s0 tcontext=u: object_r:app_data_file:s0:c512,c768 tclass=dir permissive=0
08-04 10:46:18.982 600-1297/? D/NetlinkSocketObserver: NeighborEvent{elapsedMs=4001728, 192.168.1.1, [6038E075ED73], RTM_NEWNEIGH, NUD_STALE}
08-04 10:46:19.022 191-191/? A/DEBUG:     r0 000004b0  r1 00000002  r2 00000000  r3 00000000
08-04 10:46:19.022 191-191/? A/DEBUG:     r4 9fa5dc10  r5 81bd6600  r6 862d889c  r7 ffffffff
08-04 10:46:19.022 191-191/? A/DEBUG:     r8 00000000  r9 7f929e38  sl ffffe148  fp b3ab4e14
08-04 10:46:19.022 191-191/? A/DEBUG:     ip 7ff58000  sp b3ab4de0  lr 9f8d26e0  pc 9f8e0cd8  cpsr 20070010
08-04 10:46:19.025 191-191/? A/DEBUG: backtrace:
08-04 10:46:19.025 191-191/? A/DEBUG:     #00 pc 00218cd8  /data/app/[GAME]-1/lib/arm/libmono.so
08-04 10:46:19.025 191-191/? A/DEBUG:     #01 pc 0021bc68  /data/app/[GAME]-1/lib/arm/libmono.so
08-04 10:46:19.025 191-191/? A/DEBUG:     #02 pc 0000d724  <unknown>
08-04 10:46:19.825 191-191/? W/debuggerd: type=1400 audit(0.0:38): avc: denied { read } for name="kgsl-3d0" dev="tmpfs" ino=8353 scontext=u:r:debuggerd:s0 tcontext=u: object_r:gpu_device:s0 tclass=chr_file permissive=0
08-04 10:46:21.022 600-705/? E/NativeCrashListener: Exception dealing with report
                                                    android.system.ErrnoException: read failed: EAGAIN (Try again)
                                                        at libcore.io.Posix.readBytes(Native Method)
                                                        at libcore.io.Posix.read(Posix.java:169)
                                                        at libcore.io.BlockGuardOs.read(BlockGuardOs.java:230)
                                                        at android.system.Os.read(Os.java:367)
                                                        at com.android.server.am.NativeCrashListener.consumeNativeCrashData(NativeCrashListener.java:240)
                                                        at com.android.server.am.NativeCrashListener.run(NativeCrashListener.java:138)

So it seems like the crash is happening in the BinaryFormatter.Serialize() function.

Is anyone experiencing this crash with the BinaryFormatter.Serialize() on devices? Is there another way that these files should be saved?

Same problem. I’m using BinaryFormatter.Serialize to save game data. No problem in Unity 5.6.2f1. After upgraded to Unity 2017.1.0p5 it crash when calling BinaryFormatter.Serialize on Android device.

Disable “Stripping Level” will solve the problem.

Also see the issue tracker: Unity Issue Tracker - [Android] An app crashes when BinaryFormatter is serialized and Stripping Level is enabled

We lost a couple of days until we realised it was a problem with Stripping Level