- Home /
Loading Asset in Android using StreamingAssets and UnityWebRequest
I can't believe how lack of documentation and support there is to load a simple file in Android platform... I know i have to put the file in StreamingAssets named folder, and then make a request using the UnityWebRequest class. This file is a binary file, which i saved using BinaryFormatter. How do i make this request? and then deserialize the response?
Answer by RobinReiner · Feb 03, 2020 at 07:02 AM
Hi, the thing with the StreamingAssets folder is indeed a bit tricky. To retrieve a single file the web request procedure is enough.
var loadingRequest = UnityWebRequest.Get(Path.Combine(Application.streamingAssetsPath, "your.bytes"));
loadingRequest.SendWebRequest();
while (!loadingRequest.isDone) {
if (loadingRequest.isNetworkError || loadingRequest.isHttpError) {
break;
}
}
if (loadingRequest.isNetworkError || loadingRequest.isHttpError) {
} else {
File.WriteAllBytes(Path.Combine(Application.persistentDataPath , "your.bytes"), loadingRequest.downloadHandler.data);
}
It is easier with this little plugin: https://github.com/gwiazdorrr/BetterStreamingAssets
When accessing multiple files and subfolders we had some problems ourselves. An interim solution is to pack elements of the StreamingAssets folder as file archive and unpack them on the device.
So after doing the File.WriteAllBytes, i can now access this file and deserialize the file in the normal way using BinaryFormatter? Like this:
public static int[,] loadTerrainDataPersistent(String terrainName) {
if (File.Exists(Application.persistentDataPath + "/" + terrainName + ".detail"))
{
BinaryFormatter bf = new BinaryFormatter();
FileStream stream = new FileStream(Application.persistentDataPath+ "/" + terrainName + ".detail", File$$anonymous$$ode.Open);
TerrainStorageData tsd = bf.Deserialize(stream) as TerrainStorageData;
stream.Close();
return tsd.map;
}
return new int[0, 0];
}
Or should i Deserialize the data that is present on the downloadHandler right away? (like this: https://answers.unity.com/questions/895934/serialize-and-deserialize-class-to-byte-on-ios.html
oh and about accessing multiple files and subfolder... i have two files in Strea$$anonymous$$gAssets, i'm only accessing one file per scene (level) the first level works fine but the second does not load it.. So i believe it is because i can't access multiple files as you said? how can i file archive the Strea$$anonymous$$gAssets and unpack them on the device? $$anonymous$$an...i can't believe how hard it is to do something so simple as reading a file... when i tought i was almost done, now i can't access multiple files on Strea$$anonymous$$gAssets, only one, great...
Of course you can load as many files from the Strea$$anonymous$$gAssets folder as you like. However for each file you have to use the UnityWebRequest.
Any no, that is not some stupid limitation of Unity. An android build is packed into an AP$$anonymous$$ file which is actually a zip archive. So your strea$$anonymous$$g asset files are not files in the file system but are packed inside the AP$$anonymous$$ file. You are free to use some kind of third party ZIP archive framework to directly read them out of the app file. However Unity already provides you with a way, the UnityWebRequest.
To answer your first comment: Yes the persistent data path is a path on the actual file system of the android device. So you can read and write files there as you want. If you have read only assets you could simply use a TextAsset inside Unity and use the file extension ".bytes" for your file. That way you don't need your data to be inside Strea$$anonymous$$gAssets. It would be an asset like anything else, build and packed into the Unity asset database as binary data. To get your hands on the data, just use the bytes property.
If you insist in having an actual file on the device (maybe because you want to modify it) you can use the Strea$$anonymous$$gAssets way and just copy the data from the strea$$anonymous$$g asset to a place in the persistent data path if the file doesn't exist yet. So a common solution when you want to have a file that you're going to read and write is to try to load it from the persistent data path. If that fails you copy the file from the strea$$anonymous$$g assets like RobinReiner showed and then load it again from the persistent path.
Note when you only need read access and you're using a simple TextAsset in Unity, you would just use a $$anonymous$$emoryStream ins$$anonymous$$d of a FileStream. That's all. Also please look up how to use a using block. Any sort of file IO should be secured through a using block.
Thanks alot @Bunny83 , i think that TextAsset is exactly what i need since my files are read only, i did try to access the files like a normal asset using BinaryFormatter and FileStream, but when playing in Android it just fails to load the file. So you're saying that by using TextAsset and ".bytes" extension it will sucessfully load on Android?
Hi,
I had the same issue for Android, I tried your approach but some how I am getting NetworkError. the loadingRequest.isNetworkError is set to true, any idea why that might be happening?
Thanks, Sohaib