JSON FILE couldn't find in Android Devices (C# Unity) [SOLVED]

I need a hand on this . On Unity Editor this pretty works fine but when i’m building the apk and try to run my Language Changer function it can’t find the path . Could some point me out where i am lost.

Debug.LogWarning("TODO: Loading Popup on.");

    rh.eLanguage language = tzGlobal.Instance.OPTION.language;

    string json = StreetUtility.LoadJsonFromStreamingAssets("notice.json");
    if (json != null)
    {
        // Separate only the necessary parts.
        LitJson.JsonData data = LitJson.JsonMapper.ToObject(json);
        json = data[language.ToString()].ToJson();

        notice = LitJson.JsonMapper.ToObject<string[]>(json);
    }

    string path = string.Format("{0}/{1}/language", rh.Const.LOCALIZATION_PATH, language);
    json = StreetUtility.LoadJsonFromResources(path);
    if (json != null)
    {
        // json load.
        Dictionary<string, string> dic = LitJson.JsonMapper.ToObject<Dictionary<string, string>>(json);

        // dictionary copy.
        dic_localization_text = new Dictionary<eTextKey, string>();
        eTextKey e;
        for (int i = 0; i < dic.Count; i++)
        {
            e = (eTextKey)i;
            dic_localization_text[e] = dic[e.ToString()];
        }

        // Run registered localize function.
        for (int i = 0; i < list_localize_method.Count; i++)
        {
            complete = false;
            list_localize_method[i].Invoke();
            yield return new WaitUntil(() => complete);
        }
    }

    Debug.LogWarning("TODO: Loading popup off.");

What is this StreetUtility.LoadJsonFromStreamingAssets() and what it does?
Can you show it’s code?

1 Like

Here’s what my StreetUtility.

using UnityEngine;
using System;
using System.IO;
using LitJson;

public class StreetUtility
{
  
    // Parsing 1 (Unity Basic Parser).
    public static string ToJson<T>(T requestObject)
    {
        return JsonUtility.ToJson(requestObject);
    }

    public static T FromJson<T>(string responseJson)
    {
        return JsonUtility.FromJson<T>(responseJson);
    }

    // Parsing 2 (LitJson).
    public static string ToJson_mk2<T>(T requestObject)
    {
        return LitJson.JsonMapper.ToJson(requestObject);
    }

    public static T FromJson_mk2<T>(string responseJson)
    {
        return LitJson.JsonMapper.ToObject<T>(responseJson);
    }

    // Save 1.
    public static void SaveJson(string json, string path)
    {
        using (FileStream fs = new FileStream(path, FileMode.Create))
        {
            using (StreamWriter sw = new StreamWriter(fs))
            {
                sw.Write(json);
            }
        }
#if UNITY_EDITOR
        UnityEditor.AssetDatabase.Refresh();
#endif
    }

    // Save 2.
    public static bool SaveJson_mk2(string json, string path)
    {
        try
        {
            StreamWriter writer = new StreamWriter(path, false);
            writer.WriteLine(json);
            writer.Close();
        }
        catch (Exception e)
        {
            Debug.LogWarningFormat("Failed to save.\n{0}\n{1}\n{2}", e, path, json);
            return false;
        }

#if UNITY_EDITOR
        UnityEditor.AssetDatabase.Refresh();
#endif
        return true;
    }

    // 1 (Resources).
    public static string LoadJsonFromResources(string path_without_extention_under_resources_folder)
    {
        TextAsset textAsset = Resources.Load<TextAsset>(path_without_extention_under_resources_folder);
        return textAsset.text;
    }

