• (3 Pages)
  • +
  • 1
  • 2
  • 3

Creating Simple File Chooser

#1 H3R3T1C  Icon User is offline

  • Android Expert
  • member icon

Reputation: 278
  • View blog
  • Posts: 757
  • Joined: 30-March 07

Posted 12 September 2010 - 12:28 AM

Today I'm going to be showing how to create a simple file chooser for selecting files off the SD Card!
This is what the result is goning to look like:
Posted Image
Stating this tutorial assumes that you already have Eclipse and the Android SDK installed on your computer.
Ok well here we go!
To start off we first need to create a new project...
In eclipse do File -> New -> Android Project
Name the project File Chooser.
Select the build target 1.6
For application name put File Chooser
For package name put whatever you like. I'm going to name my package com.h3r3t1c.filechooser
Make sure Create Activity is checked and type in FileChooser
Min SDK Version is 4
Now just select ok.

Before we start coding we need to set the permission so we can read and write file on the SD Card so to do this open the AndroidManifest.xml and click on the permissions tab. Click the add button and select Uses Permission.
In the drop down menu select android.permission.WRITE_EXTERNAL_STORAGE and click save.

Now to start the coding!
Expand src and open the file FileChooser.java
The first thing you'll notice is that Eclipse auto generated some code for us. This is good but we need to change a few things. First thing we need to change is activity. Rename extends Activity to extends ListActivity. Next we need to remove setContentView(R.layout.main);.
You should now have something that looks like this:
public class FileChooser extends ListActivity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
    }
}


Ok the next thing were going to want to do is to start adding our methods.
The first method were going to create is called fill. The purpose of fill is to get all the files and folder for the current directory were in.
In your FileChooser class create the method:
private void fill(File f)
{

}


Now that we have that created were going to want to have it called right away when the activity starts so to do this first we need to create a current directory variable. Above the onCreate() method add this:
private File currentDir;
Note: your going to have to import File!
Now going back to the onCreate() method we need to initialize currentDir to the root of the SD Card so to do this add this:
currentDir = new File("/sdcard/)

now under that call the fill method like so:
 fill(currentDir);

Right now our class should look like this :
public class FileChooser extends ListActivity {
    private File currentDir;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        currentDir = new File("/sdcard/");
        fill(currentDir);
    }
    private void fill(File f)
    {
        
    }
}

Before we move onto adding the code to we need to create a class to hold our data were going to get from listing all the file and directories so in eclipse right click on your package and select New -> Class.
Name this class Option and select ok.
Add this code to your Option class:
public class Option implements Comparable<Option>{
    private String name;
    private String data;
    private String path;
    
    public Option(String n,String d,String p)
    {
        name = n;
        data = d;
        path = p;
    }
    public String getName()
    {
        return name;
    }
    public String getData()
    {
        return data;
    }
    public String getPath()
    {
        return path;
    }
    @Override
    public int compareTo(Option o) {
        if(this.name != null)
            return this.name.toLowerCase().compareTo(o.getName().toLowerCase()); 
        else 
            throw new IllegalArgumentException();
    }
}


Ok now that that is done go back to FileChooser.java
The fill method is going to work like this:
Were going to get an array of all the files and dirs in the current were in.
Were going to create 2 ListArrays. One for folders and one for files.
Were going to sort files and dirs into the appropriate ListArray.
Were going to sort the ListArrays alphabetically and pass to one ListArray.
Were going to pass this ListArray to our custom ArrayAdapter
So our fill method should look like this:
private void fill(File f)
    {
        File[]dirs = f.listFiles();
         this.setTitle("Current Dir: "+f.getName());
         List<Option>dir = new ArrayList<Option>();
         List<Option>fls = new ArrayList<Option>();
         try{
             for(File ff: dirs)
             {
                if(ff.isDirectory())
                    dir.add(new Option(ff.getName(),"Folder",ff.getAbsolutePath()));
                else
                {
                    fls.add(new Option(ff.getName(),"File Size: "+ff.length(),ff.getAbsolutePath()));
                }
             }
         }catch(Exception e)
         {
             
         }
         Collections.sort(dir);
         Collections.sort(fls);
         dir.addAll(fls);
         if(!f.getName().equalsIgnoreCase("sdcard"))
             dir.add(0,new Option("..","Parent Directory",f.getParent()));
    }


