SelectFile library generates a “FATAL EXCEPTION: main” error

Running the example sketch (provided on the Processing website) “Select_All_Features” using the SelectFile library on my Android phone (Moto g7/Android 10) I get an error. When I tap one of the icons on the screen e.g. to open a folder etc, then the sketch crashes generating “FATAL EXCEPTION: main” error apparently for a "Attempt to get length of null array. Any suggestions to avoid this are welcome. Thanks.
UPDATE: Even the most simple application of this library generates the error (see code and error console)

import select.files.*;
SelectLibrary files;

void setup() {
fullScreen();

files = new SelectLibrary(this);

files.selectInput(“Select a file to process:”, “fileSelected”);
// files.selectFolder(“Select a folder to process:”, “fileSelected”);
// files.selectOutput(“Save the file please:”, “fileSelected”);
}
void fileSelected(File selection) {
if (selection == null) {
println(“Nothing was selected.”);
} else {
println("User selected " + selection.getAbsolutePath());
}
}

BUILD SUCCESSFUL in 9s
25 actionable tasks: 25 executed
FATAL EXCEPTION: main
Process: processing.test.test01, PID: 21829
java.lang.NullPointerException: Attempt to get length of null array

  • at java.util.Arrays.sort(Arrays.java:1424)*
  • at select.files.SelectDialog.sortData(Unknown Source:2)*
  • at select.files.SelectDialog.getData(Unknown Source:17)*
  • at select.files.SelectDialog.updateCurrentList(Unknown Source:0)*
  • at select.files.SelectDialog.onCreate(Unknown Source:126)*
  • at android.app.Dialog.dispatchOnCreate(Dialog.java:421)*
  • at android.app.Dialog.show(Dialog.java:315)*
  • at select.files.SelectLibrary$1.run(Unknown Source:13)*
  • at android.os.Handler.handleCallback(Handler.java:883)*
  • at android.os.Handler.dispatchMessage(Handler.java:100)*
  • at android.os.Looper.loop(Looper.java:241)*
  • at android.app.ActivityThread.main(ActivityThread.java:7617)*
  • at java.lang.reflect.Method.invoke(Native Method)*
  • at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)*
  • at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)*

Not sure as i havent used the lib, here is an alternative though.

Thank you for your suggestion, but for the moment I prefer to stick to the familiar field of processing examples.

If you are on android selectinput and selectfolder do not work.

Sorry for my late reply but can you please have a look at SelectFile and then try to explain me why it does not work.
Thanks

Woops i thought you were referring to selectInput.

You are welcome to try it however i have never tried it.

However i have tried my lib, and am comfortable with the methods.

It is of course entirely up to you so feel free to use whatever you prefer.

Please note that my lib also has a working text input class, called text area, ive made other posts on the forum if you want to see examples,

Also mine makes use of ala android file browser, and the only one ive found to be compatible is

File explorer by Xiaomi on the app store.

From the looks of things you probably have a problem as you havent set the permission requests in your sketch.

However the selectFile seems to have been made for an older version of android and its likely it wont work without choosing an alternative method for permission requests.

Please see their example sketch to see what i mean.

*
 * This minimalistic sketch shows how to use `selectFile()` on Android.
 * 
 * This sketch requires the READ_EXTERNAL_STORAGE permission to be selected
 * through the Sketch Permissions list in the PDE, and then to use the requestPermission()
 * function in the code, since READ_EXTERNAL_STORAGE is a dangerous permission that must
 * be requested during run-time in Android 23 and newer:
 * https://developer.android.com/guide/topics/permissions/requesting.html#normal-dangerous 
 */

import select.files.*;

SelectLibrary files;

void setup() {
  size(displayWidth, displayHeight);

  files = new SelectLibrary(this);
//these are the permissions you need but since api 28
//you have to request user input to confirm them. 
//The link i have provided should include a 
//permission class to address this problem.
  if (!hasPermission("android.permission.READ_EXTERNAL_STORAGE")) {
    requestPermission("android.permission.READ_EXTERNAL_STORAGE", "handleRequest");
  }

  // files.selectFolder("Select a folder to process:", "fileSelected");
  // files.selectOutput("Save the file please:", "fileSelected");
}