    // Load 2 (StreamingAssets).
    public static string LoadJsonFromStreamingAssets(string path_with_extention_under_streaming_assets_folder)
    {
        string json = null;
        try
        {
            //Android Platform
#if UNITY_ANDROID

            //string full_path = string.Format("{0}/{1}",Application.persistentDataPath, path_with_extention_under_streaming_assets_folder);
            //StreamReader reader = new StreamReader(full_path);
            //json = reader.ReadToEnd().Trim();
            //reader.Close();
            string full_path = string.Format("{0}/{1}", Application.streamingAssetsPath, path_with_extention_under_streaming_assets_folder);
            StreamReader reader = new StreamReader(full_path);
            json = reader.ReadToEnd().Trim();
            reader.Close();

            // PK Debug 2017.12.11
            //Debug.Log(json);

            //its already a json file so you don't need to convert
            //JsonData itemData = JsonMapper.ToObject(json);

            /*string full_path = System.IO.Path.Combine(Application.streamingAssetsPath, path_with_extention_under_streaming_assets_folder);
            string result;

            if (full_path.Contains("://") || full_path.Contains(":///"))
            {
                WWW www = new WWW(full_path);
                while (!www.isDone) { }
                result = www.text;
            } else
            {
                result = System.IO.File.ReadAllText(full_path);
            }
            Debug.Log("Loaded file: " + result); */

#elif UNITY_IOS //IOS Platform
          
#elif UNITY_STANDALONE //PC Platform
            string full_path = string.Format("{0}/{1}", Application.streamingAssetsPath, path_with_extention_under_streaming_assets_folder);
            StreamReader reader = new StreamReader(full_path);
            json = reader.ReadToEnd().Trim();
            reader.Close();

            Debug.Log(json);
#endif
        }
        catch (Exception e)
        {
            Debug.LogWarningFormat("Failed to Load.\n{0}\n{1}", e, path_with_extention_under_streaming_assets_folder);
        }
        return json;
    }
  
}

And here’s my LoadJsonFromStreamingAsset

public static string LoadJsonFromStreamingAssets(string path_with_extention_under_streaming_assets_folder)
    {
        string json = null;
        try
        {
            //Android Platform
#if UNITY_ANDROID

            //string full_path = string.Format("{0}/{1}",Application.persistentDataPath, path_with_extention_under_streaming_assets_folder);
            //StreamReader reader = new StreamReader(full_path);
            //json = reader.ReadToEnd().Trim();
            //reader.Close();
            string full_path = string.Format("{0}/{1}", Application.streamingAssetsPath, path_with_extention_under_streaming_assets_folder);
            StreamReader reader = new StreamReader(full_path);
            json = reader.ReadToEnd().Trim();
            reader.Close();

            // PK Debug 2017.12.11
            //Debug.Log(json);

            //its already a json file so you don't need to convert
            //JsonData itemData = JsonMapper.ToObject(json);

            /*string full_path = System.IO.Path.Combine(Application.streamingAssetsPath, path_with_extention_under_streaming_assets_folder);
            string result;

            if (full_path.Contains("://") || full_path.Contains(":///"))
            {
                WWW www = new WWW(full_path);
                while (!www.isDone) { }
                result = www.text;
            } else
            {
                result = System.IO.File.ReadAllText(full_path);
            }
            Debug.Log("Loaded file: " + result); */

#elif UNITY_IOS //IOS Platform
           
#elif UNITY_STANDALONE //PC Platform
            string full_path = string.Format("{0}/{1}", Application.streamingAssetsPath, path_with_extention_under_streaming_assets_folder);
            StreamReader reader = new StreamReader(full_path);
            json = reader.ReadToEnd().Trim();
            reader.Close();

            Debug.Log(json);
#endif
        }
        catch (Exception e)
        {
            Debug.LogWarningFormat("Failed to Load.\n{0}\n{1}", e, path_with_extention_under_streaming_assets_folder);
        }
        return json;
    }

Streaming Assets on Android are inside apk file, so normal C# stream classes can’t read it. UnityWebRequest and WWW can read them. Still, check for errors in either of them.

As you can see i have comments there that uses UnityWebRequest and WWW but non of them works. I don’t know why . Would you mind showing me some example on my end?

Print the error from WWW object and the resulting path you are trying to read. Paste both of them here, most likely there is something wrong with the path.

I have an example here https://discussions.unity.com/t/665442/10

It gets the value back, which is a string. This still has to be deserialized into an object, but that’s normal for reading all text.

Okay i’ll get back to you @Aurimas-Cernius

Thank you i’ll try that out

It has this error

Dude i try your code and it has this error on Logcat

A URL Connection to a Java ARchive (JAR) file or an entry in a JAR file is not supported

Here’s what my code looks like

