0

So I'm loading in a remote json file, storing it locally then reading the local file to populate a list which is ultimately inserted into an onscreen dropdown. I tried all sorts of things, using litjson and had errors handling, using application.various paths.

Anyway, I got it all working eventually but only in the editor, I popped a text box on the screen called Debug to load text onscreen, it should show contents of the file and it does in the editor but not on my android device.

I changed all the folder routes to move and load everything to the resources folder as I read that could be an issue.

Changed the code to writer instead of litjson writealltext() and after all that I have the same result.

It works in unity but not on the device, it's as if the populateList() function isn't firing or something.

I'm stuck. Help appreciated.

Heres the code :

using UnityEngine;
using System.Collections;
using LitJson;
using System;
using System.IO;
using System.Collections.Generic;
using UnityEngine.UI;

public class loadJSONFoodCats : MonoBehaviour {

    public string url;
    private string jsonString;
    private JsonData itemData;
    public List<Category> myListCats = new List<Category>();
    private List<string> catTags = new List<string>();

    public Dropdown typeFilter;

void Start (){
      WWW www2 = new WWW(url);
      StartCoroutine(WaitForRequest(www2));
}

IEnumerator WaitForRequest(WWW www2){
  yield return www2;

  // check for errors
  if (www2.error == null)
  {
    //SAVE JSON FROM ONLINE LOCALLY
        jsonString = www2.text;
        string path = "Assets/Resources/JSON/FoodnDrinkCats.json";
        string str = jsonString;
         using (FileStream fs = new FileStream(path, FileMode.Create)){
             using (StreamWriter writer = new StreamWriter(fs)){
                 writer.Write(str);
             }
         }

       // Debug.Log("PASSED");

    //READ SAVED FILE
        TextAsset file = Resources.Load("JSON/FoodnDrinkCats") as TextAsset;

    jsonString = file.ToString();
    itemData = JsonMapper.ToObject(jsonString);

    //SORT DATA OUT
        ConstructCatsDatabase();
        //Debug.Log(myList[0].post_title);

        //Category cat = fetchItemByID(255);
        //listing.post_title;
        //Debug.Log(cat.Slug);
        Text singleText = GameObject.Find("Debug").GetComponent<Text>();
        singleText.text = "LOADING:"+myListCats[0].Name;

        populateList();

      } else {
      Debug.Log("WWW Error: "+ www2.error);
      }    
  }

    void ConstructCatsDatabase(){

        for (int i = 0; i < itemData.Count; i++) {
            myListCats.Add(new Category((int)itemData[i][0], itemData[i][1].ToString(), itemData[i][2].ToString()));
        }

  }

    public Category fetchItemByID(int id){

        for (int i = 0; i < myListCats.Count; i++) {
            if(myListCats[i].Term_ID == id){
                return myListCats[i];
            }

        }
        return null;
 }


    void populateList(){
        for (int i = 0; i < myListCats.Count; i++) {
            //TRANSLATION DONE, NOW ADD THEM
            catTags.Add(myListCats[i].Name);

            Text singleText = GameObject.Find("Debug").GetComponent<Text>();
            singleText.text = "info:"+myListCats[i].Name;
        }
        catTags.Sort();
        typeFilter.AddOptions(catTags);



    }



}




public class Category {

    public int Term_ID {get; set;}
    public string Name {get; set;}
    public string Slug {get; set;}

    public Category(int id, string name, string slug){

        this.Term_ID = id;
        this.Name = name;
        this.Slug = slug;

    }

}
Diego
  • 371
  • 1
  • 3
  • 13
  • 1
    You don't have to change the title to "SOLVED", just mark one answer as the correct one. – Iggy Apr 11 '17 at 13:19
  • The problem is that you are writing to the Resources folder with `FileStream`. You use `Application.persistentDataPath` for that. Also, you should be using Unity's [JsonUtility](https://stackoverflow.com/questions/36239705/serialize-and-deserialize-json-and-json-array-in-unity/36244111#36244111). I made a warapper to read save game data on any device and you can find that [here](https://stackoverflow.com/questions/40965645/what-is-the-best-way-to-save-game-state/40966346#40966346). – Programmer Apr 11 '17 at 18:37

3 Answers3

1

In you can't write so easily to the FileSystem. There is something called isolated storage there.

Use instead Application.persistentDataPath as path for JSON. It's recommended from Unity3D and works on all platforms.


Also make sure your manifest file for Android contains: (located in Assets/Plugins/Android)

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

Check build configuration in Android for the write access:

enter image description here

  • I had tried that but I had Access denied issues, I'm on a mac if that makes any difference as im not running unity as an administrator like you can on windows to get around the authorised issue. Could you show me how you would change my code in the filestream section plz. To add, I also have a json file already in the folder so its the reading side more than anything that isnt working as it already has the json code in the build and just goes for an update from the server on load, unless that could cause an error which prevents the rest working I don't know? – Diego Apr 11 '17 at 12:44
  • Yup, my manifest has the line, hmm, now I'm getting a directory path issue, when I look at the path though the applicaiton.persistantDataPath is looking in the wrong route? – Diego Apr 11 '17 at 13:01
  • 1
    Ahhhh, write access was internal only, I'll give that a go :) Thanks @Smartis – Diego Apr 11 '17 at 13:05
0

For writing on different platform use Application.persistentDataPath

So your path in code will become for writing like that :

string path = Application.persistentDataPath + "FoodnDrinkCats.json";

Zohaib Javed
  • 323
  • 1
  • 20
  • Im getting a directory not found, its looking for a directory that doesnt seem to exist, DirectoryNotFoundException: Could not find a part of the path "/Users/Diego/Library/Application Support/DefaultCompany/3D Interactive App/JSON/FoodnDrinkCats.json". Default company doesnt exist not does half the path, is it just because its on the laptop rather than a device lookup for a folder? – Diego Apr 11 '17 at 12:54
  • Json folder doesn't exist currently. You have to create it by using File.CreateDirectory but for now its not required in your case so lets try by ignoring that. – Zohaib Javed Apr 11 '17 at 13:04
  • Oh oh, it turns out it works reading the json file on the device but doesn't overwrite the file with new content from the server when the json file online is altered, so the read works but not the write. – Diego Apr 11 '17 at 14:03
  • jsonString = www2.text; string path = Application.persistentDataPath + "FoodnDrinkCats.json"; string str = jsonString; using (FileStream fs = new FileStream(path, FileMode.Create)){ using (StreamWriter writer = new StreamWriter(fs)){ writer.Write(str); } } TextAsset file = Resources.Load("JSON/FoodnDrinkCats") as TextAsset; jsonString = file.ToString(); itemData = JsonMapper.ToObject(jsonString); – Diego Apr 11 '17 at 14:09
  • I added this line above the file path and it wrote a new copy, going to try it on my device now. System.IO.File.WriteAllText("Assets/Resources/JSON/listings.json", jsonString); – Diego Apr 11 '17 at 14:25
  • This only works in editor again but persistent file path wont work either for some reason, coffee time – Diego Apr 11 '17 at 14:34
  • Saw your solution below it works. Even there you can see that they are using persistent data path. Plus for writing you cannot use resources.load folder,Cheers :) – Zohaib Javed Apr 11 '17 at 18:41
0

Here's the solution.

This code will manage the file system on various platforms. Write read and path management. So far for me it works perfectly. It came from a unity forum by a guy named FAEZ.

public void writeStringToFile( string str, string filename )
{
#if !WEB_BUILD
string path = pathForDocumentsFile( filename );
FileStream file = new FileStream (path, FileMode.Create, FileAccess.Write);

StreamWriter sw = new StreamWriter( file );
sw.WriteLine( str );

sw.Close();
file.Close();
#endif  
}


public string readStringFromFile( string filename)//, int lineIndex )
{
#if !WEB_BUILD
string path = pathForDocumentsFile( filename );

if (File.Exists(path))
{
FileStream file = new FileStream (path, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader( file );

string str = null;
str = sr.ReadLine ();

sr.Close();
file.Close();

return str;
}

else
{
return null;
}
#else
return null;
#endif 
}


public string pathForDocumentsFile( string filename ) 
{ 
if (Application.platform == RuntimePlatform.IPhonePlayer)
{
string path = Application.dataPath.Substring( 0, Application.dataPath.Length - 5 );
    path = path.Substring( 0, path.LastIndexOf( '/' ) );
    return Path.Combine( Path.Combine( path, "Documents" ), filename );
}

else if(Application.platform == RuntimePlatform.Android)
{
string path = Application.persistentDataPath;   
path = path.Substring(0, path.LastIndexOf( '/' ) ); 
return Path.Combine (path, filename);
}   

else 
{
string path = Application.dataPath; 
path = path.Substring(0, path.LastIndexOf( '/' ) );
    return Path.Combine (path, filename);
    }
}
Diego
  • 371
  • 1
  • 3
  • 13