Now we need to make our custom ArrayAdapter
Create a new class called FileArrayAdapter.
In FileArrayAdapter have it extend ArrayAdapter<Option>, add constructor and add global variables like so:
public class FileArrayAdapter extends ArrayAdapter<Option>{

	private Context c;
	private int id;
	private List<Option>items;
	
	public FileArrayAdapter(Context context, int textViewResourceId,
			List<Option> objects) {
		super(context, textViewResourceId, objects);
		c = context;
		id = textViewResourceId;
		items = objects;
	}

}


Before we move on we now need to create a View for us to display our data!
Click New -> Android XML File
For file call it file_view.xml.
Click layout and then finish.
Replace the xml text in the file with this text:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_height="wrap_content" android:orientation="vertical" android:layout_width="fill_parent">
<TextView android:text="@+id/TextView01" android:id="@+id/TextView01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" android:textStyle="bold" android:layout_marginTop="5dip" android:layout_marginLeft="5dip"></TextView>
<TextView android:text="@+id/TextView02" android:id="@+id/TextView02" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dip"></TextView>
</LinearLayout>


Now go back to FileArrayAdaper.
Were going to do the following:
Add method to get item from a location in the List.
Override the getView() method
Using the getView() method create our custom view from the data in items and use file_view.xml to be the view.
Add this code to your FileArrayAdapter:
public Option getItem(int i)
	 {
		 return items.get(i);
	 }
	 @Override
       public View getView(int position, View convertView, ViewGroup parent) {
               View v = convertView;
               if (v == null) {
                   LayoutInflater vi = (LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                   v = vi.inflate(id, null);
               }
               final Option o = items.get(position);
               if (o != null) {
                       TextView t1 = (TextView) v.findViewById(R.id.TextView01);
                       TextView t2 = (TextView) v.findViewById(R.id.TextView02);
                       
                       if(t1!=null)
                       	t1.setText(o.getName());
                       if(t2!=null)
                       	t2.setText(o.getData());
                       
               }
               return v;
       }


Now go back to FileChooser and add the global variable private FileArrayAdapter adapter;
Now back in fill method add the following code to initialize our adapter:
adapter = new FileArrayAdapter(FileChooser.this,R.layout.file_view,dir);
		 this.setListAdapter(adapter);


At this point you should be able to test it and it should be listing all the folders and files in the root of your SD Card.
Now we need to handle users clicking on files and folders! To do this were going to override the onListItemClick method.
Add this code to your FileChooser class:
@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		// TODO Auto-generated method stub
		super.onListItemClick(l, v, position, id);
		Option o = adapter.getItem(position);
		if(o.getData().equalsIgnoreCase("folder")||o.getData().equalsIgnoreCase("parent directory")){
				currentDir = new File(o.getPath());
				fill(currentDir);
		}
	}


At this point we should now be able to move through the directories on the SD Card!
Now for our purposes the clicking of files will just show a toast message saying tha a file has been clicked but it will give you and idea of how to handle the files we click!
Create a method called onFileClick() and adding the following code:
private void onFileClick(Option o)
    {
    	Toast.makeText(this, "File Clicked: "+o.getName(), Toast.LENGTH_SHORT).show();
    }


Then go back up to the onListItemClick() and add this code:
else
		{
			onFileClick(o);
		}


The onFileClick method could be used to return the path of the file if FileChooser was called with startActivityForResult().

This is what your classes should look like in the end:
FileChooser:
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import android.app.ListActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ListView;
import android.widget.Toast;

public class FileChooser extends ListActivity {
    