void handleRequest(boolean granted) {
  if (granted) {
    files.selectInput("Select a file to process:", "fileSelected");
  } else {
    println("Does not have permission to read external storage.");
  }
}

void fileSelected(File selection) {
  if (selection == null) {
    println("Nothing was selected.");
  } else {
    println("User selected " + selection.getAbsolutePath());
  }
}

Again sorry for a late answer, this is probably due to the fact that I am getting more and more frustrated with this problem which by the way I posted already 7 years ago on the predecessor of this forum. Any way, thank you for your help.
The code you provided is the code that can be found on the Ostap Andrusiv page where you were so kind to comment on the importance of a proper handling of the permission requests. It is this code that I have tried several times (sorry the code at the top of my post is incomplete in that respect). Building the sketch works and a message appears on the phone asking to confirm the permissions set. Once accepted, the sketch will crash and the errors as mentioned above will appear.
Have you successfully tried this code?
regards
marc

not sure how the lib works honestly, and I don’t feel like digging around in it to understand why, as I currently have a working solution. Is it the best probably not, does it allow me to pick a file or a folder yes. Image text etc, no problem. Of course this is just my personal taste.


import select.files.*;

SelectLibrary files;

void setup() {
  size(displayWidth, displayHeight);
  Permission p = new Permission(this, "WRITE_EXTERNAL_STORAGE");
  p = new Permission(this, "READ_EXTERNAL_STORAGE");
  files = new SelectLibrary(this);

  //files.selectFolder("Select a folder to process:", "fileSelected");
  //files.selectOutput("Save the file please:", "fileSelected");
};

void mousePressed() {
  files.selectFolder("Select a folder to process:", "fileSelected");
  //selectInput("Select a file to process:", "fileSelected");
  files.selectOutput("Save the file please:", "fileSelected");
};

void handleRequest(boolean granted) {
  if (granted) {
    println("1");
    files.selectInput("Select a file to process:", "fileSelected");
  } else {
    println("Does not have permission to read external storage.");
  }
};

void fileSelected(File selection) {
  if (selection == null) {
    println("Nothing was selected.");
  } else {
    println("User selected " + selection.getAbsolutePath());
  }
};

this is the permission class remember you also need to set permission in processing’s ide.

public class Permission{
  
  PApplet parent;
  String p;

  public Permission(PApplet pParent,String permissionName) {
    parent = pParent;
    p = permissionName;
    parent.requestPermission("android.permission."+permissionName, "onPermissionResult", this);
  };

  public void onPermissionResult(boolean granted) {
    if (!granted) {
      PApplet.println("User did not grant", p ,"permission.", p ,"is disabled.");
    }
  };

};

However the code above doesnt work even with permissions.

Hi Paul,
Better late than never I decided to try the code above you posted some time ago. All went well until the actual selection of a file. The sketch opened the build-in android fileselector on the phone and I could easily navigate to whatever file on the internal and external storage. The files were visible as thumbnail or as list but they were all greyed out. So it is not possible to make a selection. I checked to permissions but there all was fine. I noticed in the error console the following statements:
The method getExternalStorageDirectory() from the type Environment is deprecated (line 62)
The MediaStore.MediaColumns.DATA is deprecated. (line 135)
Googeling the first statement I found that getExternalStorageDirectory() could be replaced by Context.getExternalFilesDir().getAbsolutePath();
Unfortunately this creates another error. Regrettably my understanding of Java is rather primitive which means I cannot solve this myself. Can you please help me.
regards, marc

You’ll have to give me a few minutes.

It has been updated since but here is the new processing code

import android.content.Intent;
BMS b;
fileInput f;
void setup() {
  size(600,600,P2D);
  b = new BMS(this);
  f = new fileInput(this);
  //f.folder = true;
  //f.file = true;
  f.image = true;
};

void draw() {
  background(255);
  f.displayImage();
  f.readContents();
};

void mousePressed() {
  f.getItem();
};


//@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
  f.handleActivity(requestCode,resultCode,data);
};

you need to download the github filewriterv1.jar

when using folder

the files get sent to their respective arraylists

