├── .classpath
├── .project
├── .settings
└── org.eclipse.jdt.core.prefs
├── AndroidManifest.xml
├── README.md
├── project.properties
├── res
├── drawable-hdpi
│ └── ic_launcher.png
├── drawable-ldpi
│ ├── dir_up.png
│ ├── file_icon.png
│ ├── folder_icon.png
│ ├── folder_icon_light.png
│ └── ic_launcher.png
├── drawable-mdpi
│ └── ic_launcher.png
├── drawable-xhdpi
│ └── ic_launcher.png
├── layout
│ ├── main.xml
│ └── ua_com_vassiliev_filebrowser_layout.xml
└── values
│ └── strings.xml
└── src
└── ua
└── com
└── vassiliev
└── androidfilebrowser
├── AndroidFileBrowserExampleActivity.java
└── FileBrowserActivity.java
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | AndroidFileBrowser
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
3 | org.eclipse.jdt.core.compiler.compliance=1.5
4 | org.eclipse.jdt.core.compiler.source=1.5
5 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
12 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | AndroidFileBrowser
2 | ==================
3 |
4 | Provides an Activity, which can be used to select files/folders from the application.
5 | This project is based on the Manish Burman's Android-File-Explore project (https://github.com/mburman/Android-File-Explore), but is heavily rewritten.
6 |
7 | And example Eclipse project is included.
8 |
9 | To use the component in your project, you would need to copy the following (to the same folders of your project):
10 | 1. ua\com\vassiliev\androidfilebrowser\FileBrowserActivity.java from src folder
11 | 2. a. folder_icon_light.png
12 | b. dir_up.png
13 | c. file_icon.png
14 | d. folder_icon.png all from res\drawable-ldpi
15 | 3. res\layout\ua_com_vassiliev_filebrowser_layout.xml
16 |
17 | Change line 37 (import of ua.com.vassiliev.androidfilebrowser.R) to the R file of your project, so resources you copied would be available for the FileBrowser.
18 |
19 | To call the activity you do it as alwasy (see AndroidFileBrowserExampleActivity.java):
20 | ```
21 | Intent fileExploreIntent = new Intent(
22 | ua.com.vassiliev.androidfilebrowser.FileBrowserActivity.INTENT_ACTION_SELECT_DIR,
23 | null,
24 | activityForButton,
25 | ua.com.vassiliev.androidfilebrowser.FileBrowserActivity.class
26 | );
27 | // fileExploreIntent.putExtra(
28 | // ua.com.vassiliev.androidfilebrowser.FileBrowserActivity.startDirectoryParameter,
29 | // "/sdcard"
30 | // );//Here you can add optional start directory parameter, and file browser will start from that directory.
31 | startActivityForResult(
32 | fileExploreIntent,
33 | REQUEST_CODE_PICK_FILE_TO_SAVE_INTERNAL
34 | );
35 | ```
36 |
37 | To get result overrider onActivityResult method of calling Activity for example (from AndroidFileBrowserExampleActivity.java):
38 | ```
39 | @Override
40 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
41 | // TODO Auto-generated method stub
42 | if (requestCode == REQUEST_CODE_PICK_FILE_TO_SAVE_INTERNAL) {
43 | if(resultCode == this.RESULT_OK) {
44 | String newDir = data.getStringExtra(
45 | ua.com.vassiliev.androidfilebrowser.FileBrowserActivity.returnDirectoryParameter);
46 | Toast.makeText(
47 | this,
48 | "Received path from file browser:"+newDir,
49 | Toast.LENGTH_LONG
50 | ).show();
51 | } else {//if(resultCode == this.RESULT_OK) {
52 | Toast.makeText(
53 | this,
54 | "Received NO result from file browser",
55 | Toast.LENGTH_LONG)
56 | .show();
57 | }//END } else {//if(resultCode == this.RESULT_OK) {
58 | }//if (requestCode == REQUEST_CODE_PICK_FILE_TO_SAVE_INTERNAL) {
59 | super.onActivityResult(requestCode, resultCode, data);
60 | }
61 | ```
62 |
63 | Features
64 | At the moment only pick directory activity is provided, though more options are planned to be added in the future.
65 |
66 | Sometimes it is necessary to run Project/Clean for both this project and project(s) which rely on this to regenerate correct files/jars.
67 |
68 | License
69 | Licensed under the Apache License, Version 2.0 (the "License");
70 | you may not use this file except in compliance with the License.
71 | You may obtain a copy of the License at
72 |
73 | http://www.apache.org/licenses/LICENSE-2.0
74 |
75 | Unless required by applicable law or agreed to in writing, software
76 | distributed under the License is distributed on an "AS IS" BASIS,
77 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
78 | See the License for the specific language governing permissions and
79 | limitations under the License.
80 |
81 | Thanks.
82 | This project is inspired and initially based on the project of Manish Burman - https://github.com/mburman/Android-File-Explore.
83 |
84 |
85 |
86 |
87 | [//]: <> (Author SHA-512: c46c48ddaccc53835237b551df240c1dc51ca78911fdec845481c04bb2bb438b71ed15431131850dd2654a136047dbe3129c728d4148f971d3bc0d7568124a86)
--------------------------------------------------------------------------------
/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-8
15 | android.library=true
16 |
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vaal12/AndroidFileBrowser/1e31e1506185be317be140ed569696af6241d6e9/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/dir_up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vaal12/AndroidFileBrowser/1e31e1506185be317be140ed569696af6241d6e9/res/drawable-ldpi/dir_up.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/file_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vaal12/AndroidFileBrowser/1e31e1506185be317be140ed569696af6241d6e9/res/drawable-ldpi/file_icon.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/folder_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vaal12/AndroidFileBrowser/1e31e1506185be317be140ed569696af6241d6e9/res/drawable-ldpi/folder_icon.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/folder_icon_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vaal12/AndroidFileBrowser/1e31e1506185be317be140ed569696af6241d6e9/res/drawable-ldpi/folder_icon_light.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vaal12/AndroidFileBrowser/1e31e1506185be317be140ed569696af6241d6e9/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vaal12/AndroidFileBrowser/1e31e1506185be317be140ed569696af6241d6e9/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vaal12/AndroidFileBrowser/1e31e1506185be317be140ed569696af6241d6e9/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
21 |
22 |
23 |
24 |
31 |
32 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/res/layout/ua_com_vassiliev_filebrowser_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
19 |
20 |
27 |
28 |
36 |
37 |
47 |
48 |
49 |
57 |
58 |
68 |
69 |
70 |
71 |
76 |
77 |
83 |
84 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | AndroidFileBrowserExampleActivity
5 | Android File Browser Example
6 |
7 |
--------------------------------------------------------------------------------
/src/ua/com/vassiliev/androidfilebrowser/AndroidFileBrowserExampleActivity.java:
--------------------------------------------------------------------------------
1 | package ua.com.vassiliev.androidfilebrowser;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | //import android.os.Environment;
7 | import android.util.Log;
8 | import android.view.View;
9 | import android.widget.Button;
10 | import android.widget.Toast;
11 |
12 | public class AndroidFileBrowserExampleActivity extends Activity {
13 | /** Called when the activity is first created. */
14 | private final String LOGTAG = "AndroidFileBrowserExampleActivity";
15 |
16 | private final int REQUEST_CODE_PICK_DIR = 1;
17 | private final int REQUEST_CODE_PICK_FILE = 2;
18 | //Arbitrary constant to discriminate against values returned to onActivityResult
19 | // as requestCode
20 | @Override
21 | public void onCreate(Bundle savedInstanceState) {
22 | super.onCreate(savedInstanceState);
23 |
24 | setContentView(R.layout.main);
25 |
26 | final Activity activityForButton = this;
27 |
28 | final Button startBrowserButton = (Button) findViewById(R.id.startFileBrowserButtonID);
29 |
30 | startBrowserButton.setOnClickListener(new View.OnClickListener() {
31 | public void onClick(View v) {
32 | Log.d(LOGTAG, "Start browsing button pressed");
33 | Intent fileExploreIntent = new Intent(
34 | ua.com.vassiliev.androidfilebrowser.FileBrowserActivity.INTENT_ACTION_SELECT_DIR,
35 | null,
36 | activityForButton,
37 | ua.com.vassiliev.androidfilebrowser.FileBrowserActivity.class
38 | );
39 | //If the parameter below is not provided the Activity will try to start from sdcard(external storage),
40 | // if fails, then will start from roor "/"
41 | // Do not use "/sdcard" instead as base address for sdcard use Environment.getExternalStorageDirectory()
42 | // fileExploreIntent.putExtra(
43 | // ua.com.vassiliev.androidfilebrowser.FileBrowserActivity.startDirectoryParameter,
44 | // "/sdcard"
45 | // );
46 | startActivityForResult(
47 | fileExploreIntent,
48 | REQUEST_CODE_PICK_DIR
49 | );
50 | }//public void onClick(View v) {
51 | });//startBrowserButton.setOnClickListener(new View.OnClickListener() {
52 |
53 | final Button startBrowser4FileButton = (Button) findViewById(R.id.startFileBrowser4FileButtonID);
54 | startBrowser4FileButton.setOnClickListener(new View.OnClickListener() {
55 | public void onClick(View v) {
56 | Log.d(LOGTAG, "StartFileBrowser4File button pressed");
57 | Intent fileExploreIntent = new Intent(
58 | ua.com.vassiliev.androidfilebrowser.FileBrowserActivity.INTENT_ACTION_SELECT_FILE,
59 | null,
60 | activityForButton,
61 | ua.com.vassiliev.androidfilebrowser.FileBrowserActivity.class
62 | );
63 | // fileExploreIntent.putExtra(
64 | // ua.com.vassiliev.androidfilebrowser.FileBrowserActivity.startDirectoryParameter,
65 | // "/sdcard"
66 | // );
67 | startActivityForResult(
68 | fileExploreIntent,
69 | REQUEST_CODE_PICK_FILE
70 | );
71 | }//public void onClick(View v) {
72 | });
73 |
74 | final Button start4FileHideNonReadButton =
75 | (Button) findViewById(R.id.startBrowse4FileHideNonReadButtonID);
76 | start4FileHideNonReadButton.setOnClickListener(new View.OnClickListener() {
77 | public void onClick(View v) {
78 | Log.d(LOGTAG, "StartFileBrowser4File button pressed");
79 | Intent fileExploreIntent = new Intent(
80 | ua.com.vassiliev.androidfilebrowser.FileBrowserActivity.INTENT_ACTION_SELECT_FILE,
81 | null,
82 | activityForButton,
83 | ua.com.vassiliev.androidfilebrowser.FileBrowserActivity.class
84 | );
85 | fileExploreIntent.putExtra(
86 | ua.com.vassiliev.androidfilebrowser.FileBrowserActivity.showCannotReadParameter,
87 | false);
88 | startActivityForResult(
89 | fileExploreIntent,
90 | REQUEST_CODE_PICK_FILE
91 | );
92 | }//public void onClick(View v) {
93 | });//start4FileHideNonReadButton.setOnClickListener(new View.OnClickListener() {
94 |
95 | }//public void onCreate(Bundle savedInstanceState) {
96 |
97 | @Override
98 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
99 | if (requestCode == REQUEST_CODE_PICK_DIR) {
100 | if(resultCode == RESULT_OK) {
101 | String newDir = data.getStringExtra(
102 | ua.com.vassiliev.androidfilebrowser.FileBrowserActivity.returnDirectoryParameter);
103 | Toast.makeText(
104 | this,
105 | "Received DIRECTORY path from file browser:\n"+newDir,
106 | Toast.LENGTH_LONG).show();
107 |
108 | } else {//if(resultCode == this.RESULT_OK) {
109 | Toast.makeText(
110 | this,
111 | "Received NO result from file browser",
112 | Toast.LENGTH_LONG).show();
113 | }//END } else {//if(resultCode == this.RESULT_OK) {
114 | }//if (requestCode == REQUEST_CODE_PICK_DIR) {
115 |
116 | if (requestCode == REQUEST_CODE_PICK_FILE) {
117 | if(resultCode == RESULT_OK) {
118 | String newFile = data.getStringExtra(
119 | ua.com.vassiliev.androidfilebrowser.FileBrowserActivity.returnFileParameter);
120 | Toast.makeText(
121 | this,
122 | "Received FILE path from file browser:\n"+newFile,
123 | Toast.LENGTH_LONG).show();
124 |
125 | } else {//if(resultCode == this.RESULT_OK) {
126 | Toast.makeText(
127 | this,
128 | "Received NO result from file browser",
129 | Toast.LENGTH_LONG).show();
130 | }//END } else {//if(resultCode == this.RESULT_OK) {
131 | }//if (requestCode == REQUEST_CODE_PICK_FILE) {
132 |
133 |
134 |
135 | super.onActivityResult(requestCode, resultCode, data);
136 | }
137 | }
--------------------------------------------------------------------------------
/src/ua/com/vassiliev/androidfilebrowser/FileBrowserActivity.java:
--------------------------------------------------------------------------------
1 | package ua.com.vassiliev.androidfilebrowser;
2 |
3 | //Heavily based on code from
4 | //https://github.com/mburman/Android-File-Explore
5 | // Version of Aug 13, 2011
6 | //Also contributed:
7 | // Sugan Krishnan (https://github.com/rgksugan) - Jan 2013.
8 | //
9 |
10 | //Project type now is Android library:
11 | // http://developer.android.com/guide/developing/projects/projects-eclipse.html#ReferencingLibraryProject
12 |
13 | //General Java imports
14 | import java.io.File;
15 | import java.io.FilenameFilter;
16 | import java.util.ArrayList;
17 | import java.util.Comparator;
18 | import java.util.List;
19 | import java.util.Collections;
20 |
21 | //Android imports
22 | import android.app.Activity;
23 | import android.content.Intent;
24 | import android.content.res.Configuration;
25 | import android.graphics.Color;
26 | import android.os.Bundle;
27 | import android.os.Environment;
28 | import android.os.StatFs;
29 | import android.util.Log;
30 | import android.view.View.OnClickListener;
31 | import android.view.ViewGroup.LayoutParams;
32 | import android.view.*;
33 | import android.widget.*;
34 |
35 | //Import of resources file for file browser
36 | import ua.com.vassiliev.androidfilebrowser.R;
37 |
38 | public class FileBrowserActivity extends Activity {
39 | // Intent Action Constants
40 | public static final String INTENT_ACTION_SELECT_DIR = "ua.com.vassiliev.androidfilebrowser.SELECT_DIRECTORY_ACTION";
41 | public static final String INTENT_ACTION_SELECT_FILE = "ua.com.vassiliev.androidfilebrowser.SELECT_FILE_ACTION";
42 |
43 | // Intent parameters names constants
44 | public static final String startDirectoryParameter = "ua.com.vassiliev.androidfilebrowser.directoryPath";
45 | public static final String returnDirectoryParameter = "ua.com.vassiliev.androidfilebrowser.directoryPathRet";
46 | public static final String returnFileParameter = "ua.com.vassiliev.androidfilebrowser.filePathRet";
47 | public static final String showCannotReadParameter = "ua.com.vassiliev.androidfilebrowser.showCannotRead";
48 | public static final String filterExtension = "ua.com.vassiliev.androidfilebrowser.filterExtension";
49 |
50 | // Stores names of traversed directories
51 | ArrayList pathDirsList = new ArrayList();
52 |
53 | // Check if the first level of the directory structure is the one showing
54 | // private Boolean firstLvl = true;
55 |
56 | private static final String LOGTAG = "F_PATH";
57 |
58 | private List- fileList = new ArrayList
- ();
59 | private File path = null;
60 | private String chosenFile;
61 | // private static final int DIALOG_LOAD_FILE = 1000;
62 |
63 | ArrayAdapter
- adapter;
64 |
65 | private boolean showHiddenFilesAndDirs = true;
66 |
67 | private boolean directoryShownIsEmpty = false;
68 |
69 | private String filterFileExtension = null;
70 |
71 | // Action constants
72 | private static int currentAction = -1;
73 | private static final int SELECT_DIRECTORY = 1;
74 | private static final int SELECT_FILE = 2;
75 |
76 | @Override
77 | public void onCreate(Bundle savedInstanceState) {
78 | super.onCreate(savedInstanceState);
79 | // In case of
80 | // ua.com.vassiliev.androidfilebrowser.SELECT_DIRECTORY_ACTION
81 | // Expects com.mburman.fileexplore.directoryPath parameter to
82 | // point to the start folder.
83 | // If empty or null, will start from SDcard root.
84 | setContentView(R.layout.ua_com_vassiliev_filebrowser_layout);
85 |
86 | // Set action for this activity
87 | Intent thisInt = this.getIntent();
88 | currentAction = SELECT_DIRECTORY;// This would be a default action in
89 | // case not set by intent
90 | if (thisInt.getAction().equalsIgnoreCase(INTENT_ACTION_SELECT_FILE)) {
91 | Log.d(LOGTAG, "SELECT ACTION - SELECT FILE");
92 | currentAction = SELECT_FILE;
93 | }
94 |
95 | showHiddenFilesAndDirs = thisInt.getBooleanExtra(
96 | showCannotReadParameter, true);
97 |
98 | filterFileExtension = thisInt.getStringExtra(filterExtension);
99 |
100 | setInitialDirectory();
101 |
102 | parseDirectoryPath();
103 | loadFileList();
104 | this.createFileListAdapter();
105 | this.initializeButtons();
106 | this.initializeFileListView();
107 | updateCurrentDirectoryTextView();
108 | Log.d(LOGTAG, path.getAbsolutePath());
109 | }
110 |
111 | private void setInitialDirectory() {
112 | Intent thisInt = this.getIntent();
113 | String requestedStartDir = thisInt
114 | .getStringExtra(startDirectoryParameter);
115 |
116 | if (requestedStartDir != null && requestedStartDir.length() > 0) {// if(requestedStartDir!=null
117 | File tempFile = new File(requestedStartDir);
118 | if (tempFile.isDirectory())
119 | this.path = tempFile;
120 | }// if(requestedStartDir!=null
121 |
122 | if (this.path == null) {// No or invalid directory supplied in intent
123 | // parameter
124 | if (Environment.getExternalStorageDirectory().isDirectory()
125 | && Environment.getExternalStorageDirectory().canRead())
126 | path = Environment.getExternalStorageDirectory();
127 | else
128 | path = new File("/");
129 | }// if(this.path==null) {//No or invalid directory supplied in intent
130 | // parameter
131 | }// private void setInitialDirectory() {
132 |
133 | private void parseDirectoryPath() {
134 | pathDirsList.clear();
135 | String pathString = path.getAbsolutePath();
136 | String[] parts = pathString.split("/");
137 | int i = 0;
138 | while (i < parts.length) {
139 | pathDirsList.add(parts[i]);
140 | i++;
141 | }
142 | }
143 |
144 | private void initializeButtons() {
145 | Button upDirButton = (Button) this.findViewById(R.id.upDirectoryButton);
146 | upDirButton.setOnClickListener(new OnClickListener() {
147 | public void onClick(View v) {
148 | Log.d(LOGTAG, "onclick for upDirButton");
149 | loadDirectoryUp();
150 | loadFileList();
151 | adapter.notifyDataSetChanged();
152 | updateCurrentDirectoryTextView();
153 | }
154 | });// upDirButton.setOnClickListener(
155 |
156 | Button selectFolderButton = (Button) this
157 | .findViewById(R.id.selectCurrentDirectoryButton);
158 | if (currentAction == SELECT_DIRECTORY) {
159 | selectFolderButton.setOnClickListener(new OnClickListener() {
160 | public void onClick(View v) {
161 | Log.d(LOGTAG, "onclick for selectFolderButton");
162 | returnDirectoryFinishActivity();
163 | }
164 | });
165 | } else {// if(currentAction == this.SELECT_DIRECTORY) {
166 | selectFolderButton.setVisibility(View.GONE);
167 | }// } else {//if(currentAction == this.SELECT_DIRECTORY) {
168 | }// private void initializeButtons() {
169 |
170 | private void loadDirectoryUp() {
171 | // present directory removed from list
172 | String s = pathDirsList.remove(pathDirsList.size() - 1);
173 | // path modified to exclude present directory
174 | path = new File(path.toString().substring(0,
175 | path.toString().lastIndexOf(s)));
176 | fileList.clear();
177 | }
178 |
179 | private void updateCurrentDirectoryTextView() {
180 | int i = 0;
181 | String curDirString = "";
182 | while (i < pathDirsList.size()) {
183 | curDirString += pathDirsList.get(i) + "/";
184 | i++;
185 | }
186 | if (pathDirsList.size() == 0) {
187 | ((Button) this.findViewById(R.id.upDirectoryButton))
188 | .setEnabled(false);
189 | curDirString = "/";
190 | } else
191 | ((Button) this.findViewById(R.id.upDirectoryButton))
192 | .setEnabled(true);
193 | long freeSpace = getFreeSpace(curDirString);
194 | String formattedSpaceString = formatBytes(freeSpace);
195 | if (freeSpace == 0) {
196 | Log.d(LOGTAG, "NO FREE SPACE");
197 | File currentDir = new File(curDirString);
198 | if(!currentDir.canWrite())
199 | formattedSpaceString = "NON Writable";
200 | }
201 |
202 | ((Button) this.findViewById(R.id.selectCurrentDirectoryButton))
203 | .setText("Select\n[" + formattedSpaceString
204 | + "]");
205 |
206 | ((TextView) this.findViewById(R.id.currentDirectoryTextView))
207 | .setText("Current directory: " + curDirString);
208 | }// END private void updateCurrentDirectoryTextView() {
209 |
210 | private void showToast(String message) {
211 | Toast.makeText(this, message, Toast.LENGTH_LONG).show();
212 | }
213 |
214 | private void initializeFileListView() {
215 | ListView lView = (ListView) this.findViewById(R.id.fileListView);
216 | lView.setBackgroundColor(Color.LTGRAY);
217 | LinearLayout.LayoutParams lParam = new LinearLayout.LayoutParams(
218 | LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
219 | lParam.setMargins(15, 5, 15, 5);
220 | lView.setAdapter(this.adapter);
221 | lView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
222 | public void onItemClick(AdapterView> parent, View view,
223 | int position, long id) {
224 | chosenFile = fileList.get(position).file;
225 | File sel = new File(path + "/" + chosenFile);
226 | Log.d(LOGTAG, "Clicked:" + chosenFile);
227 | if (sel.isDirectory()) {
228 | if (sel.canRead()) {
229 | // Adds chosen directory to list
230 | pathDirsList.add(chosenFile);
231 | path = new File(sel + "");
232 | Log.d(LOGTAG, "Just reloading the list");
233 | loadFileList();
234 | adapter.notifyDataSetChanged();
235 | updateCurrentDirectoryTextView();
236 | Log.d(LOGTAG, path.getAbsolutePath());
237 | } else {// if(sel.canRead()) {
238 | showToast("Path does not exist or cannot be read");
239 | }// } else {//if(sel.canRead()) {
240 | }// if (sel.isDirectory()) {
241 | // File picked or an empty directory message clicked
242 | else {// if (sel.isDirectory()) {
243 | Log.d(LOGTAG, "item clicked");
244 | if (!directoryShownIsEmpty) {
245 | Log.d(LOGTAG, "File selected:" + chosenFile);
246 | returnFileFinishActivity(sel.getAbsolutePath());
247 | }
248 | }// else {//if (sel.isDirectory()) {
249 | }// public void onClick(DialogInterface dialog, int which) {
250 | });// lView.setOnClickListener(
251 | }// private void initializeFileListView() {
252 |
253 | private void returnDirectoryFinishActivity() {
254 | Intent retIntent = new Intent();
255 | retIntent.putExtra(returnDirectoryParameter, path.getAbsolutePath());
256 | this.setResult(RESULT_OK, retIntent);
257 | this.finish();
258 | }// END private void returnDirectoryFinishActivity() {
259 |
260 | private void returnFileFinishActivity(String filePath) {
261 | Intent retIntent = new Intent();
262 | retIntent.putExtra(returnFileParameter, filePath);
263 | this.setResult(RESULT_OK, retIntent);
264 | this.finish();
265 | }// END private void returnDirectoryFinishActivity() {
266 |
267 | private void loadFileList() {
268 | try {
269 | path.mkdirs();
270 | } catch (SecurityException e) {
271 | Log.e(LOGTAG, "unable to write on the sd card ");
272 | }
273 | fileList.clear();
274 |
275 | if (path.exists() && path.canRead()) {
276 | FilenameFilter filter = new FilenameFilter() {
277 | public boolean accept(File dir, String filename) {
278 | File sel = new File(dir, filename);
279 | boolean showReadableFile = showHiddenFilesAndDirs
280 | || sel.canRead();
281 | // Filters based on whether the file is hidden or not
282 | if (currentAction == SELECT_DIRECTORY) {
283 | return (sel.isDirectory() && showReadableFile);
284 | }
285 | if (currentAction == SELECT_FILE) {
286 |
287 | // If it is a file check the extension if provided
288 | if (sel.isFile() && filterFileExtension != null) {
289 | return (showReadableFile && sel.getName().endsWith(
290 | filterFileExtension));
291 | }
292 | return (showReadableFile);
293 | }
294 | return true;
295 | }// public boolean accept(File dir, String filename) {
296 | };// FilenameFilter filter = new FilenameFilter() {
297 |
298 | String[] fList = path.list(filter);
299 | this.directoryShownIsEmpty = false;
300 | for (int i = 0; i < fList.length; i++) {
301 | // Convert into file path
302 | File sel = new File(path, fList[i]);
303 | Log.d(LOGTAG,
304 | "File:" + fList[i] + " readable:"
305 | + (Boolean.valueOf(sel.canRead())).toString());
306 | int drawableID = R.drawable.file_icon;
307 | boolean canRead = sel.canRead();
308 | // Set drawables
309 | if (sel.isDirectory()) {
310 | if (canRead) {
311 | drawableID = R.drawable.folder_icon;
312 | } else {
313 | drawableID = R.drawable.folder_icon_light;
314 | }
315 | }
316 | fileList.add(i, new Item(fList[i], drawableID, canRead));
317 | }// for (int i = 0; i < fList.length; i++) {
318 | if (fileList.size() == 0) {
319 | // Log.d(LOGTAG, "This directory is empty");
320 | this.directoryShownIsEmpty = true;
321 | fileList.add(0, new Item("Directory is empty", -1, true));
322 | } else {// sort non empty list
323 | Collections.sort(fileList, new ItemFileNameComparator());
324 | }
325 | } else {
326 | Log.e(LOGTAG, "path does not exist or cannot be read");
327 | }
328 | // Log.d(TAG, "loadFileList finished");
329 | }// private void loadFileList() {
330 |
331 | private void createFileListAdapter() {
332 | adapter = new ArrayAdapter
- (this,
333 | android.R.layout.select_dialog_item, android.R.id.text1,
334 | fileList) {
335 | @Override
336 | public View getView(int position, View convertView, ViewGroup parent) {
337 | // creates view
338 | View view = super.getView(position, convertView, parent);
339 | TextView textView = (TextView) view
340 | .findViewById(android.R.id.text1);
341 | // put the image on the text view
342 | int drawableID = 0;
343 | if (fileList.get(position).icon != -1) {
344 | // If icon == -1, then directory is empty
345 | drawableID = fileList.get(position).icon;
346 | }
347 | textView.setCompoundDrawablesWithIntrinsicBounds(drawableID, 0,
348 | 0, 0);
349 |
350 | textView.setEllipsize(null);
351 |
352 | // add margin between image and text (support various screen
353 | // densities)
354 | // int dp5 = (int) (5 *
355 | // getResources().getDisplayMetrics().density + 0.5f);
356 | int dp3 = (int) (3 * getResources().getDisplayMetrics().density + 0.5f);
357 | // TODO: change next line for empty directory, so text will be
358 | // centered
359 | textView.setCompoundDrawablePadding(dp3);
360 | textView.setBackgroundColor(Color.LTGRAY);
361 | return view;
362 | }// public View getView(int position, View convertView, ViewGroup
363 | };// adapter = new ArrayAdapter
- (this,
364 | }// private createFileListAdapter(){
365 |
366 | private class Item {
367 | public String file;
368 | public int icon;
369 | public boolean canRead;
370 |
371 | public Item(String file, Integer icon, boolean canRead) {
372 | this.file = file;
373 | this.icon = icon;
374 | }
375 |
376 | @Override
377 | public String toString() {
378 | return file;
379 | }
380 | }// END private class Item {
381 |
382 | private class ItemFileNameComparator implements Comparator
- {
383 | public int compare(Item lhs, Item rhs) {
384 | return lhs.file.toLowerCase().compareTo(rhs.file.toLowerCase());
385 | }
386 | }
387 |
388 | public void onConfigurationChanged(Configuration newConfig) {
389 | super.onConfigurationChanged(newConfig);
390 | if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
391 | Log.d(LOGTAG, "ORIENTATION_LANDSCAPE");
392 | } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
393 | Log.d(LOGTAG, "ORIENTATION_PORTRAIT");
394 | }
395 | // Layout apparently changes itself, only have to provide good onMeasure
396 | // in custom components
397 | // TODO: check with keyboard
398 | // if(newConfig.keyboard == Configuration.KEYBOARDHIDDEN_YES)
399 | }// END public void onConfigurationChanged(Configuration newConfig) {
400 |
401 | public static long getFreeSpace(String path) {
402 | StatFs stat = new StatFs(path);
403 | long availSize = (long) stat.getAvailableBlocks()
404 | * (long) stat.getBlockSize();
405 | return availSize;
406 | }// END public static long getFreeSpace(String path) {
407 |
408 | public static String formatBytes(long bytes) {
409 | // TODO: add flag to which part is needed (e.g. GB, MB, KB or bytes)
410 | String retStr = "";
411 | // One binary gigabyte equals 1,073,741,824 bytes.
412 | if (bytes > 1073741824) {// Add GB
413 | long gbs = bytes / 1073741824;
414 | retStr += (new Long(gbs)).toString() + "GB ";
415 | bytes = bytes - (gbs * 1073741824);
416 | }
417 | // One MB - 1048576 bytes
418 | if (bytes > 1048576) {// Add GB
419 | long mbs = bytes / 1048576;
420 | retStr += (new Long(mbs)).toString() + "MB ";
421 | bytes = bytes - (mbs * 1048576);
422 | }
423 | if (bytes > 1024) {
424 | long kbs = bytes / 1024;
425 | retStr += (new Long(kbs)).toString() + "KB";
426 | bytes = bytes - (kbs * 1024);
427 | } else
428 | retStr += (new Long(bytes)).toString() + " bytes";
429 | return retStr;
430 | }// public static String formatBytes(long bytes){
431 |
432 | }// END public class FileBrowserActivity extends Activity {
433 |
--------------------------------------------------------------------------------