- Home /
Android StreamingAssets File Access
I have an iPhone game that I am working on an Android build for with a system where everything is dynamically instanced in a singular generic game scene and I divide the assets in different levels into their own AssetBundles to reduce upfront download size. There is a loading system in place to attempt to load the AssetBundle associated with the current level from the StreamingAssets directory, or my downloaded data, or just download it if it's not found in either of those places.
I usually package these files with the game for test builds and throw them all into the StreamingAssets directory, this works find on the iPhone because I can access them simply at (Application.dataPath + "/Raw/" + fileName). However on my Android device I am having a difficult time locating these files. I've tried a couple different file paths with no success and admittedly I'm something of a novice when it comes to Android development so I am just sort of wandering through this. I can see via debug test in adb that Application.dataPath on the Android is "/data/app/[installed apk name].apk/" and by opening my built apk as an archive I can see the correct bundles reside in the "assets" directory but (Application.dataPath + "/assets/" + fileName) fails to find them correctly. After researching a bit I also tried (Application.dataPath + "!/assets/" + fileName) with the same results.
I'm thinking now that either there is an issue with how I am checking the validity of a file using System.IO.FileInfo:
FileInfo fileInfo = new FileInfo(filePath);
if (fileInfo == null || fileInfo.Exists == false) {
// File not found.
}
I've also noticed that when receiving debug text featureing the Application.dataPath from logcat the installed name of the apk is different than the name of the apk I built with Unity, although I assume this is normal behavior.
Does anyone have any file IO experience on Android and feel like pointing me in the right direction? It would be much appreciated.
Thank you for taking the time to read this long winded post.
P.S. Shame on you Unity staff for not making even a passing mention of the Android functionality of Application.dataPath on http://unity3d.com/support/documentation/ScriptReference/Application-dataPath.html. You've broken my heart.
Answer by mpavlinsky · Jan 30, 2012 at 10:38 PM
So I was never able to figure out if it is possible to use the System.IO.FileInfo class to check the existence of a file that is added to your Android .APK file through the StreamingAssets directory. At this point I really doubt it's possible at all. The reason for this is that the .APK file is an archive, as you may know you can open a .APK file using any archiving utility (WinRAR for example) to inspect it's contents as I touched on above. So the FileInfo class apparently does not support archives like this.
Fortunately the WWW class does support a URI in the style of a JAR URL. So instead I am just pointing my WWW object at the location where the file might be (using the correct JAR URL syntax) and seeing if I come back with an error.
This forums post was extremely insightful in showing how exactly to open a file from the StreamingAssets folder. I'm kind of surprised that this issue isn't better documented, but hopefully in the future this post will save someone a lot of time.
In review:
Don't use System.IO.FileInfo to access files that are archived in your .APK
WWW is your best friend.
The correct URI to access StreamingAssets on Android devices is: "jar:file://" + Application.dataPath + "!/assets/" + fileName
can u tell me how to use WWW class and get the file..from it..??
Is strea$$anonymous$$gAssets folder path "jar:file://" + Application.dataPath + "!/Assets/Strea$$anonymous$$gAssets" + fileName. is this currect?
Guys! If I really need to use Directory. Getfile(*.mp3), what should I do? Cause android won’t let me
Use https://www.assetstore.unity3d.com/#!/content/103788, it is free. Once you have it, you can call BetterStrea$$anonymous$$gAssets.GetFiles("/", "*.mp3"); to get all the mp3 files in Strea$$anonymous$$gAssets.
This helped me a lot to get a file out of the strea$$anonymous$$gAssets folder in the apk, but it resulted in an empty copy of my file. What am I doing wrong?
Answer by shinriyo_twitter · Aug 23, 2013 at 11:00 AM
Try it
string filePath = "jar:file://" + Application.dataPath + "!/assets/" + fileName;
var www = new WWW(filePath);
yield return www;
if (!string.IsNullOrEmpty(www.error))
{
Debug.LogError ("Can't read");
}
SomeMethod (www.text);
please , please upload an example for android that work completely. about 1 week iam working on open a $$anonymous$$icrosoft Access data base on android i create Strea$$anonymous$$gAssets folder in Assests folder i t work fine on my pc and i change the path according you say but it doesnot work .then please make a example for us.
IEnumerator LinkStrea$$anonymous$$gFolder()
{
FinalPath = "file://"+Application.strea$$anonymous$$gAssetsPath + "/" + databasename;
WWW linkstream = new WWW(FinalPath);
yield return linkstream;
read$$anonymous$$DB(linkstream.text);
}
it didn't work for me either .. please do find a way for this /
You are the best man, 4 hours and finally it worked. Thanks a lot.
Answer by gwiazdorrr · Dec 13, 2017 at 07:15 AM
I may be a little late to the party, but it I managed to do it without WWW, @mpavlinsky.
Streaming Assets remain uncompressed in APK/OBB archive, so they can be read directly - if you know their offset and size. And once you do such approach is ~10 times faster (on my device at least), does not suffer memory duplication issue (WWW does) and can be used synchronously (not in a coroutine) and in any thread.
Long story short, I created Better Streaming Assets plugin that does exactly that, comes for free and is open source.
Asset Store: https://www.assetstore.unity3d.com/#!/content/103788
Github: https://github.com/gwiazdorrr/BetterStreamingAssets
Some lovely snippets:
// contents as bytes
byte[] data = BetterStreamingAssets.ReadAllBytes("Foo/bar.data");
// as stream, last 10 bytes
byte[] footer = new byte[10];
using (var stream = BetterStreamingAssets.OpenRead("Foo/bar.data"))
{
footer.Seek(footer.Length, SeekOrigin.End);
footer.Read(footer, 0, footer.Length);
}
// contents as text
string contents = BetterStreamingAssets.ReadAllText("text.txt");
// contents as lines
string[] lines = BetterStreamingAssets.ReadAllLines("text.txt");
// find all Xmls in Streaming Assets
string[] paths1 = BetterStreamingAssets.GetFiles("/", "*.xml",
SearchOption.AllDirectories);
// just Xmls in StreamingAssets/Config directory
string[] paths2 = BetterStreamingAssets.GetFiles("Config", "*.xml");
// check if stuff exists
Debug.Assert(BetterStreamingAssets.FileExists("text.txt"));
Debug.Assert(BetterStreamingAssets.DirectoryExists("Config"));
Hope this helps someone!
I'm trying to use this for Strea$$anonymous$$gAssets and cannot get it to work. I'm getting an error "IOException: Invalid characters" when I try to read from an existing json file.
I tried replacing File.ReadAllText(filePath) with BetterStrea$$anonymous$$gAssets.ReadAllText(filePath). But got the error above. Can you provide documentation on how to read from the Strea$$anonymous$$gAssets folder?
Issue here: https://github.com/gwiazdorrr/BetterStrea$$anonymous$$gAssets/issues/2. Fixed.
$$anonymous$$aybe you should run BetterStrea$$anonymous$$gAssets.Initialize();
before
Answer by shadyshrif · Jul 04, 2017 at 07:53 PM
I solved the problem after I added my files in this directory inside the projec Assets/StreamingAssets/
then I read it inside the code
#if UNITY_ANDROID
string path = "jar:file://" + Application.dataPath + "!/assets/alphabet.txt";
WWW wwwfile = new WWW(path);
while (!wwwfile.isDone) { }
var filepath = string.Format("{0}/{1}", Application.persistentDataPath, "alphabet.t");
File.WriteAllBytes(filepath, wwwfile.bytes);
StreamReader wr = new StreamReader(filepath);
string line;
while ((line = wr.ReadLine()) != null)
{
//your code
}
#endif
string path = "jar:file://" + Application.dataPath + $"!/assets/{_settings.QuestionFolder}/{_settings.FilderName_Big5}/{fileName}"; var filepath = string.Format("{0}/{1}", Application.persistentDataPath, $"{fileName}"); ![alt text][1]
Awesome work for me. Thx, deer. [1]: /storage/temp/170418-unity-mvpap5155j.png
Answer by SirLaur · Dec 15, 2017 at 10:02 AM
@gwiazdorrr Hello and thank you for the code. Can you help me a little ? Lets say I have a StreamingAssets folder with a video "name.mp4" in it, and I build the application with binary split(with obb). How can I get the path to the video inside the obb file. Thanks.
You can post a new question if the above answers do not help you. Do not try to ask anything in the other person's question.
@haruna9x @Paul$$anonymous$$evin I already asked about this yesterday( https://answers.unity.com/questions/1442462/path-to-strea$$anonymous$$gassets-obb-video.html ), but since I didn't get any answer I thought it's okay if I ask in related questions. Sorry about that.