Android native File Explorer

Following short code will open Android’s File explorer.
In this example only txt files are admitted and displayed in console, but of course you can customize for every extension as you see fit.
Important! Give read permission!


import android.content.Intent;
import android.app.Activity;
import android.os.Environment;

Activity act;
String[] lines; 

void settings() {
  fullScreen();
}

void setup() {
  background(#F9C454);
  fill(#4A3A16);
  textSize(38);
  textAlign(CENTER);
  text("Click on screen", width/2, height/3);
  act = this.getActivity();
}

void draw() {
  //if (img_loaded)  image(img, 0, 0);
}

void mousePressed() {  
  searchFile();
}

public void searchFile() {
  Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
  intent.setType("*/*");
  act.startActivityForResult(intent, 7);
}

@Override
  void onActivityResult(int requestCode, int resultCode, Intent data) {
  switch(requestCode) {
  case 7:
    if (resultCode == Activity.RESULT_OK) {
      String temp_path = data.getData().getPath();
      int last_index =  temp_path.lastIndexOf(':');
      temp_path = temp_path.substring(last_index+1);
      String path = new String(Environment.getExternalStorageDirectory().getAbsolutePath() +"/"+ temp_path);
      last_index = path.lastIndexOf('.');
      String ext = path.substring(last_index+1);
      if (ext.equals("txt") == true) {
        lines = loadStrings(path);
        printArray(lines);
      } else {
        println("Not a text file!");
      }
    }
    break;
  }
}

Lollipop 5.1

KitKat 4.4

3 Likes

This is great! But how can i open multiple files?

Hi @AniManOtaku,

you need to set an extra attribute to the intent.

intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);

To use this you need to handle the activity result a bit different than in above example. See … EXTRA_ALLOW_MULTIPLE

Cheers
— mnse

1 Like

Hi, thank you! And sorry for the late reply.

I made this:

import android.content.Intent;
import android.app.Activity;
import android.os.Environment;
import android.net.Uri;

Activity act;
String[] lines;

void settings() {
  fullScreen();
}

void setup() {
  act = this.getActivity();
}

void draw() {
  background(#F9C454);
  fill(#4A3A16);
  textSize(38);
  textAlign(CENTER);
  text("Click on screen", width/2, height/3);
}

void mousePressed() {  
  if(mouseY<height*0.8f)
  searchFile();
}

public void searchFile() {
  Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
  intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
  intent.setType("*/*");
  act.startActivityForResult(intent, 7);
}

@Override
  void onActivityResult(int requestCode, int resultCode, Intent data) {
  switch(requestCode) {
  case 7:
    if (resultCode == Activity.RESULT_OK) {
      Uri uri;
      String temp_path;
      int last_index;
      String path;
      String ext;
      String[] str;
      
      for(int i=0;i<data.getClipData().getItemCount();i++){
        uri=data.getClipData().getItemAt(i).getUri();
        temp_path=uri.getPath();
        last_index =  temp_path.lastIndexOf(':');
        temp_path = temp_path.substring(last_index+1);
        path = new String(Environment.getExternalStorageDirectory().getAbsolutePath() +"/"+ temp_path);
        last_index = path.lastIndexOf('.');
        ext = path.substring(last_index+1);
        println(path);
        if(ext.equals("txt"))
        try{
        str=loadStrings(path);
        println();
        printArray(str);
        }
        catch(Exception e){
          println(e);
        }
      }
      
    }
    break;
  }
}

And it works, but only if I open multiple files.
If I try to open only one file, the app just closes.
How can I fix it?

What Android version are you using/targeting? It’s correct to use the Intent approach but I’m not sure using getExternalStorageDirectory() will work on the most recent?

Hi @AniManOtaku,

You need to implement both ways, means
For multiple files use data.getClipData() and for single use data.getData(). So ie …

if (data.getData() != null) {
// single file, implementation as of first example from above
}
else {
// your implementation
}

Cheers
— mnse

1 Like

@AniManOtaku

OK … that’s version 8 …Oreo

What you have done will work for your phone but won’t for a new device because Google made big changes to external storage access for security reasons. Instead of being able to use getExternalStorageDirectory() etc from which you get a file path, you have to use the URI provided by your intent along with DocumentFileif necessary.

I’m not sure either whether loadStrings() will work as this takes file path and the new method provides a URI.

I posted some code a whil back and this is slightly changed version … for the way load is handled. Basically you get a byte array holding you file and you then have to do whatever… eg convert to strings etc

Import android.content.Intent;
import android.net.Uri;
import android.provider.DocumentsContract;
import android.content.Context;
import android.content.ContentResolver;
import android.app.Activity;


Context context ;
Activity activity ;
byte[] saveArray = {0, 1, 2, 3, 4, 5, 6, 7} ; //dummy data
byte[] loadArray ;
String displayText1 = "tap HERE to save";
String displayText2 = "tap HERE to load";
int REQUEST_CODE ;

void setup() {
  activity = getActivity();
  context = getContext();
  fill(255);
  textSize(width/20) ;
  textAlign(CENTER, CENTER);
}

void draw() {
  background(0);
  text(displayText1, 0, 0, width, height/2) ;
  text(displayText2, 0, height/2, width, height/2) ;
}

void mouseReleased() {
  if (mouseY <height/2) {
    //start an Intent to save
    REQUEST_CODE = 1;
    Intent saveIntent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
    saveIntent.setType("*/*");
    activity.startActivityForResult(saveIntent, REQUEST_CODE);
  } else {
    //start an Intent to load
    REQUEST_CODE = 2;
    Intent loadIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
    loadIntent.setType("*/*"); //any file type
    activity.startActivityForResult(loadIntent, REQUEST_CODE);
  }
}

@Override
  public void onActivityResult(int requestCode, int resultCode, Intent resultData) {

  if (resultCode == Activity.RESULT_OK && resultData != null) {
    ContentResolver contentResolver = context.getContentResolver();
    Uri uri = resultData.getData();


    switch (REQUEST_CODE) {
    case 1: // save file
      try {
        OutputStream os = contentResolver.openOutputStream(uri);
        os.write(saveArray);
        os.close();
        displayText1 = "File saved sccessfully" ;
        //saveArray should now be saved
      }
      catch (Exception e) {
        displayText1 = "File Save Error ..." ;
      }
      break;
    case 2:
      try { //load file
        InputStream is = contentResolver.openInputStream(uri);
       int fileSize = is.available ;
        loadArray = new byte[fileSize] ;
        for (int i=0; i<fileSize; I++) {
          loadArray[i] = (byte) is.read();
        }
        is.close();
        displayText2 = "File loaded successfully"  ;
        //do whatever you need with loadArray ....
      }
      catch (Exception e) {
        displayText2 = "File Load Error ..." ;
      }
      break;
    }
  }
}//end onActivityResult

@shedMusic
And how do I convert those bytes to strings or images or something?

Covert each byte to a character and add them together to create a string.

byte[] data .... //your loaded file

// then

String str = "";

for (int i=0; i<data.length; i++) {
  str += char(data[i]);
}