Writing to Unity's StreamingAssets folder at runtime, on Android?
The project assests (StreamingAssets ,RawAssets,etc..) are read only, you cant write anything there, instead write write to internal/external storage have a look here, if you prefer writing in c# i believe that you would use Xaramin framework
Read/Load image file from the StreamingAssets folder
While reading files in the StreamingAssets
folder, you have to use WWW
on some platforms or File.ReadAllBytes
some others. You check if the path contains ://
or :///
then determine which one to use. This should solve the question mark issue. Note that you should now be using UnityWebRequest
where WWW
is required unless there is a bug with UnityWebRequest
.
Another issue that will arise is the SpriteRenderer
image not being upadte. The material will reflect the images changes but the SpriteRenderer
will not. The proper way to change a sprite of a SpriteRenderer
is to change the SpriteRenderer.sprite
property. This means that you will have to Convert the Texture2D
to Sprite
then assign that sprite to the SpriteRenderer.sprite
property.
Finally, use Application.streamingAssetsPath
when accessing files in the StreamingAssets
folder. This is not the issue now since you're running it in the Editor but will be in a build.
Below is what your code for reading image file in the StreamingAssets should look like:
using UnityEngine.Networking;
public string url;
IEnumerator Start()
{
///url = Application.dataPath + "/StreamingAssets/shareImage.png";
url = Path.Combine(Application.streamingAssetsPath, "shareImage.png");
byte[] imgData;
Texture2D tex = new Texture2D(2, 2);
//Check if we should use UnityWebRequest or File.ReadAllBytes
if (url.Contains("://") || url.Contains(":///"))
{
UnityWebRequest www = UnityWebRequest.Get(url);
yield return www.SendWebRequest();
imgData = www.downloadHandler.data;
}
else
{
imgData = File.ReadAllBytes(url);
}
Debug.Log(imgData.Length);
//Load raw Data into Texture2D
tex.LoadImage(imgData);
//Convert Texture2D to Sprite
Vector2 pivot = new Vector2(0.5f, 0.5f);
Sprite sprite = Sprite.Create(tex, new Rect(0.0f, 0.0f, tex.width, tex.height), pivot, 100.0f);
//Apply Sprite to SpriteRenderer
SpriteRenderer renderer = GetComponent<SpriteRenderer>();
renderer.sprite = sprite;
}
Read json file from SreamingAssets folder
The fix is to load the contents, the call requires JSON text, not a file path:
ShipTypes shipTypes;
string path = Application.streamingAssetsPath + "/ShipTypes.json";
string contents = File.ReadAllText(path);
shipTypes = JsonUtility.FromJson<ShipTypes>(contents);
How read json from Unity StreamingAssets, Android
Based on this Manual:
On Android, the files are contained within a compressed .jar file (which is essentially the same format as standard zip-compressed files). This means that if you do not use Unity’s WWW class to retrieve the file, you need to use additional software to see inside the .jar archive and obtain the file.
public void ReadJson(){
string path = Application.streamingAssetsPath + "/elements.json";
#if UNITY_EDITOR
path = "/StreamingAssets/elements.json";
#endif
WWW www = new WWW(path);
while(!www.isDone) {}
string json = www.text;
itemsContent = JsonUtility.FromJson<Main> (json);
bundleForPing = itemsContent.bundleID;
}
Unity Android's StreamingAssets folder location
You can not add or modify files that are inside the streaming assets folder after building since on almost all platforms the directory is read only. From the docs:
On many platforms, the streaming assets folder location is read-only; you can not modify or write new files there at runtime. Use Application.persistentDataPath for a folder location that is writable.
That said, on Android the filepath to the streaming assets is at "jar:file://" + Application.dataPath + "!/assets
, from the same docs:
Android uses files inside a compressed APK
/JAR file, "jar:file://" + Application.dataPath + "!/assets".
Do note that you can not access this file location through the standard C# File
functions, but need to access it using a webrequest.
If you need a directory to store data during run time you need to use the Application.persistenDataPath
instead.
From the docs:
This value is a directory path where you can store data that you want to be kept between runs. When you publish on iOS and Android, persistentDataPath points to a public directory on the device. Files in this location are not erased by app updates. The files can still be erased by users directly.
File read/write paradigms on Unity- which to use?
You can get a basic idea in this answer.
In addition, I would suggest placing anything you want to package with your game in your Resources folder, which you can access by using Resources.Load(). You can iterate through these directories however you want- ex: Resources.Load("folder/file");
.
If you want to write files, they have to go in Application.persistentDataPath
as that's the only write-able directory (that's specified by Unity), i.e. for run-time files only. But once a file is stored there, it is persistent between sessions.
You can, of course, specify absolute paths and try to load assets from there, but that's more risk than necessary (paths differ on different devices).
You could ignore Application.dataPath altogether, until you find a specific need for it (ex: to access files that are not in persistentDataPath, but not in resources either).
I hope that helps!
Related Topics
How to Get a JSON String from Url
How to Get the HTML Output of a Usercontrol in .Net (C#)
Handling Decimal Values in Newtonsoft.JSON
What Is the "Volatile" Keyword Used For
Refresh Datagridview When Updating Data Source
How to Sort a Two-Dimensional (Rectangular) Array in C#
Regular Expression for Decimal Number
Passing Dynamic Object to C# Method Changes Return Type
Copy Constructor Versus Clone()
How to Clean HTML Tags Using C#
How to Render Text in .Net in the Same Size as Browsers Does Given CSS for the Text
How to Convert JavaScript Datetime to C# Datetime
How Does Creating a Instance of Class Inside of the Class Itself Works