    private File currentDir;
    private FileArrayAdapter adapter;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        currentDir = new File("/sdcard/");
        fill(currentDir);
    }
    private void fill(File f)
    {
        File[]dirs = f.listFiles();
         this.setTitle("Current Dir: "+f.getName());
         List<Option>dir = new ArrayList<Option>();
         List<Option>fls = new ArrayList<Option>();
         try{
             for(File ff: dirs)
             {
                if(ff.isDirectory())
                    dir.add(new Option(ff.getName(),"Folder",ff.getAbsolutePath()));
                else
                {
                    fls.add(new Option(ff.getName(),"File Size: "+ff.length(),ff.getAbsolutePath()));
                }
             }
         }catch(Exception e)
         {
             
         }
         Collections.sort(dir);
         Collections.sort(fls);
         dir.addAll(fls);
         if(!f.getName().equalsIgnoreCase("sdcard"))
             dir.add(0,new Option("..","Parent Directory",f.getParent()));
         adapter = new FileArrayAdapter(FileChooser.this,R.layout.file_view,dir);
         this.setListAdapter(adapter);
    }
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        // TODO Auto-generated method stub
        super.onListItemClick(l, v, position, id);
        Option o = adapter.getItem(position);
        if(o.getData().equalsIgnoreCase("folder")||o.getData().equalsIgnoreCase("parent directory")){
                currentDir = new File(o.getPath());
                fill(currentDir);
        }
        else
        {
            onFileClick(o);
        }
    }
    private void onFileClick(Option o)
    {
        Toast.makeText(this, "File Clicked: "+o.getName(), Toast.LENGTH_SHORT).show();
    }
}

FileArrayAdapter:

import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;


public class FileArrayAdapter extends ArrayAdapter<Option>{

    private Context c;
    private int id;
    private List<Option>items;
    
    public FileArrayAdapter(Context context, int textViewResourceId,
            List<Option> objects) {
        super(context, textViewResourceId, objects);
        c = context;
        id = textViewResourceId;
        items = objects;
    }
    public Option getItem(int i)
     {
         return items.get(i);
     }
     @Override
       public View getView(int position, View convertView, ViewGroup parent) {
               View v = convertView;
               if (v == null) {
                   LayoutInflater vi = (LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                   v = vi.inflate(id, null);
               }
               final Option o = items.get(position);
               if (o != null) {
                       TextView t1 = (TextView) v.findViewById(R.id.TextView01);
                       TextView t2 = (TextView) v.findViewById(R.id.TextView02);
                       
                       if(t1!=null)
                           t1.setText(o.getName());
                       if(t2!=null)
                           t2.setText(o.getData());
                       
               }
               return v;
       }

}


Option:

public class Option implements Comparable<Option>{
    private String name;
    private String data;
    private String path;
    
    public Option(String n,String d,String p)
    {
        name = n;
        data = d;
        path = p;
    }
    public String getName()
    {
        return name;
    }
    public String getData()
    {
        return data;
    }
    public String getPath()
    {
        return path;
    }
    @Override
    public int compareTo(Option o) {
        if(this.name != null)
            return this.name.toLowerCase().compareTo(o.getName().toLowerCase()); 
        else 
            throw new IllegalArgumentException();
    }
}


Next tutorial I will be showing how to add icons for different file types and folders :D!
The full project can be downloaded here:
http://www.sendspace.com/pro/dl/vre5ac

Is This A Good Question/Topic? 4
  • +

Replies To: Creating Simple File Chooser

#2 Atspulgs  Icon User is offline

  • D.I.C Regular

Reputation: 68
  • View blog
  • Posts: 380
  • Joined: 29-July 09

Posted 13 December 2010 - 09:43 PM

Hey,
Not sure why, but my phone wouldnt run the app properly, as far as ive figured this out, its due to the fact that its ListActivity, the layout manager is giving out about it even when i try setting it as the main layout. Could you look into it? Not entirely sure whats going on with it. Im using Sony Ericsson x10 with 2.1 OS version.
Was This Post Helpful? 0
  • +
  • -

#3 H3R3T1C  Icon User is offline

  • Android Expert
  • member icon

Reputation: 278
  • View blog
  • Posts: 757
  • Joined: 30-March 07

Posted 13 December 2010 - 09:47 PM

Are you using my code exactly?
Also could you provide a screenshot of what is happening if possible?
Was This Post Helpful? 0
  • +
  • -

#4 Atspulgs  Icon User is offline

