# Errors with saveTable() on Android

**URL:** <https://discourse.processing.org/t/errors-with-savetable-on-android/26546>\
**Category:** Processing for Android\
**Created:** [December 28, 2020, 2:15am UTC](https://discourse.processing.org/t/errors-with-savetable-on-android/26546 "2020-12-28T02:15:48Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![SNICKRS](https://avatars.discourse-cdn.com/v4/letter/s/43a26b/32.png) [@SNICKRS](https://discourse.processing.org/u/SNICKRS)\
**Post date:** [December 28, 2020, 2:15am UTC](https://discourse.processing.org/t/errors-with-savetable-on-android/26546/1 "2020-12-28T02:15:48Z")

</div>

Hello, I’m making an android application with processing. It started as a Java game but then i ported it to Android. However, this game utilizes save data, and I used .csv files to save the game’s data. This worked fine in Java mode, but on an Android phone, it strangely doesn’t save the data, and it closes out, and Android gives me an error message. I have looked into other threads, but I don’t know how to fix it. Maybe it can be because i set the game to save data when closed on Java mode, but since the sketch utilizes “fullScreen()”, it only saves data when the esc key is hit.

---

<div class="post-metadata">

**Author:** ![paulgoux](https://avatars.discourse-cdn.com/v4/letter/p/b9bd4f/32.png) [@paulgoux](https://discourse.processing.org/u/paulgoux)\
**Post date:** [December 28, 2020, 5:53am UTC](https://discourse.processing.org/t/errors-with-savetable-on-android/26546/2 "2020-12-28T05:53:28Z")

</div>

Search for android permissions in the forum search you should find your answer there.

---

<div class="post-metadata">

**Author:** ![noel](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/noel/32/213_2.png) [@noel](https://discourse.processing.org/u/noel)\
**Post date:** [December 28, 2020, 6:33am UTC](https://discourse.processing.org/t/errors-with-savetable-on-android/26546/3 "2020-12-28T06:33:41Z")

</div>

To save game results I would use SharedPreferences; Then you don’t have to worry, about permissions. But results, however, will be lost when you uninstall the App. You can also use the save() function, or saveStrings(), but along with giving permissions, you have to add some extra code for versions above Lollipop. See examples for these [on my repo here](https://github.com/EmmanuelPil/Android-java-code-utilities-widgets-for-Processing-for-Android).

---

<div class="post-metadata">

**Author:** ![SNICKRS](https://avatars.discourse-cdn.com/v4/letter/s/43a26b/32.png) [@SNICKRS](https://discourse.processing.org/u/SNICKRS)\
**Post date:** [December 28, 2020, 7:36pm UTC](https://discourse.processing.org/t/errors-with-savetable-on-android/26546/4 "2020-12-28T19:36:19Z")

</div>

Hello, I have tried looking for android permissions but it still unexpectedly closes the app. I am able to load the csv or tsv files, but i am not able to write them.

---

<div class="post-metadata">

**Author:** ![noel](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/noel/32/213_2.png) [@noel](https://discourse.processing.org/u/noel)\
**Post date:** [December 28, 2020, 7:58pm UTC](https://discourse.processing.org/t/errors-with-savetable-on-android/26546/5 "2020-12-28T19:58:45Z")

</div>

I just verified, and indeed my android code for saving a table like csv was not updated for versions above Lollipop. Try this code instead.

```auto
// Be sure to give permission WRITE_EXTERNAL_STORAGE

import android.os.Environment;
import android.Manifest; 
import android.content.pm.PackageManager; 
import android.os.Build; 
import android.os.Build.VERSION_CODES; 
import processing.core.PConstants;
import android.app.Activity; 
import android.os.Environment;
Table table; 

Activity activity; 
boolean permissions_granted;
boolean file_saved;
String str_1, str_2;
String tableFile;
String tableFolder;

void setup() { 
  size(displayWidth, displayHeight);
  activity = this.getActivity();
  if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) { 
    requestParticularPermission();
  }
  textAlign(CENTER);
  str_1 = "Click to save a table.";
  str_2 = "Table saved on SD card.";
  textSize(12);
  float twf = width/textWidth(str_1);
  textSize(8*twf);
  table = new Table(); 
  table.addColumn("id"); 
  table.addColumn("species"); 
  table.addColumn("name"); 
  TableRow newRow = table.addRow(); 
  newRow.setInt("id", table.getRowCount() - 1); 
  newRow.setString("species", "Panthera leo"); 
  newRow.setString("name", "Lion"); 
  // Folowing file name is the folder you save your table file in.
  // If it does not exist it will be created automatically
  tableFolder = "MyTables";
  // Folowing string is the name of your table file
  // Be sure to include extension.
  tableFile = "MyTable.csv";
}

void draw() {
  background(0, 0, 200);
  if (file_saved) text(str_2, width/2, height/2);
  else text(str_1, width/2, height/2);
}

void mousePressed () {
  saveMyTable(tableFolder, tableFile);
}

void saveMyTable(String sf, String tf) { 
  try { 
    String absolute_path = new String(Environment.getExternalStorageDirectory().getAbsolutePath()); 
    File file = new File(absolute_path+"/"+sf); 
    println(file);
    if (!file.exists()) { 
      boolean success = true; 
      success = file.mkdirs();
    } 
    saveTable(table, file+"/"+tf);
    println("File saved successfully.");
    file_saved = true;
  } 
  catch (Exception e) { 
    println("Error while saving file: " + e);
  }
} 

private static String[] PERMISSIONS_STORAGE = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }; 
private void requestParticularPermission() { 
  activity.requestPermissions(PERMISSIONS_STORAGE, 2020);
}

public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { 
  switch (requestCode) { 
  case 2020: 
    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
      println("permissions granted");
      permissions_granted = true;
    } else { 
      println("permissions not granted");
    } 
    break; 
  default: 
    activity.onRequestPermissionsResult(requestCode, permissions, grantResults);
  }
}

void onStop() {
  file_saved = false;
}

void onPause() {
  file_saved = false;
}

```

---

<div class="post-metadata">

**Author:** ![SNICKRS](https://avatars.discourse-cdn.com/v4/letter/s/43a26b/32.png) [@SNICKRS](https://discourse.processing.org/u/SNICKRS)\
**Post date:** [December 28, 2020, 8:56pm UTC](https://discourse.processing.org/t/errors-with-savetable-on-android/26546/6 "2020-12-28T20:56:32Z")

</div>

Thanks! I’ll try implementing this code.

---

<div class="post-metadata">

**Author:** ![SNICKRS](https://avatars.discourse-cdn.com/v4/letter/s/43a26b/32.png) [@SNICKRS](https://discourse.processing.org/u/SNICKRS)\
**Post date:** [December 29, 2020, 12:52am UTC](https://discourse.processing.org/t/errors-with-savetable-on-android/26546/7 "2020-12-29T00:52:07Z")

</div>

Hmm, I tried implementing this, but it didn’t seem to work. It may be because I used the loadTable() function wrong, but I will have to keep trying.

---

<div class="post-metadata">

**Author:** ![noel](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/noel/32/213_2.png) [@noel](https://discourse.processing.org/u/noel)\
**Post date:** [December 29, 2020, 4:10am UTC](https://discourse.processing.org/t/errors-with-savetable-on-android/26546/8 "2020-12-29T04:10:24Z")

</div>

I’ve edited the code above and tested it on a KitKat, a Lollipop, and an Android 10 device. I would like to ask you to retry the code again. Previous installations of the app should be uninstalled, to have a clean start. On devices with an Android version above Lollipop, immediately after installing, a dialog will appear asking permission to access photos, media, and other files. (Unless a previous app was not uninstalled) After running the app a folder named “myTables” containing a file “MyTable.csv” should exist on your internal storage SDcard. (Not in Sketch data folder!) The permission WRITE\_EXTERNAL\_STORAGE is required when compiling. If you use the APDE app, please use the “app mode”, instead of the “preview mode”.

---

<div class="post-metadata">

**Author:** ![SNICKRS](https://avatars.discourse-cdn.com/v4/letter/s/43a26b/32.png) [@SNICKRS](https://discourse.processing.org/u/SNICKRS)\
**Post date:** [December 29, 2020, 5:12pm UTC](https://discourse.processing.org/t/errors-with-savetable-on-android/26546/9 "2020-12-29T17:12:06Z")

</div>

Sorry, but the code is not able to write a save file. I will try using a tsv file because on a website it says that you cannot write a csv file, only read it. However, it did say that you can write a tsv file.

---

<div class="post-metadata">

**Author:** ![noel](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/noel/32/213_2.png) [@noel](https://discourse.processing.org/u/noel)\
**Post date:** [December 29, 2020, 5:18pm UTC](https://discourse.processing.org/t/errors-with-savetable-on-android/26546/10 "2020-12-29T17:18:33Z")

</div>

Did you give the permission WRITE\_EXTERNAL\_STORAGE?  
Could you please tell me what device and which Android version you are using?

---

<div class="post-metadata">

**Author:** ![SNICKRS](https://avatars.discourse-cdn.com/v4/letter/s/43a26b/32.png) [@SNICKRS](https://discourse.processing.org/u/SNICKRS)\
**Post date:** [December 29, 2020, 5:48pm UTC](https://discourse.processing.org/t/errors-with-savetable-on-android/26546/11 "2020-12-29T17:48:12Z")

</div>

I’m using a samsung s10e, and I always had the write external storage permission enabled. I don’t know for sure what android version it is, but I think it is that latest API.

---

<div class="post-metadata">

**Author:** ![noel](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/noel/32/213_2.png) [@noel](https://discourse.processing.org/u/noel)\
**Post date:** [December 29, 2020, 5:54pm UTC](https://discourse.processing.org/t/errors-with-savetable-on-android/26546/12 "2020-12-29T17:54:15Z")

</div>

But does it give any error? Is there something else written in the console?  
Are you using PC or APDE?

@akenaton could you revise the code above?

---

<div class="post-metadata">

**Author:** ![noel](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/noel/32/213_2.png) [@noel](https://discourse.processing.org/u/noel)\
**Post date:** [December 29, 2020, 6:36pm UTC](https://discourse.processing.org/t/errors-with-savetable-on-android/26546/13 "2020-12-29T18:36:49Z")

</div>

@SNICKRS Until what API are you targeting?  
Please add this to your Manifest and try once more.

```auto
<manifest ... >
  <application android:requestLegacyExternalStorage="true" ... >
  </application>
</manifest>

```

---

<div class="post-metadata">

**Author:** ![akenaton](https://avatars.discourse-cdn.com/v4/letter/a/a88e4f/32.png) [@akenaton](https://discourse.processing.org/u/akenaton)\
**Post date:** [December 29, 2020, 6:53pm UTC](https://discourse.processing.org/t/errors-with-savetable-on-android/26546/14 "2020-12-29T18:53:58Z")

</div>

@ noel=== your code seems to be good (yet i ll test tomorrow) and it is difficult to answer without any error code

---

<div class="post-metadata">

**Author:** ![SNICKRS](https://avatars.discourse-cdn.com/v4/letter/s/43a26b/32.png) [@SNICKRS](https://discourse.processing.org/u/SNICKRS)\
**Post date:** [December 30, 2020, 12:32am UTC](https://discourse.processing.org/t/errors-with-savetable-on-android/26546/15 "2020-12-30T00:32:44Z")

</div>

Maybe I should send my code? Then we can figure out the error.

---

<div class="post-metadata">

**Author:** ![noel](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/noel/32/213_2.png) [@noel](https://discourse.processing.org/u/noel)\
**Post date:** [December 30, 2020, 12:44am UTC](https://discourse.processing.org/t/errors-with-savetable-on-android/26546/16 "2020-12-30T00:44:37Z")

</div>

Oh sure. If you don’t want it public you can send it as a message…

---

<div class="post-metadata">

**Author:** ![SNICKRS](https://avatars.discourse-cdn.com/v4/letter/s/43a26b/32.png) [@SNICKRS](https://discourse.processing.org/u/SNICKRS)\
**Post date:** [December 30, 2020, 2:42am UTC](https://discourse.processing.org/t/errors-with-savetable-on-android/26546/17 "2020-12-30T02:42:00Z")

</div>

int[] scores = new int[10];  
for(int i = 0; i \< scores.length; i++) {  
scores[i] = 0;  
}  
table = null;  
table = loadTable(“highscore.csv”, “header”);  
if(table != null){  
for(TableRow row : table.rows()){  
int id = row.getInt(“id”);  
scores[id] = row.getInt(“savedata”);  
}  
} else {  
table = new Table();  
table.addColumn(“id”);  
table.addColumn(“savedata”);  
for(int i = 0; i \< scores.length; i++){  
TableRow newRow = table.addRow();  
newRow.setInt(“id”, table.lastRowIndex());  
newRow.setInt(“savedata”, scores[i]);  
}  
}

---

<div class="post-metadata">

**Author:** ![SNICKRS](https://avatars.discourse-cdn.com/v4/letter/s/43a26b/32.png) [@SNICKRS](https://discourse.processing.org/u/SNICKRS)\
**Post date:** [December 30, 2020, 3:43am UTC](https://discourse.processing.org/t/errors-with-savetable-on-android/26546/18 "2020-12-30T03:43:34Z")

</div>

It doesn’t give an error message, because I don’t test on the emulator, I test on a phone. Also, the tsv file method didn’t work.

---

<div class="post-metadata">

**Author:** ![noel](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/noel/32/213_2.png) [@noel](https://discourse.processing.org/u/noel)\
**Post date:** [December 30, 2020, 10:55am UTC](https://discourse.processing.org/t/errors-with-savetable-on-android/26546/19 "2020-12-30T10:55:30Z")

</div>

Sorry I was too tired and fell asleep.  
Seems that maybe you did not load the table correctly for Android.  
Try this code. If everything goes well, a folder “GameTables” will be created in your sdcard with the table file in it.

```auto
// Be sure to give permission WRITE_EXTERNAL_STORAGE

import android.os.Environment;
import android.Manifest; 
import android.content.pm.PackageManager; 
import android.os.Build; 
import android.os.Build.VERSION_CODES; 
import processing.core.PConstants;
import android.app.Activity; 
import android.os.Environment;

Table table; 
Activity activity; 
boolean permissions_granted;
String tableFile = "highscore.csv";
String tableFolder = "GameTables";
int[] scores = new int[10];

void setup() { 
  size(displayWidth, displayHeight);
  activity = this.getActivity();
  if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) { 
    requestParticularPermission();
  }
  
  for (int i = 0; i < scores.length; i++) {
    scores[i] = 0;
  }
  loadMyTable(tableFile);
  if (table != null) {
    for (TableRow row : table.rows()) {
      int id = row.getInt("id");
      scores[id] = row.getInt("savedata");
    }
  }
  printArray(scores);
 
  // gain points in game
  scores[0] = 123;
  scores[1] = 456;
  scores[9] = 789;
  setTableValues();
  printArray(scores);
}

void draw() {
}

void setTableValues() {
  table = new Table();
  table.addColumn("id");
  table.addColumn("savedata");
  for (int i = 0; i < scores.length; i++) {
    TableRow newRow = table.addRow();
    newRow.setInt("id", table.lastRowIndex());
    newRow.setInt("savedata", scores[i]);
  }
  saveMyTable(tableFile, tableFolder);
}

void saveMyTable(String file_s, String folder_s) { 
  try { 
    String absolute_path = new String(Environment.getExternalStorageDirectory().getAbsolutePath()); 
    File file = new File(absolute_path+"/"+folder_s); 
    println(file);
    if (!file.exists()) { 
      boolean success = true; 
      success = file.mkdirs();
    } 
    saveTable(table, file+"/"+file_s);
    println("File saved successfully.");
  } 
  catch (Exception e) { 
    println("Error while saving file: " + e);
  }
} 

void loadMyTable(String s) {
  try {
    String directory = new String(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+tableFolder+"/");
    table = loadTable(directory+s, "header");
    println(directory+s+tableFile);
  } 
  catch (Exception e) {
   println("first table loading");
  }
}

private static String[] PERMISSIONS_STORAGE = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }; 
private void requestParticularPermission() { 
  activity.requestPermissions(PERMISSIONS_STORAGE, 2020);
}

public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { 
  switch (requestCode) { 
  case 2020: 
    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
      println("permissions granted");
      permissions_granted = true;
    } else { 
      println("permissions not granted");
    } 
    break; 
  default: 
    activity.onRequestPermissionsResult(requestCode, permissions, grantResults);
  }
}

```

---

<div class="post-metadata">

**Author:** ![paulgoux](https://avatars.discourse-cdn.com/v4/letter/p/b9bd4f/32.png) [@paulgoux](https://discourse.processing.org/u/paulgoux)\
**Post date:** [December 30, 2020, 11:03am UTC](https://discourse.processing.org/t/errors-with-savetable-on-android/26546/20 "2020-12-30T11:03:34Z")

</div>

This code works for me, and so does the other one.

 ![Screenshot_20201230_110217_com.calsignlabs.apde](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/7/708e704d95affb9a5232339d7ca9c4fdb547f79a.jpeg)

[Next page](https://discourse.processing.org/t/errors-with-savetable-on-android/26546.md?page=2)