string full_path = string.Format("{0}/{1}", Application.streamingAssetsPath, path_with_extention_under_streaming_assets_folder);
            UnityWebRequest www = UnityWebRequest.Get(full_path);
            www.Send();
            if (www.isError)
            {
                Debug.Log(www.error);
            } else
            {
                Debug.Log(www.downloadHandler.text);
            }

Hello guys i tried reconstruct my code and did it this way.

string full_path = Path.Combine(Application.streamingAssetsPath, path_with_extention_under_streaming_assets_folder);
            string result;
            if (full_path.Contains("://") || full_path.Contains(":///"))
            {
                WWW www = new WWW(full_path);
                while (!www.isDone) { }
                result = www.text;
            }
            else
            {
                result = File.ReadAllText(full_path);
            }
            Debug.Log("Loaded File : " + result);

Now on my Logcat it displays like this

Loaded File : {
“EN”: [
“Cancel is available with Cancel button.”,
“If you succeed in a lottery, you can receive additional rewards.”,
“Round 2 and 3 are shorter than you think.”,
“Please check the homepage in Confirm Game Method and Change Member Information.”
],
“KR”: [
“Cancel 버튼으로 배팅 취소가 가능합니다.”,
“로또에 성공하면 추가적인 보상을 받을 수 있습니다.”,
“라운드 2와 3은 생각보다 시간이 짧습니다.”,
“게임 방법 확인 및 회원정보 변경은 홈페이지에서 확인해주세요.”
],
“CN”: [
“[中文] Cancel is available with Cancel button.”,
“[中文] If you succeed in a lottery, you can receive additional rewards.”,
“[中文] Round 2 and 3 are shorter than you think.”,
“[中文] Please check the homepage in Confirm Game Method and Change Member Information.”
],
“HK”: [
“[广东话] Cancel is available with Cancel button.”,
"[广东话] If you succe

It successfully get the notice.json but the problem is its like not getting all the information inside my notice.json??? What do you think because i can’t still change my language

Hey guys someone help me please

While I did try to help you before, I’m not sure what your question is now. If you pull the string and try to deserialize it into a class, you should get an error. Logcat should display this error, but I would suggest you use something like log viewer https://assetstore.unity.com/packages/tools/log-viewer-12047 (note you’ll get an error about the web player, just remove those lines that use it if you get this error) to view stuff on the device itself.

Otherwise, you say it doesn’t show you all the text, but unless there is something in your file that makes it cut off the text, it should load it all.

Actually sir while i was away , i keep on testing it until it came out that this line of code

LitJson.JsonData data = LitJson.JsonMapper.ToObject(json);
            json = data[language.ToString()].ToJson();
            Debug.LogError("PK DEBUG on Language.toString() : " + language.ToString());
            notice = LitJson.JsonMapper.ToObject<string[]>(json);

is the suspect so if did it like this right now:
On my StreetUtlity function

string full_path = Path.Combine(Application.streamingAssetsPath, path_with_extention_under_streaming_assets_folder);
            if (full_path.Contains("://") || full_path.Contains(":///"))
            {
                WWW reader = new WWW(full_path);
                while (!reader.isDone) { }

                json = reader.text;
            }
            else
            {
                json = File.ReadAllText(full_path);
            }

            Debug.Log("Loaded File : " + json);
            JsonData itemData = JsonMapper.ToObject(json);

I’m doing it like that while on my LocalizationManager.cs

        rh.eLanguage language = tzGlobal.Instance.OPTION.language;
       
        string json = StreetUtility.LoadJsonFromStreamingAssets("notice.json");
        if (json != null)
        {
            // 필요한 부분만 분리.

#if UNITY_STANDALONE
            LitJson.JsonData data = LitJson.JsonMapper.ToObject(json);
            json = data[language.ToString()].ToJson();
            Debug.LogError("PK DEBUG on Language.toString() : " + language.ToString());
            notice = LitJson.JsonMapper.ToObject<string[]>(json);
           
#elif UNITY_ANDROID
            LitJson.JsonData data = LitJson.JsonMapper.ToObject(json);
            json = data.ToJson();
            notice =

#else
#endif

        }

I’m doing it like this now . The problem is that i’m stuck on how to convert the jsonData to string for android.

Hi sir i tried this line of code

#if UNITY_STANDALONE
            LitJson.JsonData data = LitJson.JsonMapper.ToObject(json);
            json = data[language.ToString()].ToJson();
            Debug.LogError("PK DEBUG on Language.toString() : " + language.ToString());
            notice = LitJson.JsonMapper.ToObject<string[]>(json);
           
#elif UNITY_ANDROID
            LitJson.JsonData data = LitJson.JsonMapper.ToObject(json);
            json = data.ToJson();
            notice = LitJson.JsonMapper.ToObject<string[]>(json);

On my #UNITY_ANDROID it has this error on my unity editor
Method not found: ‘Default constructor not found…ctor() of System.String[ ]’.

I’m not familiar with LitJson as I use Json.net.

However my guess is it doesn’t know how to handle your Generic type of string[ ].

I’m also confused by your code. You do a ToObject on the json, assigning it to data. Then you convert that data back to a json and assign it to the json variable, then you try to convert that back into an object with the only difference being you try to do a generic type of string[ ].

1 Like

Hi PaulKevin,

I’am using this code and works in webGL and Android.
I put the language files in StreamingAssets directory; when building to Android I can see the files in the apk file, using 7zip.
My JSON file (one for each language) is something “fake”: it has the format “key”:“translation”.

Good luck and hope this help.

// -----------------------------------------------------------------------------------------------------
//separating the reading coroutine to call from the inspector based on gamer language selection
    IEnumerator readLocalizedText(string language)
    {
        bool error = false;
        isRunning = true;   //171023
        string filePath;
        if ((Application.platform == RuntimePlatform.Android) ||
            (Application.platform == RuntimePlatform.WebGLPlayer)) {
            filePath = Application.streamingAssetsPath + "/i18n/" + language + ".json";
        } else {
                filePath = "file://" + Application.streamingAssetsPath + "/i18n/" + language + ".json";
        }
        WWW www = new WWW (filePath);
        yield return www;
        isRunning = false;
        if (!string.IsNullOrEmpty (www.error)) {
            error = true;
        }
     
        //if the file does not exist send msg to the output.txt and it does not stop the game,
        //but all translatable texts will appear as @ - as defined above (arbitrary)
        if (!error) {         //found the file, let's read
            string dataAsJson = www.text;
            //remove keys, quotation marks, \ r \ n - to stay "msgCalledInTheCode":"translation"
            string[] keyValueArray = dataAsJson.Replace ("{", string.Empty).Replace ("}", string.Empty).Replace ("\"", string.Empty).Replace ("\r", string.Empty).Split (new string[] { "\n" }, System.StringSplitOptions.RemoveEmptyEntries);
            string tmp;
            for (int i = 0; i < keyValueArray.Length; i++) {
                //json: in all key/value pairs there is the comma separating between items, except in the last pair
                tmp = keyValueArray [I].Substring (keyValueArray [I].IndexOf (":") + 1);
                tmp = (i == keyValueArray.Length - 1) ? tmp : tmp.Substring (0, tmp.Length - 1);
                localizedText.Add (keyValueArray [I].Substring (0, keyValueArray [I].IndexOf (":")), tmp);
            }
        } else {
            Debug.LogError (">>> Cannot find localization file StreamingAssets" + "/i18n/" + language + ".json");
        }
        //read or not, call up the team selection screen
        SceneManager.LoadScene("Configurations");
    }

Hi joseperez i’m kind of noob when it comes to json file and dictionaries so i’m going to ask this noob question . Your code doesn’t have a conversion of json data to string right . after reading the json file from streaming asset it will remove the unnecessary things which i have something like this

LitJson.JsonData data = LitJson.JsonMapper.ToObject(json);
            json = data[language.ToString()].ToJson();
            Debug.LogError("PK DEBUG on Language.toString() : " + language.ToString());
            notice = LitJson.JsonMapper.ToObject<string[]>(json);

the only problem i got here is that it’s only working on my PC version and not on my android version . Could you help me out translating/converting this code to work on android?? Cause i’m suspecting that json = data[language.ToString()].ToJson(); line of code is the suspect of my problem

And sorry for this can i have your localizedtext method . If you dont mind