  • D.I.C Regular

Reputation: 68
  • View blog
  • Posts: 380
  • Joined: 29-July 09

Posted 13 December 2010 - 10:01 PM

Yeah im using yours, and yes it works, its my own fault, its cause its x10 -_- I forgot to unmount my sdcard, im sorry for disturbing. I took the phone off the pc and saw the message for preparing the sd card and then it hit me, so silly, and its not the first time either. Im sorry.
Was This Post Helpful? 0
  • +
  • -

#5 Guest_wHiTeHaT*


Reputation:

Posted 29 December 2010 - 07:42 AM

Awsome, this kinda code i was looking for.
I cant wait to see your second tutorial for this app.
I was hoping to find such code to use it as a file picker to send emails with attachments.

Greath job
Was This Post Helpful? 0

#6 Marble68  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 17-January 11

Posted 17 January 2011 - 05:19 PM

For the record - this tutorial is awesome.

Looking forward to the 2nd one with images. I'm trying to do it on my own first, so I'll be interested to see how you do it.

Thanks.
Was This Post Helpful? 0
  • +
  • -

#7 sgt.assassin  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 40
  • Joined: 18-March 11

Posted 20 March 2011 - 06:11 AM

View PostH3R3T1C, on 13 December 2010 - 09:47 PM, said:

Are you using my code exactly?
Also could you provide a screenshot of what is happening if possible?



Hi, using the code provided how would i get the sdcard files to show up with a click of a button. Im new to this programming. Therefore, using the code provided i wanted to practice how to open up your app with a button.
Was This Post Helpful? 0
  • +
  • -

#8 allygirly  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 09-April 11

Posted 09 April 2011 - 10:40 AM

Suggestion on allowing 'Back' button to go to the previous folder.

    Stack<File> dirStack = new Stack<File>();
    
    @Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		// TODO Auto-generated method stub
		super.onListItemClick(l, v, position, id);
		Option o = adapter.getItem(position);
		if(o.getData().equalsIgnoreCase("folder")){
	    		dirStack.push(currentDir);
			currentDir = new File(o.getPath());
			fill(currentDir);
		}
		else
		if(o.getData().equalsIgnoreCase("parent directory")){
			currentDir = dirStack.pop();
	    		fill(currentDir);
		}
		else
		{
			onFileClick(o);
		}
	}
    
    @Override
    public void onBackPressed() {
		if (dirStack.size() == 0)
			return;
		currentDir = dirStack.pop();
    		fill(currentDir);
    }


Was This Post Helpful? 0
  • +
  • -

#9 allygirly  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 09-April 11

Posted 09 April 2011 - 11:02 AM

   public void onBackPressed() {
		if (dirStack.size() == 0)
			{
			finish();
			return;
			}
		currentDir = dirStack.pop();
    	fill(currentDir);
    }
 


This post has been edited by allygirly: 09 April 2011 - 11:02 AM

Was This Post Helpful? 0
  • +
  • -

#10 sasykes  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 27-May 11

Posted 27 May 2011 - 01:01 PM

Thank you for taking the time to write this up and sharing the code, awesome tutorial. You rock!

~Stephen
Was This Post Helpful? 0
  • +
  • -

#11 Simphiwe  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 12-June 11

Posted 12 June 2011 - 10:13 AM

Thanks alot for tutorial man , it really helped me out.
Was This Post Helpful? 0
  • +
  • -

#12 XSYLUS  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 02-December 08

Posted 19 June 2011 - 08:35 PM

Excellent write up! :D The code works like a champ and the break down is extremely helpful. I was able to understand this enough to modify it to make it fit the needs of my app. :^: :^: (two thumbs up) ;) Thanks!
Was This Post Helpful? 0
  • +
  • -

#13 Batzi  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 02-August 11

Posted 02 August 2011 - 05:29 PM

Hello,

Thank you for the code, I've been looking for a Filechooser for Android for a while now. My question to you is as follows:

I would like to start the ListActivity through an intent. Do you know how I can do that

i = new Intent(this, Filechooser.class);
      startActivity(i);


doesn't seem to work. It's not showing anything.

Thanks again.
Was This Post Helpful? 0
  • +
  • -

#14 sanjeevdesai  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 05-October 11

Posted 05 October 2011 - 04:10 AM

Higuys m getting an error dirList.add(new Option(ff.getName(),"folder",ff.getAbsolutePath()));
in eclipse i have used exactly the above code
Was This Post Helpful? 0
  • +
  • -

#15 H3R3T1C  Icon User is offline

  • Android Expert
  • member icon

Reputation: 278
  • View blog
  • Posts: 757
  • Joined: 30-March 07

Posted 05 October 2011 - 07:52 AM

What does your error say?
Was This Post Helpful? 0
  • +
  • -

  • (3 Pages)
  • +
  • 1
  • 2
  • 3