So in my project I have an image object that loads various different sprites throughout the game. In order to implement this, I have a folder with a bunch of .pngs that the game accesses. In order for this to work in a standalone build I put these images in the following path:
StreamingAssets/Question Images
However, in Android I am getting an error because, as the manual says:
"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.
The thing is I have no idea how to go about implementing this, any ideas?
From Application.streamingAssetsPath
It is not possible to access the StreamingAssets folder on WebGL and Android platforms. No file access is available on WebGL. Android uses a compressed .apk file. These platforms return a URL. Use the UnityWebRequest class to access the Assets.
Example using UnityWebRequestTexture
private void Start()
{
StartCoroutine(GetTexture());
}
private IEnumerator GetTexture()
{
// in general I would always avoid to have spaces in file-paths
var path = Path.Combine(Application.streamingAssetsPath, "QuestionImages", "exampleImage.png");
using(var www = UnityWebRequestTexture.GetTexture(path))
{
yield return www.SendWebRequest();
if(www.isNetworkError || www.isHttpError)
{
Debug.LogErrorFormat(this, "Unable to load texture due to {0} - {1}", www.responseCode, www.error);
}
else
{
Texture myTexture = ((DownloadHandlerTexture)www.downloadHandler).texture;
}
}
}
Note: Typed on smartphone so no warrenty but I hope the idea gets clear.
Related
I want to plot multiple assets with buildGriedView. I already have some assets to plot. But I want to add to this asset list some images I'm getting from using imagePicker. I'd like to ask if it is possible to make these images (from imagePicker) assets so I can also add them to the list and plot with buildGridView.
Here's what is said on assets in the Flutter documentation:
Flutter apps can include both code and assets (sometimes called
resources). An asset is a file that is bundled and deployed with your
app, and is accessible at runtime. [...]
So no, you won't be able to add any assets once your application is compiled. If you want to use images from an image picker you will need to use workaround such as reading the file's bytes (you could use the widget Image.memory). The package image_picker (which I suppose is the one you are using) provide a method readAsBytes() for the retrieved file.
final myImage = await pickImage(source: ImageSource.gallery);
if (myImage != null) {
final myImageBytes = await myImage.readAsBytes();
return Image.memory(myImageBytes);
}
Documentation
Image.memory
image_picker readAsBytes
I want to copy a single json file from Unity's Assets/Resources/ directory to the internal persistent memory of Android device (INTERNAL STORAGE/Android/data/<packagename>/files/) only once at the start of the game. I looked up all over the internet, with solutions saying to use Streaming assets and UnityWebRequests or WWW class which is obsolete now. I tried everything for hours now. And did not find a exact solutions, but only got null references and directory not found.
I added my json file to the <UnityProject>/Assets/Resources/StreamingAssets/, but it doesn't seem to detect any streaming assets. I understand an apk is a zip file and so I can only read the contents of streaming assets, but my I can't find a solution to this.
Once I get my json from streaming asset, I can finally add it to Application.persistentDataPath.
UPDATE
I had actually figured it out,
public void LoadFromResources() {
{mobilePath = "StreamingAssets/"; mobilePath = mobilePath + "stickerJson" + ".json";
string newPath = mobilePath.Replace(".json", "");
TextAsset ta = Resources.Load<TextAsset>(newPath);
string json = ta.text; Debug.Log(json); System.IO.File.WriteAllText(Application.persistentDataPath + "/stickers.json", json);
}
}
To copy a file you only need to have the information of the file and then create a new one in another place.
So if you got your json file into your Resources directory you can retreive like the documentation say:
//Load text from a JSON file (Assets/Resources/Text/jsonFile01.json)
var jsonTextFile = Resources.Load<TextAsset>("Text/jsonFile01");
//Then use JsonUtility.FromJson<T>() to deserialize jsonTextFile into an object
Then you only have to create your android file in your persistentDataPath as #Iggy says in the comments doing:
System.IO.File.WriteAllText(Path.Combine(Application.persistentDataPath, "file.txt"), jsonTextFile);
Note: Not really sure, but for other cases I think that StreamingAssets folder should be inside Assets, no inside Resources.
I have some level definitions in xml format (with .txt extension) inside (without any subfolders) my project's rescources folder
I for more scalability, I have a plain text file naming all these level definition XMLs
I read that file using
TextAsset WorldList = (TextAsset)Resources.Load("WorldList");
And then I load the needed world:
TextAsset TA = (TextAsset)Resources.Load(/*"LevelDefs/" +*/ Worlds[worldToload]);
xps.parseXml(TA.text);
loadLevel(levelToLoad);
(you see that I have moved these rescources out of subfolder to reduce the chance of them not loading)
worldToload here is the index number of that world
program works fine on windows but nothing loads on my android test device.
I seem to have problems debugging on device so I only guess something went wrong in loading phase.
any suggestions?
From Unity Documentation:
Most assets in Unity are combined into the project when it is built.
However, it is sometimes useful to place files into the normal
filesystem on the target machine to make them accessible via a
pathname. An example of this is the deployment of a movie file on iOS
devices; the original movie file must be available from a location in
the filesystem to be played by the PlayMovie function.
Any files placed in a folder called StreamingAssets in a Unity project
will be copied verbatim to a particular folder on the target machine.
You can retrieve the folder using the Application.streamingAssetsPath
property. It’s always best to use Application.streamingAssetsPath to
get the location of the StreamingAssets folder, it will always point
to the correct location on the platform where the application is
running.
So below snippet should work:
// Put your file to "YOUR_UNITY_PROJ/Assets/StreamingAssets"
// example: "YOUR_UNITY_PROJ/Assets/StreamingAssets/Your.xml"
if (Application.platform == RuntimePlatform.Android)
{
// Android
string oriPath = System.IO.Path.Combine(Application.streamingAssetsPath, "Your.xml");
// Android only use WWW to read file
WWW reader = new WWW(oriPath);
while ( ! reader.isDone) {}
realPath = Application.persistentDataPath + "/Your"; // no extension ".xml"
var contents = System.IO.File.ReadAll(realPath);
}
else // e.g. iOS
{
dbPath = System.IO.Path.Combine(Application.streamingAssetsPath, "Your.xml");
}
Thanks to David I have resolved this problem.
for more precision I add some small details:
1-As David points out in his answer (and as stated in unity documentations), we should use StreamingAssets if we want to have the same folder structure. One should use Application.streamingAssetsPathto retrieve the path.
However, files are still in the apk package in android's case, so they should be accessed using unity android's www class.
a good practice here is to create a method to read the file (even mandatory if you are going to read more than one file)
here is one such method:
private IEnumerator LoadDataFromResources(string v)
{
WWW fileInfo = new WWW(v);
yield return fileInfo;
if (string.IsNullOrEmpty(fileInfo.error))
{
fileContents = fileInfo.text;
}
else
fileContents = fileInfo.error;
}
This is a coroutine, and to use it we need to call it using
yield return StartCoroutine(LoadDataFromResources(path + "/fileName.ext"));
Yet another remark: we can not write into this file or modify it as it's still inside the apk package.
I am working on some app that loads external swfs from the application directory
the problem is that some swf files get loaded correctly and others give ioerror url not found
i put the paths in an array and use a loader to load the path
var arr:Array = ["Games/1.swf", "Games/2.swf"];
var loader:Loader = new Loader();
loader.load(new URLRequest(arr[0]));
this is just example and it is the same in loading all the files but does not work on all files.
what would be the problem?
Firstly, whenever you load something, listen for the appropriate error events so you know what's going on:
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
When using mobile, you should use the app:// shorthand as a reference to the application directory (which I assume is where your Game folder is. Relative paths do not usually work.
So it should look like this:
var arr:Array = ["app://Games/1.swf", "app://Games/2.swf"];
For more information/options, you can look at my answer to this question
I am using FlashDevelop 4.0.1 RTM to create a simple Android app and I would like to ask how to include external assets (images, xml & sounds located inside the bin folder) to the apk package.
Thanks.
As far as I see, you don't need the external assets to be actually external, they can be embedded, since anyway you want them embedded into the apk.
So just embed them into your swf. Instead of loading assets from the bin folder, do this:
public class YourClass {
// Embed the asset
[Embed(source='assets/yourImage.jpg')] private var yourImageClass:Class;
// ...
// Use the asset
private function someFunction():void {
var yourImage:DisplayObject = DisplayObject(new yourImageClass());
}
}
You can embed pretty much any kind of file.