Search Unity

UnityWebRequest for local files on Android - failure

Discussion in 'Scripting' started by KeirREA, Nov 18, 2016.

  1. KeirREA

    KeirREA

    Joined:
    May 1, 2015
    Posts:
    7
    I use UnityWebRequest to load images over the internet. The non-block native texture handling works well and everything is quite smooth.

    Another very handy feature of UnityWebRequest is that it can actually load from HDD too, using file:// instead of http. This is very handy for caching as all you really need to do is alter the load path prefix to switch from a remote url to a local file path.

    Only problem is it doesn't seem to work on Android.

    Anyone out there able to get local UntyWebRequest image loading happening from an Android phone?
     
  2. KeirREA

    KeirREA

    Joined:
    May 1, 2015
    Posts:
    7
  3. Pickyguy

    Pickyguy

    Joined:
    Aug 24, 2013
    Posts:
    13
    I have a similar problem.
    UnityWebRequest for local files doesn't work on even Windows since 5.4.3p3.
    I tried again 5.4.4p2. but It doesn't solved.
     
  4. Pickyguy

    Pickyguy

    Joined:
    Aug 24, 2013
    Posts:
    13
    I found a workaround by accident.
    Use url prefix file:/// instead of file://.
     
  5. Victor-Garcia

    Victor-Garcia

    Joined:
    Jul 16, 2014
    Posts:
    3
    In the Unity 5.6, the UnityWebRequest for local files uses again the format "file://". If you use 3 slashes, it does not work.
     
  6. Edahsrevlis

    Edahsrevlis

    Joined:
    Jul 20, 2017
    Posts:
    2
    If the first character of the path (Application.persistentDataPath for example) is "/" then you need three slashes. FYI for anyone dealing with that issue.
     
  7. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,731
    When using file:// URI the correct one is with three slashes:
    - on UNIX-like operating systems absolute paths star with '/' symbol, so you have file:// + path there
    - on Windows the correct URI is file:/// + path, it's a very common error to have only two slashes (and a lot of software accepts that too)

    Also, it is not recommended to use UnityWebRequest for that. In most cases there are more efficient ways to read local files.
     
    Rodolfo-Rubens likes this.
  8. ferretnt

    ferretnt

    Joined:
    Apr 10, 2012
    Posts:
    412
    We have never managed to get UnityWebRequest and a DownloadHandlerTexture to load files from StreamingAssets on Android, and don't understand why. This is with Unity 5.6.3f1, but we have tried many other 5.x versions. The same code has always worked fine with WWW, and runs on all platforms other than Android. Note for sanity, we have constructed the path string in two different ways, and checked that filePathPerDocs and filePathFromStreamingAssets are identical.

    Code (csharp):
    1.  
    2.         // Construct path as recommended in https://docs.unity3d.com/Manual/StreamingAssets.html
    3.         string filePathPerDocs = "jar:file://" + Application.dataPath + "!/assets/" + fileName;  
    4.         Debug.Log("File Path per docs: " + filePathPerDocs);
    5.  
    6.         // Construct path as we always have for streaming assets.
    7. string filePathFromStreamingAssets = Application.streamingAssetsPath + "/" + fileName;  
    8.         if (Application.platform != RuntimePlatform.Android)
    9.         {
    10.             filePathFromStreamingAssets = "file://" + filePathFromStreamingAssets;
    11.         }
    12.         Debug.Log("File path using streamingassets: " + filePathFromStreamingAssets);
    13.  
    14.         // Load it. This will fail, but will work if using a WWW.
    15. using (UnityWebRequest www = UnityWebRequest.GetTexture(filePathFromStreamingAssets))
    16.  
    On Android, both of these functions build a string of the form:

    jar:file:///data/app/com.mycompany.application-nlg8YQn72iHpXna6k-FeqQ==/base.apk!/assets/imageToLoad.png

    And fail with: "A URL Connection to a Java ARchive (JAR) file or an entry in a JAR file is not supported."

    Can somebody tell me what is wrong with this string (e.g. by typing the correct form of the above string)? We have tried all manner of permutations of file://, ///, etc.

    Interestingly, this thread implies that UnityWebRequest streamingassets support on Android was only added in 2017.1 (post #16)

    https://forum.unity.com/threads/unitywebrequest-getassetbundle-from-streamingassets.430689/

    Yet there are replies higher in this thread (e.g. #5) saying it works in 5.6. I see nothing in the 2017.1 release notes saying that android streamingassets support for UnityWebRequest was added in this version.
     
    Librarius likes this.
  9. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,731
    Reading StreamingAssets on Android using UnityWebRequest is supported since 2017.1. It will not work in 5.6.
    WWW supports this in 5.x.
     
    MechEthan likes this.
  10. ferretnt

    ferretnt

    Joined:
    Apr 10, 2012
    Posts:
    412
    Thanks for clarifying. We'll upgrade after our current release cycle.
     
  11. karsnen

    karsnen

    Joined:
    Feb 9, 2014
    Posts:
    65
    @Aurimas-Cernius

    Could you please state better ways to handle file operations. Let's say there is audio file/ video file or png/jpg on a local drive. I find UnityWebRequest & it's variety of download handlers to load the concerned file and make it Unity friendly.

    My target is iOS && Android.

    I have scoured the internet for a solid solution to load any Unity type file from local drive to Unity at runtime, to find none.

    Thank you
     
    mimiCryMuffin likes this.
  12. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,731
    Texture and AudioClip have methods for loading from files.
     
  13. dhami-nitin

    dhami-nitin

    Joined:
    Jun 5, 2016
    Posts:
    8
    Thanks all you guys for this wonderful thread this helped me
     
  14. ohbane

    ohbane

    Joined:
    Jan 14, 2013
    Posts:
    7
    @Aurimas-Cernius could you be more specific, please? for instance, how to load a Texture2D during runtime (and not in the editor) with unity 2018.3? what is currently the best way and what you are referring to?

    bear in mind that you need texture dimension information from that texture/image itself.

    this is not an answer since width/height are static here: https://answers.unity.com/questions/432655/loading-texture-file-from-pngjpg-file-on-disk.html
     
    mimiCryMuffin likes this.
  15. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    862
    Maybe I am missing something, but how is this done for AudioClip?
     
    abj2023 and MarcSpraragen like this.
  16. Voronoi

    Voronoi

    Joined:
    Jul 2, 2012
    Posts:
    585
    @Aurimas-Cernius Can you be more specific for why the Texture2D.Apply is more efficient compared to
    UnityWebRequestTexture.GetTexture?

    I am trying to build a gallery of in-game screenshots and have tried numerous methods to retrieve the screenshots from disk. The user can take a screenshot, the script saves the file to disk. I want the thumbnail of the new screenshot to populate a gallery of the last 10 screenshots that the user can load.

    Everything works, except that since this is in-game, the texture is not refreshed when written to the games folder. While working In the editor, AssetDatabase.Refresh() makes it work like I want, but I can't access that in a build.

    Using the persistentDatapath and UnityWebRequest gives me the behavior that I want. However, I'm suspicious that the screenshots are now loaded in memory, even when the gallery is not displayed. The same would be true if I used the ScreencaptureAsTexture method. The manual recommends destroying the texture after it's been created. To me, that's the same as just accessing a texture using UnityWebRequest, so I don't see the point.
     
  17. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,731
    It isn't in general. Measure your exact use case.
    The advantage of UWR is that it creates texture on a background thread, so large part of work is done without stalling main thread.
     
  18. DigitalSalmon

    DigitalSalmon

    Joined:
    Jul 29, 2013
    Posts:
    100
    We're experiencing what appears to be this same issue.

    Code (CSharp):
    1.  
    2. using (UnityWebRequest www = UnityWebRequest.Get(url)) {
    3.     UnityWebRequestAsyncOperation asyncOp = www.SendWebRequest();
    4.     while (asyncOp.isDone == false) {
    5.         await Task.Delay(30);
    6.     }
    7.     if (www.isNetworkError || www.isHttpError) {
    8.          Debug.LogWarning($"Network error whilst downloading [{url}] Error: [{www.error}]");
    9.          return null;
    10.     }
    11. }
    12.  
    We have tested with a url as:

    jar:file:///storage/emulated/0/Texture.png
    file:///storage/emulated/0/Texture.png
    /storage/emulated/0/Texture.png
    storage/emulated/0/Texture.png

    Every other combination we can think to try.

    We consistently get HTTP/1.1 404 Not Found returned as the www.error

    This could be a permissions issue, though we have external write permission. Or it could be an issue with the UnityWebRequest system. Or we could be missing something fundemental about Android file loading.

    --

    We understand that Application.dataPath and Application.persistentDataPath both exist (Though since neither path seems to be visible in a file explorer, we can't add our files there).

    Our use case is that we need the access files that exist on our device outside the application folder. They will be placed there using a standard file explorer, ideally in a folder like "storage/CustomFolder/Texture.png".

    There are lots of forum posts around this issue, but as is tradition, they all seem to go dead and remain unsolved.
     
    dimib likes this.
  19. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,731
    Sounds like a likely cause. Export Android Studio project from Unity and play with manifest settings.
     
  20. DigitalSalmon

    DigitalSalmon

    Joined:
    Jul 29, 2013
    Posts:
    100
    The manifest in Android Studio includes

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    Various sources online state:
    Note: If your app uses the WRITE_EXTERNAL_STORAGE permission, then it implicitly has permission to read the external storage as well.

    Are you/ Is anyone aware of any other permissions or manifest keys that related to access?

    It's worth nothing the the URI of the UnityWebRequest reads as http://localhost/storage/emulated/0, which I imagine is incorrect. Specifically using file:///storage/emulated/0 doesn't seem to make any difference (404).

    Also noting I'm talking about primary internal storage, not an sd card, if that is likely to make a difference.

    I remember doing this exact thing years ago through the old WWW class without half the headache :(

    -

    Any other pointers would be very appreciated.
     
    dimib likes this.
  21. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,731
    First thing I'd try would be using System.IO.File to read that same file. If that works, so should UWR.
     
  22. DigitalSalmon

    DigitalSalmon

    Joined:
    Jul 29, 2013
    Posts:
    100
    So. The following is the code i'm using, roughly.

    Code (CSharp):
    1.  
    2. Debug.Log($"({url}) File Exists: {File.Exists(url)} ");
    3. using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(url)) {
    4.     UnityWebRequestAsyncOperation request = www.SendWebRequest();
    5.     while (!request.isDone || !www.isDone) await Task.Delay(30);
    6.     if (www.isNetworkError || www.isHttpError) {
    7.         Debug.LogWarning($"WWW ({url}) has error: {www.error}");
    8.         return null;
    9.     }
    10.     ...
    11. }
    12.  
    Logs:

    (/storage/emulated/0/myImage.jpg) File Exists: True
    java.net.ConnectException: Failed to connect to localhost/127.0.0.1:80
    WWW (/storage/emulated/0/myImage.jpg) has error: Unknown Error

    -

    I've also used File.ReadAllBytes, which reads correctly (Read 475849bytes).

    So IO is quite happy to work with the file, but UnityWebRequest isn't?

    I appriciate all the help - I know support with so many unknowns is a real pain, so thank you very much for your time.
     
    dimib likes this.
  23. rushk1

    rushk1

    Joined:
    Sep 24, 2017
    Posts:
    39
    I'm getting the following error on Android, I'm a beginner but I think this is related.


    Instantiating Bundle- Preparing
    UnityEngine.Logger:Log(LogType, Object)
    <InstantiateBundle>d__8:MoveNext()
    UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
    DownloaderFiles:SaveFile(Byte[])
    <CdnDownloadFile>d__5:MoveNext()
    UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
    (Filename: ./Runtime/Export/Debug.bindings.h Line: 45)
    java.net.ConnectException: Connection refused
    (Filename: Line: 451)
    Bundle Get Content
    UnityEngine.Logger:Log(LogType, Object)
    <InstantiateBundle>d__8:MoveNext()
    UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
    (Filename: ./Runtime/Export/Debug.bindings.h Line: 45)
    InvalidOperationException: Unknown Error
    at UnityEngine.Networking.DownloadHandler.GetCheckedDownloader[T] (UnityEngine.Networking.UnityWebRequest www) [0x00000] in <00000000000000000000000000000000>:0
    at UnityEngine.Networking.DownloadHandlerAssetBundle.GetContent (UnityEngine.Networking.UnityWebRequest www) [0x00000] in <00000000000000000000000000000000>:0
    at DownloaderBundles+<InstantiateBundle>d__8.MoveNext () [0x00000] in <00000000000000000000000000000000>:0
    at UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) [0x00000] in <00000000000000000000000000000000>:0
    (Filename: currently not available on il2cpp Line: -1)



    Code (CSharp):
    1. Debug.Log("Instantiating Bundle- Preparing");
    2.         UnityEngine.Networking.UnityWebRequest request =
    3.             UnityEngine.Networking.UnityWebRequestAssetBundle.GetAssetBundle(savePath);
    4.         yield return request.SendWebRequest();            
    5.  
    6.    
    7.         Debug.Log("Bundle Get Content");
    8.         AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);
    9.         Debug.Log("Bundle Load Asset");
    10.         GameObject a = bundle.LoadAsset<GameObject>(assetToLoad);
    11.  
     
  24. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,731
    UnityWebRequest operates on URIs, not file paths. So you have to prepend the absolute path with file://.
    If that still doesn't work, please report a bug. A file readable via File class should be readable for UWR too.
     
  25. DigitalSalmon

    DigitalSalmon

    Joined:
    Jul 29, 2013
    Posts:
    100
    Thankyou. We had tried every combination of file:// in the past with no luck. There must have been an issue with some other part of our code. The following code is working for us:

    Code (CSharp):
    1. public static async Task<(bool validURL, Texture thumbnail)> LoadImageThumbnail(string url) {
    2.     url = url.Replace("$dataPath", Application.dataPath);
    3.     url = url.Replace("$persistentDataPath", Application.persistentDataPath);
    4.     url = url.Replace("$streamingAssetsPath", Application.streamingAssetsPath);
    5.  
    6.     string baseURL = url.Replace("file://", "");
    7.     Debug.Log($"IO Exists: {File.Exists(baseURL)} ({baseURL})");
    8.  
    9.     using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(url)) {
    10.         UnityWebRequestAsyncOperation request = www.SendWebRequest();
    11.         while (!request.isDone || !www.isDone) await Task.Delay(30);
    12.         if (www.isNetworkError || www.isHttpError) {
    13.             Debug.LogWarning($"WWW ({url}) has error: {www.error}");
    14.             return (false, null);
    15.         }
    16.  
    17.         Texture2D handledTexture = DownloadHandlerTexture.GetContent(www);
    18.         if (handledTexture == null) {
    19.             return (false, null);
    20.         }
    21.         Texture2D texture = new Texture2D(handledTexture.width, handledTexture.height, TextureFormat.ARGB32, false);
    22.         texture.name = Path.GetFileNameWithoutExtension(url);
    23.  
    24.         texture.LoadImage(www.downloadHandler.data);
    25.      
    26.         texture.Apply();
    27.  
    28.         //return valid results:
    29.         return (true, texture);
    30.     }
    31. }
    An example path we're using:
    file:///storage/emulated/0/Corridor.jpg
     
    Last edited: Mar 22, 2019
  26. rushk1

    rushk1

    Joined:
    Sep 24, 2017
    Posts:
    39
    I have tried the followings Uris

    /storage/emulated/0/Android/data/com.sri.sriedu/files/sriGames/mybundle
    file:///storage/emulated/0/Android/data/com.sri.sriedu/files/sriGames/mybundle

    I get the same error for both of the above ,
    java.net.ConnectException: Connection refused
     
  27. rushk1

    rushk1

    Joined:
    Sep 24, 2017
    Posts:
    39
    Can you please give the uri that worked for you. Also , in the player settings, what is the min / max target android api, that is working for you? And the Unity Version that is working for you?
     
    Last edited: Mar 21, 2019
  28. rushk1

    rushk1

    Joined:
    Sep 24, 2017
    Posts:
    39
    I updated Unity and reinstalled Android Studio and sdk
    Still getting the same error.
    File.ReadAllBytes works ok. But UWR does not.

    Unity Version is 2018.3.9f1

    My Player Settings are as follows :
    Minimum API Level 21
    Target API Level 26
    Scripting Runtime Version .NET 4.x equivalent
    Scripting Backend IL2CPP
    Api Compatibility Level : .NET Standard 2.0


    Install Location : External
    Internet Access : Require
    Write Permission : Internal


    Permissions as per the manifest are :

    <uses-permission
    android:name="android.permission.INTERNET" />

    <uses-permission
    android:name="com.android.vending.BILLING" />

    <uses-permission
    android:name="android.permission.ACCESS_NETWORK_STATE" />


    Also , on inspecting the APK in Android Studio , in the manifest the following line has been flagged as an error :

    xmlns:android="http://schemas.android.com/apk/res/android"
    Error : URI Is not registered (Settings |Languages and Frameworks |Schemas and DTDs)



    I'll file a bug report soon, unless any of the above already points to the problem ?
    Thanks
     
  29. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,731
    Which version of Unity do you use?
     
  30. rushk1

    rushk1

    Joined:
    Sep 24, 2017
    Posts:
    39
    Unity Version is 2018.3.9f1
     
  31. DigitalSalmon

    DigitalSalmon

    Joined:
    Jul 29, 2013
    Posts:
    100
    Added an example URL - the URI is generated in the code, not directly set :)

    Min: 6.0 (23)
    Max: Auto (Highest)

    2018.3.8f1
     
    rushk1 likes this.
  32. rushk1

    rushk1

    Joined:
    Sep 24, 2017
    Posts:
    39
    Thank you very much for the info.
    I am also setting the URI from code , and it's the same format. But I'm trying access an Asset Bundle, so maybe something to do with that...
     
  33. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,731
    No, the only specific with asset bundles is that you can get an error due to cashing system. You can easily check that by simply using Get to just load bytes to memory and not use asset bundle system at all.
    If absolute path is readable using File.ReadAllBytes, then just prepending that path with file:// should work too, unless your path contains special characters that have to be escaped in URIs.
     
  34. Wattosan

    Wattosan

    Joined:
    Mar 22, 2013
    Posts:
    460
    Hey,

    My Unity version is 2019.1.4f1 and I had the same issues as described above (developing for Oculus Go, which uses an Android platform). I managed to fix it. The final code can be seen here (it is full of commented debug.logs for you to test):
    Code (CSharp):
    1. IEnumerator LoadImageFromDisk(string id, string path, Action<string, string, Texture2D> callback)
    2. {
    3.     using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(path))
    4.     {
    5.         // string baseURL = path.Replace("file://", "");
    6.         // Debug.Log($"IO Exists: {File.Exists(path)} ({path})");
    7.  
    8.         // Debug.Log("uwr.uri: " + uwr.uri);
    9.         // Debug.Log("uwr.uri.absoluteUri: " + uwr.uri.AbsoluteUri);
    10.         // Debug.Log("uwr.uri.absolutePath: " + uwr.uri.AbsolutePath);
    11.         // Debug.Log("uwr.url: " + uwr.url);
    12.  
    13.         uwr.uri = new Uri(uwr.uri.AbsoluteUri.Replace("http://localhost", "file://"));
    14.         uwr.url = uwr.url.Replace("http://localhost", "file://");
    15.  
    16.         yield return uwr.SendWebRequest();
    17.  
    18.         // Debug.Log("AFTER URL: " + uwr.url);
    19.         // Debug.Log("AFTER URI.AbsoluteUri: " + uwr.uri.AbsoluteUri);
    20.         // Debug.Log("AFTER URI.AbsoluteUrl: " + uwr.uri.AbsolutePath);
    21.  
    22.         if (uwr.isNetworkError || uwr.isHttpError)
    23.         {
    24.             Debug.LogError(uwr.error);
    25.         }
    26.         else
    27.         {
    28.             Debug.Log("Loaded file from " + path.Replace("/", "\\"));
    29.             var tex = DownloadHandlerTexture.GetContent(uwr);
    30.             if (tex != null)
    31.             {
    32.                 callback?.Invoke(id, path, tex);
    33.             }
    34.         }
    35.     }
    36. }

    The beginnings of url and uri.absoluteUri are automatically set to "http://localhost" when the UnityWebRequest object is created. Before calling uwr.SendWebRequest() you have to do one of following (or both):

    1. Change the beginning of uwr.uri.AbsoluteUri (in my case "http://localhost/storage/...") from "http://localhost" to "file://" (in my case "file:///storage/...". Notice 3 slashes, not 2!). To do that you have to create a new Uri object on the uwr.
      uwr.uri = new Uri(uwr.uri.AbsoluteUri.Replace("http://localhost", "file://"));
      .
    2. Or do the same with uwr.url:
      uwr.url = uwr.url.Replace("http://localhost", "file://");
      .
     
  35. JeanSebastienMDC

    JeanSebastienMDC

    Joined:
    Nov 22, 2018
    Posts:
    1
    Thank you very much FROSTY, you just have just saved me and my project....
    I ve got the same issues and i was stuck in it.
    You r my savior :) . it is working now !
     
  36. samson2020

    samson2020

    Joined:
    Dec 16, 2019
    Posts:
    8
    I got this error The type or namespace name 'Action<,,>' could not be found (are you missing a using directive or an assembly reference?)
     
  37. samson2020

    samson2020

    Joined:
    Dec 16, 2019
    Posts:
    8
    Please paste the full working code
     
  38. samson2020

    samson2020

    Joined:
    Dec 16, 2019
    Posts:
    8
    Thanks a lot:):) it worked for me !!!!
     
  39. coderacer

    coderacer

    Joined:
    Dec 13, 2016
    Posts:
    2
    For me, the solution found on the Internet worked - to bring the target file names to lowercase. my task looked like this (on android): transfer the file from the StreamingAssets directory (into apk) to the PersistentDataPath directory for reading/writing. here is the code:
    Code (CSharp):
    1. if (!File.Exists(Application.persistentDataPath + "/gamedata"))
    2.         {
    3.             string path = "";
    4.             #if (UNITY_EDITOR || UNITY_STANDALONE_LINUX)          
    5.                 path = "file://" + Application.streamingAssetsPath + "/gamedata";          
    6.             #endif
    7.             #if (UNITY_ANDROID && !UNITY_EDITOR && !UNITY_STANDALONE_LINUX)                                      
    8.                 path = Application.streamingAssetsPath + "/gamedata";
    9.             #endif
    10.             UnityEngine.Networking.UnityWebRequest www = UnityEngine.Networking.UnityWebRequest.Get(path);
    11.             www.SendWebRequest();
    12.             while (!www.isDone) { }
    13.             byte[] loadBytes = www.downloadHandler.data;
    14.             System.IO.File.WriteAllBytes(Application.persistentDataPath + "/gamedata", loadBytes);
    15.         }
    I hope I helped someone)
     
  40. jiahuafu

    jiahuafu

    Joined:
    Feb 22, 2018
    Posts:
    3
    F***ing UnityWebRequest
     
    abixbg, Tural-Muslim and WangShibo17 like this.
  41. jiahuafu

    jiahuafu

    Joined:
    Feb 22, 2018
    Posts:
    3
    you must use WWW
     
  42. fashrista

    fashrista

    Joined:
    Apr 6, 2017
    Posts:
    6
    I do not understand why was WWW deprecated if this UnityWebRequest des not even begin to replace it.
     
  43. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,731
    Nonsense. WWW uses UnityWebRequest under the hood. Ignore the haters.
     
  44. Grinchi

    Grinchi

    Joined:
    Apr 19, 2014
    Posts:
    130
    www.bytes - what can replace this in UnityWebRequest ?
    Dont tell me downloadhandler.data because it does on WEB Req and not when you want to read some files or classes.dex from storage.
    Show me the way master !
     
  45. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,731
    Download handler is what has data, whether you read local file or network request.
     
  46. Grinchi

    Grinchi

    Joined:
    Apr 19, 2014
    Posts:
    130
    Code (CSharp):
    1.             string urlScheme = "jar:file://";
    2.             string apkPath = Application.dataPath;
    3.             string separator = "!/";
    4.             string entry = "classes3.dex";
    5.             string url = urlScheme + apkPath + separator + entry;
    6.  
    7.             WWW www = new WWW(url);
    8.             yield return www;
    9.  
    10.             if (www.bytes.Length > 0)
    11.                 Debug.Log("Found");
    Be Friend and change this code to UnityWebRequest so it can work :)
     
  47. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,731
    I believe Application.dataPath already includes jar:file:// in it. Have you tried printing the url out?
    Otherwise, look at the documentation for UnityWebRequest.Get(), it has a sample that should work.
     
  48. jhughes2112

    jhughes2112

    Joined:
    Nov 20, 2014
    Posts:
    178
    So, here's a surprise. Android is INCREDIBLY PICKY about jar:file:// path names. So picky, in fact, that a path like this will fail:
    Code (CSharp):
    1. jar:file:///some/path/to//file.json
    but this will succeed:
    Code (CSharp):
    1. jar:file:///some/path/to/file.json
    Make absolutely certain you don't end up with an extra slash anywhere. I spent two hours tracking this down tonight, and sure enough, this was the problem.
     
    lukasz13 and swingingtom like this.
  49. astracat111

    astracat111

    Joined:
    Sep 21, 2016
    Posts:
    725
    So I needed to migrate from Resources.Load to my own class because Resources.Load broke when loading for Android for my project (not good to use Resources.Load anyway so meh), so I store my files in the persistent data path on Android (gonna use asset bundles that are downloaded from a server).

    With the file in persistent data path, I just drag a file in called 'TestAudioClipOGG'.

    You build a Uri using UriBuilder like this (works for me Unity 2021,1, Android 6.0+ AND windows this works too) and pass the UriBuilder.Uri right into UnityWebRequest.

    Code (CSharp):
    1.  
    2.  
    3. public class ExternalResources {
    4.  
    5.     public static async Task<AudioClip> LoadAudioClipAsync(string relativePath)
    6.     {
    7.         string filePath = GetFileFullPath(relativePath, ".ogg");
    8.         if (filePath == null)
    9.             return null;
    10.  
    11.         UriBuilder uriBuilder = new UriBuilder(filePath);
    12.  
    13.         UnityEngine.Debug.Log("uriBuilder.uri: " + uriBuilder.Uri);
    14.  
    15.         using (UnityWebRequest unityWebRequest = UnityWebRequestMultimedia.GetAudioClip(uriBuilder.Uri, AudioType.OGGVORBIS))
    16.         {
    17.             unityWebRequest.SendWebRequest();
    18.  
    19.             while (unityWebRequest.isDone == false)
    20.                 await Task.Delay(5);
    21.  
    22.             if (unityWebRequest.result == UnityWebRequest.Result.ConnectionError || unityWebRequest.result == UnityWebRequest.Result.DataProcessingError)
    23.             {
    24.                 UnityEngine.Debug.LogError("Data Processing or Connection Error for filePath: " + filePath);
    25.                 return null;
    26.             }
    27.  
    28.             return DownloadHandlerAudioClip.GetContent(unityWebRequest);
    29.  
    30.         }
    31.  
    32.     }
    33.  
    34.  
    35.     private static string GetFileFullPath(string relativePath, string extension)
    36.     {
    37.         string fullPath = UnityDataPath + "/" + relativePath + extension;
    38.         if (File.Exists(fullPath) == false)
    39.         {
    40.             UnityEngine.Debug.LogError("No asset found with path of: " + fullPath);
    41.             return null;
    42.         } else
    43.         {
    44.             return fullPath;
    45.         }
    46.  
    47.     }
    48.  
    49. }
    50.  
    51.  

    You run it like this:

    Code (CSharp):
    1. Task<AudioClip> acTask = ExternalResources.LoadAudioClipAsync("TestAudioClipOGG");
    2.  
    3.         while (acTask.IsCompleted == false)
    4.         {
    5.             UnityEngine.Debug.Log("Loading AudioClip...");
    6.             yield return new WaitForSeconds(0.1f);
    7.         }
    8.  
    9.         AudioClip testAudioClip = acTask.Result;
    10.  
    11.         audioSource.PlayOneShot(testAudioClip);
     
    LordVise likes this.
  50. codemaker2015

    codemaker2015

    Joined:
    Aug 19, 2018
    Posts:
    27
    This error will occurs when we are trying to access a local file content using WWW. There we have to provide the protocol field as "file://" otherwise it will consider as a normal URL and trying to reach the address.

    Change the below code

    Code (CSharp):
    1.        
    2.         string localFilePath = Path.Combine(Application.persistentDataPath, fileName);
    3.         WWW www = new WWW(localFilePath);
    4.         yield return www;
    5.         if (!string.IsNullOrEmpty(www.error))
    6.         {
    7.             Debug.LogError("Error while loading file : " + www.error);
    8.             yield break;
    9.         }
    10.  
    to

    Code (CSharp):
    1.        
    2.         string localFilePath = Path.Combine(Application.persistentDataPath, fileName);
    3.         WWW www = new WWW("file://" + localFilePath);
    4.         yield return www;
    5.         if (!string.IsNullOrEmpty(www.error))
    6.         {
    7.             Debug.LogError("Error while loading file : " + www.error);
    8.             yield break;
    9.         }
    10.  
     
    astracat111 likes this.