saveStrings() works but it shouldn't - or should it?

My app, which was originally programmed for Windows, uses loadStrings() and saveStrings() to save its settings. Under Processing for Android, I would have expected that saveStrings() doesn’t work (after reading https://forum.processing.org/one/topic/how-to-savestrings-in-android-22-8-2013.html). Except that it does?! Is this a recent feature or does writing only work on the emulator?

LoadConfig()
{
    File filehandle = new File(sketchPath("config.txt"));
    
    println("PATH "+ sketchPath("config.txt"));
      
    if (filehandle.exists()) 
    {  
        String config[] = loadStrings("config.txt");

        ...
    }
}

void
SaveConfig()
{
    String config[] = new String [1];

    config[0] = ...;
    
    saveStrings("config.txt", config);
}

The println() command to display where the data ends up says “/data/user/0/com.myname.testapp/files/config.txt”. I can not browse to that location on the emulator and I don’t find my settings file anywhere else. For example, not under /storage/emulated/…

You cannot reach this location as it is an internal storage attached to your application, so i understand from the documentation. If you want to get access to any file that you save from your app, you need to save them using getExeternalStorage (don’t forget to enable the permissions) and you need to use absolute paths when working with saveStrings and loadStrings. You get the absolute path using the same getExternalStorage function, as you have seen in previous posts.

Related to your initial question, saveStrings() works as it uses the location of sketchPath() instead of dataPath() internally. I believe Andres made a recent change so when loading data, Android mode will first, attempt to get the data using the folder location provided by dataPath(). If that fails, it automatically looks into sketchPath(). It might throw a warning when it does this… This is an attempt to try to keep dataPath() functionality aligned to the Processing java counterpart.

Kf

@dtmr,@kfrajer ====
Globally, android storage can be of 3 types:

  • internal storage (that is inside your app)
  • external storage inside the phone memory
  • external storage sd card

normally for little files (like scores in a game and so on, perhaps your config file) you saved them using the internal storage, which is the default one; you can see the path to it with context.getFilesdir().getAbsolutePath(); as for rwriting you can use FileOutPutStream adding either context_MODE-PRIVATE or Context.MODE_APPEND; with the second one you can add things to your file; with the first you delete the whole content when you save.

In order to read your files you can use either FileInputStream or processing loadStrings() using the path to your internal storage.

for files more important (videos, sounds…) using external storage is better and as kfrajer said you get the path with getExternalStorage().getAbsolutePath();

in your case i think that you have to save inside onPause();

1 Like

you can use … loadStrings()

So reading/writing internal storage is easy - loadStrings() and saveStrings(). But how can a file be copied from external storage (e.g. download directory) to internal storage? Saving to internal storage isn’t the problem, that’s just saveStrings() with an argument that has no path part. However, loadStrings() with a fully qualified path fails: “Java.lang.IllegalArgumentException: File … contains a path separator”. Should that happen or is that a bug? Documentation states absolute paths - outside data directory - are allowed. Permissions for external storage were set.


// copy file specified by <filename> from downloads to internal storage

String PathDownload = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();

File handle = new File(PathDownload + File.separator + filename);
        
if (handle.exists())
{
    // next line throws exception "contains path separator"

    String strings[] = loadStrings(handle.toString());
        
    ...    
    
    saveStrings(filename, strings);
}

@dtmr===
that s not a bug && the error is well explicated: a file name never includes a path separator.

solution is easy (there are many others, using fileInputStream for example, which is more evident to understand than the wrapper loadStrings() P5 is using). So, supposing that you want to loadStrings from the externalStorageDirectory (the same for download dir) and supposing that the file is called “essai.txt”:

File externalDir = Environment.getExternalStorageDirectory();
   File[] files = externalDir.listFiles();
   String path = externalDir.getAbsolutePath();
   println(path);
 printArray(files);//here you can see all the files and as they are in an array you can also directly get one:
Strings[] monFichier= files[somenumber];//some number= you have seen in the printArray or you can get it by code with a loop
 String[] fichier= loadStrings(path+"/"+"essai.txt");//not any error is fired
 println(fichier[0]);