public String[] listFiles(String s1) {
		String  []s = null;
		String path = s1;
		println("Files", "Path: " + path);
		File directory = new File(path);
		File[] files = directory.listFiles();
		if (files!=null) {
			s = new String [files.length];
			println("Files", "Size: "+ files.length);
			for (int i = 0; i < files.length; i++)
			{
				s[i] = files[i].getName();
				Files.add(s[i]);
				filterAll(s[i]);

				println("Files", "FileName: " + files[i].getName());
			}
		}
		println("Images", images.size());
		println("text", textFiles.size());
		println("Audio", audioFiles.size());
		println("Other", otherFiles.size());
		return s;
	};

there is also a video files arrayList videoFiles, just forgot to print it out

when loading an image the image gets stored to fileInput.img or whatever your fileInput instance is called.

when loading a file it gets stored to fileContent which is a String object, note it is not a String[] array and /n is used to separate lines.

Thanks, I give it a try and let you know but it might be tomorrow.
marc

1 Like

Hi Paul, It is a bit embarrassing but I cannot get the code run. So here is what I did. I combined the two code parts in a new sketch and added the Permission class. Made sure to allow reading and writing to the external storage. Dragged the filewriterv1.jar into the sketch. Checked that the jar is in the Lib directory.
The following errors were generated:

  1. The name “Files” cannot be recognized
  2. The function “FilterAll(String)” does not exist.
  3. The name "textFiles"cannot be recognized.
    It is obvious that I am missing something.
    Can you please put me on the right path.
    marc

here the complete code of the sketch
(I am only looking for txt files)

import android.content.Intent;

BMS b;
fileInput f;
void setup() {
  size(600, 600, P2D);
  b = new BMS(this);
  f = new fileInput(this);
  f.folder = true;
  f.file = true;
  //f.image = true;
};

void draw() {
  background(255);
  f.displayImage();
  f.readContents();
};

void mousePressed() {
  f.getItem();
};


//@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
  f.handleActivity(requestCode, resultCode, data);
};



public String[] listFiles(String s1) {
  String  []s = null;
  String path = s1;
  println("Files", "Path: " + path);
  File directory = new File(path);
  File[] files = directory.listFiles();
  if (files!=null) {
    s = new String [files.length];
    println("Files", "Size: "+ files.length);
    for (int i = 0; i < files.length; i++)
    {
      s[i] = files[i].getName();
      Files.add(s[i]);
      filterAll(s[i]);

      println("Files", "FileName: " + files[i].getName());
    }
  }
  //println("Images", images.size());
  println("text", textFiles.size());
  //println("Audio", audioFiles.size());
  //println("Other", otherFiles.size());
  return s;
};



public class Permission {

  PApplet parent;
  String p;

  public Permission(PApplet pParent, String permissionName) {
    parent = pParent;
    p = permissionName;
    parent.requestPermission("android.permission."+permissionName, "onPermissionResult", this);
  };

  public void onPermissionResult(boolean granted) {
    if (!granted) {
      PApplet.println("User did not grant", p, "permission.", p, "is disabled.");
    }
  };
};

The bms library already includes a listFiles method so adding one to your sketch might cause conflicts, I was only showing you what it contains so you know the names of the arraylists, also the bms already handles the file read write permissions you don’t need to add it to the sketch.

Thanks. Keeping only the first part of the sketch solves indeed the problems. When I run the sketch on the phone I can easily find the the txt file which is located on the SD external storage /games/data/test.txt but I cannot select the file (it is greyed).

on the sketch console the following message is generated
Bms paths: /storage/emulated/0 /data/user/0/processing.test.test_paul02/files /data/user/0/processing.test.test_paul02/files/data
WRITE_EXTERNAL_STORAGE

marc

That’s because you also have folder set to true. You can only do one or the other, however if both are true it will first attempt to locate a folder. So pointing to a file won’t work.

I commented out the f.folder = true; so that only f.file = true but the problem remains (the file is still grey)

We’re you prompted for permissions when you loaded the sketch. The permissions still require you to set the request in processing, via the sketch permissions menu in the processing file bar.

Which were done already from the beginning.