diff --git a/AwesomeScreencast/AndroidManifest.xml b/AwesomeScreencast/AndroidManifest.xml
index adae18c..d645d03 100644
--- a/AwesomeScreencast/AndroidManifest.xml
+++ b/AwesomeScreencast/AndroidManifest.xml
@@ -5,8 +5,8 @@
android:versionName="1.0" >
+ android:minSdkVersion="8"
+ android:targetSdkVersion="17" />
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-filechooser/LICENSE b/android-filechooser/LICENSE
new file mode 100755
index 0000000..530faaf
--- /dev/null
+++ b/android-filechooser/LICENSE
@@ -0,0 +1,18 @@
+Copyright (C) 2012 Hai Bison
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/android-filechooser/NOTICE b/android-filechooser/NOTICE
new file mode 100755
index 0000000..11615f1
--- /dev/null
+++ b/android-filechooser/NOTICE
@@ -0,0 +1,273 @@
+android-filechooser
+
+Version: 5.0
+
+===========
+
+Feel free to contact us at:
+ - Homepage : http://www.haibison.com
+ - E-mails :
+ + haibison.apps(@)gmail(.)com
+ + support(@)haibison(.)com
+
+Or you can join this forum for discussion, and to receive news (new version,
+bugs...), your e-mail address will be kept private:
+ - https://groups.google.com/forum/#!forum/android-filechooser
+
+And here is history:
+
++++ Version 5.0 +++
+ - Release: October 21, 2012
+
+ - We don't use Apache License 2.0 anymore. Now the library is released under
+ MIT license.
+
++++ Version 4.9 +++
+ - Release: October 20, 2012
+
+ - Improves the speed of formatting file time;
+ - Uses a unique filename of SharedPreferences instead of default application's
+ SharedPreferences;
+ - Uses Context.MODE_MULTI_PROCESS for storing global preferences;
+ - Uses a Runnable + setSelection() to select item of list view of files.
+ Because if the list view is handling data, only setSelection() might not
+ work;
+ - Updates NOTICE;
+
++++ Version 4.9 beta +++
+ - Initialize: October 12, 2012
+
++++ Version 4.8.1 +++
+ - Release: October 12, 2012
+
+ - Fixes a bug that file item does not draw properly after flinging it to delete
+ files;
+
++++ Version 4.8 +++
+ - Release: October 12, 2012
+
+ - Fixes a small bug that last location or selected file will be not pushed into
+ history;
+
++++ Version 4.7 +++
+ - Release: October 12, 2012
+
+ - All date formatting utilities were moved from /IFileAdapter to
+ /utils.DateUtils;
+ - Removes key /FileChooserActivity._UseThemeDialog;
+ - Adds options for single tapping/ double tapping to choose files;
+ - Auto remembers last location;
+ - Adds key /FileChooserActivity._SelectFile to select a specific file on
+ startup;
+ - Updates new mime types;
+ - UI for footer;
+ - Minor changes;
+
++++ Version 4.7 beta +++
+ - Initialize: October 02, 2012
+
++++ Version 4.6.2 +++
+ - Release: October 01, 2012
+
+ - Fixes: View does not reload after changing view type between list view and
+ grid view.
+
++++ Version 4.6.1 +++
+ - Release: October 01, 2012
+
+ - Fixes: View does not reload after changing view type between list view and
+ grid view.
+
++++ Version 4.6 +++
+ - Release: October 01, 2012
+
+ - Updates UI;
+ - Removes deprecated method History.push(A, A);
+ - Keeps and shows full history to the user (wherever they have been gone to);
+ - Removes button Cancel in dialogs. Users can tap Back button or touch outside
+ of the dialogs to cancel them;
+ - Moves [/]io.LocalFile to [/]io.localfile.LocalFile;
+ - Fixes:
+ + Issue #6 (thanks to @buckelieg);
+ + Issue #10;
+
++++ Version 4.6 beta +++
+ - Initialize: September 08, 2012
+
++++ Version 4.5 +++
+ - Release: September 07, 2012
+
+ - New icons for menu Home, Reload and for file types audio, image, video,
+plain text and compressed;
+
++++ Version 4.5 beta +++
+ - Initialize: August 31, 2012
+
++++ Version 4.4 +++
+ - Release: August 30, 2012
+
+ - Added languages: Spanish, Vietnamese. Special thanks to C. - a kind friend
+ who helped us translate the library into Spanish;
+
++++ Version 4.3 +++
+ - Release: August 29, 2012
+
+ - Fixed issue #2 (http://code.google.com/p/android-filechooser/issues/detail?id=2);
+ - Upgraded UI;
+ - Added history viewer;
+ - Improved some minor code;
+
++++ Version 4.3 beta +++
+ - Initialization: May 19, 2012
+
++++ Version 4.2 +++
+ - Release: May 15, 2012
+
+ - due to this bug: http://code.google.com/p/android/issues/detail?id=30622,
+ so we prefix all resource names with 'afc_';
+ - add small text view below location bar, to show current location's full name
+ if it is truncated by the view's ellipsize property;
+ - save and restore state after screen orientation changed (except selected items
+ in multi-selection mode);
+ - add menu Reload;
+ - some UI fixes/ updates;
+
++++ Version 4.2 beta +++
+ - Initialization: May 13, 2012
+
++++ Version 4.1 +++
+ - Release: May 12, 2012
+
+ - update UI messages;
+ - if the app does not have permission WRITE_EXTERNAL_STORAGE, notify user
+ when he creates or deletes folder/ file;
+ - make location bar hold buttons of directories, which user can click to
+ go to;
+
++++ Version 4.1 beta +++
+ - Initialization: May 11, 2012
+
++++ Version 4.0 - Tablet +++
+ - Release: May 11, 2012
+
+ - add Home button;
+ - add grid view/ list view mode;
+ - allow creating new directory;
+ - allow deleting a single file/ directory by flinging its name;
+ - use android-support-v13.jar:
+ + show menu items as actions from API 11 and up;
+ + support new Android layout;
+ - change to new icons;
+ - some minor changes;
+
++++ Version 4.0 beta +++
+ - Initialization: May 08, 2012
+
++++ Version 3.5 +++
+ - Release: May 01, 2012
+
+ - remove button Cancel (use default Back button of system)
+ - hello May Day :-)
+
++++ Version 3.4 +++
+ - Release: March 23, 2012
+
+ - fix serious bug: hardcode service action name of local file provider;
+ the service will be called as a remote service, which will raise
+ fatal exception if there are multiple instances of the library installed
+ on the device;
+
++++ Version 3.3 +++
+ - Release: March 22, 2012
+
+ - fix bug in LoadingDialog: if the user finishes the owner activity,
+ the application can crash if the dialog is going to show up or dismiss;
+ - improve FileChooserActivity: make its height and width always fit the
+ screen size in dialog theme;
+
++++ Version 3.2 +++
+ - Release: March 16, 2012
+
+ - add package io: IFile and LocalFile;
+ - use IFile instead of java.io.File;
+ - remove FileContainer and package bean;
+
++++ Version 3.1 +++
+ - Release: March 15, 2012
+
+ - add FileProviderService;
+
++++ Version 3.0 +++
+ - Release: March 15, 2012
+
+ - move file listing functions to external service;
+ - change project name from FileChooser to android-filechooser :-D
+ - some minor changes:
+ + UI messages;
+ + icons;
+ + make LoadingDialog use AsyncTask instead of Thread;
+ + ...
+
++++ Version 2.0 +++
+ - Release: Feb 22, 2012
+
+ - change default date format to "yyyy.MM.dd hh:mm a";
+ - try using sdcard as rootpath if it is not specified; if sdcard is not available, use "/";
+ - add sorter (by name/ size/ date);
+ - show directories' date (last modified);
+
++++ Version 1.91 +++
+ - Release: Feb 06, 2012
+
+ - Add: show file time (last modified);
+
++++ Version 1.9 +++
+ - Release: Feb 06, 2012
+
+ - Fix: crash if cast footer of listview to DataModel;
+
++++ Version 1.8.2 +++
+ - Release: Feb 06, 2012
+
+ - enable fast scroll of the list view;
+
++++ Version 1.8.1 +++
+ - Release: Feb 05, 2012
+
+ - Fix: it doesn't remember the first path (rootpath) in history;
+
++++ Version 1.8 +++
+ - Release: Feb 05, 2012
+
+ - Shows progress dialog while listing files of a directory;
+ - Adds flag max file count allowed, in case the directory has thousands of files,
+ the application can harm memory. Default value is 1,024;
+ - TODO: let the user cancel the method java.io.File.listFiles().
+ It seems this is up to Android developers :-)
+
++++ Version 1.7 +++
+ - Release: Jan 22, 2012
+
+ - add function to check if filename (in save dialog mode) is valid or not;
+ - change name FilesAdapter to FileAdapter;
+
++++ Version 1.6 +++
+ - Release: Jan 13, 2012
+
+ - check and warn user if save as filename is a directory;
+ - when finish, return some flags for further use (in case the
+ caller needs);
+
++++ Version 1.5 +++
+ - Release: Jan 13, 2012
+
+ - apply Apache License 2.0;
+ - set result code to RESULT_CANCELED when user clicks button Cancel;
+
++++ Version 1.4 +++
+ - Release: Jan 08, 2012
+
+ - first publishing;
+ - choose file(s) dialog;
+ - choose file(s) and/or directory(ies) dialog;
+ - save as dialog;
diff --git a/android-filechooser/project.properties b/android-filechooser/project.properties
new file mode 100644
index 0000000..f47ab3e
--- /dev/null
+++ b/android-filechooser/project.properties
@@ -0,0 +1,13 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-17
+android.library=true
+android.library.reference.1=../dentex.youtube.downloader.strings
diff --git a/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_gridview.png b/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_gridview.png
new file mode 100644
index 0000000..c93964e
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_gridview.png differ
diff --git a/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_home.png b/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_home.png
new file mode 100644
index 0000000..72305cb
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_home.png differ
diff --git a/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_listview.png b/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_listview.png
new file mode 100644
index 0000000..7b2e487
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_listview.png differ
diff --git a/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_reload.png b/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_reload.png
new file mode 100644
index 0000000..1ed03f0
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_reload.png differ
diff --git a/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_sort_by_date_asc.png b/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_sort_by_date_asc.png
new file mode 100644
index 0000000..60873cf
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_sort_by_date_asc.png differ
diff --git a/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_sort_by_date_desc.png b/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_sort_by_date_desc.png
new file mode 100644
index 0000000..7cebfcd
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_sort_by_date_desc.png differ
diff --git a/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_sort_by_name_asc.png b/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_sort_by_name_asc.png
new file mode 100644
index 0000000..038546d
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_sort_by_name_asc.png differ
diff --git a/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_sort_by_name_desc.png b/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_sort_by_name_desc.png
new file mode 100644
index 0000000..bad5389
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_sort_by_name_desc.png differ
diff --git a/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_sort_by_size_asc.png b/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_sort_by_size_asc.png
new file mode 100644
index 0000000..7772d62
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_sort_by_size_asc.png differ
diff --git a/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_sort_by_size_desc.png b/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_sort_by_size_desc.png
new file mode 100644
index 0000000..5497e14
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi-v11/afc_ic_menu_sort_by_size_desc.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_button_navi_left.png b/android-filechooser/res/drawable-hdpi/afc_button_navi_left.png
new file mode 100644
index 0000000..52889f6
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_button_navi_left.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_button_navi_left_disabled.png b/android-filechooser/res/drawable-hdpi/afc_button_navi_left_disabled.png
new file mode 100644
index 0000000..8e451b4
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_button_navi_left_disabled.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_button_navi_left_pressed.png b/android-filechooser/res/drawable-hdpi/afc_button_navi_left_pressed.png
new file mode 100644
index 0000000..6150fa1
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_button_navi_left_pressed.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_button_navi_right.png b/android-filechooser/res/drawable-hdpi/afc_button_navi_right.png
new file mode 100644
index 0000000..3a5c955
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_button_navi_right.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_button_navi_right_disabled.png b/android-filechooser/res/drawable-hdpi/afc_button_navi_right_disabled.png
new file mode 100644
index 0000000..72e9d89
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_button_navi_right_disabled.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_button_navi_right_pressed.png b/android-filechooser/res/drawable-hdpi/afc_button_navi_right_pressed.png
new file mode 100644
index 0000000..b8844bc
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_button_navi_right_pressed.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_button_ok_saveas.png b/android-filechooser/res/drawable-hdpi/afc_button_ok_saveas.png
new file mode 100644
index 0000000..dff2707
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_button_ok_saveas.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_button_ok_saveas_pressed.png b/android-filechooser/res/drawable-hdpi/afc_button_ok_saveas_pressed.png
new file mode 100644
index 0000000..358a571
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_button_ok_saveas_pressed.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_context_menu_item_divider.png b/android-filechooser/res/drawable-hdpi/afc_context_menu_item_divider.png
new file mode 100644
index 0000000..eba06e2
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_context_menu_item_divider.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_file.png b/android-filechooser/res/drawable-hdpi/afc_file.png
new file mode 100644
index 0000000..fcf239c
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_file.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_file_audio.png b/android-filechooser/res/drawable-hdpi/afc_file_audio.png
new file mode 100644
index 0000000..5d21334
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_file_audio.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_file_compressed.png b/android-filechooser/res/drawable-hdpi/afc_file_compressed.png
new file mode 100644
index 0000000..0fe46f3
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_file_compressed.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_file_image.png b/android-filechooser/res/drawable-hdpi/afc_file_image.png
new file mode 100644
index 0000000..ccc1140
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_file_image.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_file_plain_text.png b/android-filechooser/res/drawable-hdpi/afc_file_plain_text.png
new file mode 100644
index 0000000..fe20bb4
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_file_plain_text.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_file_video.png b/android-filechooser/res/drawable-hdpi/afc_file_video.png
new file mode 100644
index 0000000..2159688
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_file_video.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_folder.png b/android-filechooser/res/drawable-hdpi/afc_folder.png
new file mode 100644
index 0000000..202b4e5
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_folder.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_ic_menu_gridview.png b/android-filechooser/res/drawable-hdpi/afc_ic_menu_gridview.png
new file mode 100644
index 0000000..e5f007d
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_ic_menu_gridview.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_ic_menu_home.png b/android-filechooser/res/drawable-hdpi/afc_ic_menu_home.png
new file mode 100644
index 0000000..d5bf465
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_ic_menu_home.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_ic_menu_listview.png b/android-filechooser/res/drawable-hdpi/afc_ic_menu_listview.png
new file mode 100644
index 0000000..428553d
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_ic_menu_listview.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_ic_menu_reload.png b/android-filechooser/res/drawable-hdpi/afc_ic_menu_reload.png
new file mode 100644
index 0000000..04ae1db
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_ic_menu_reload.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_ic_menu_sort_by_date_asc.png b/android-filechooser/res/drawable-hdpi/afc_ic_menu_sort_by_date_asc.png
new file mode 100644
index 0000000..93cd66b
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_ic_menu_sort_by_date_asc.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_ic_menu_sort_by_date_desc.png b/android-filechooser/res/drawable-hdpi/afc_ic_menu_sort_by_date_desc.png
new file mode 100644
index 0000000..5d61618
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_ic_menu_sort_by_date_desc.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_ic_menu_sort_by_name_asc.png b/android-filechooser/res/drawable-hdpi/afc_ic_menu_sort_by_name_asc.png
new file mode 100644
index 0000000..0994e96
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_ic_menu_sort_by_name_asc.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_ic_menu_sort_by_name_desc.png b/android-filechooser/res/drawable-hdpi/afc_ic_menu_sort_by_name_desc.png
new file mode 100644
index 0000000..f3b90c5
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_ic_menu_sort_by_name_desc.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_ic_menu_sort_by_size_asc.png b/android-filechooser/res/drawable-hdpi/afc_ic_menu_sort_by_size_asc.png
new file mode 100644
index 0000000..b024864
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_ic_menu_sort_by_size_asc.png differ
diff --git a/android-filechooser/res/drawable-hdpi/afc_ic_menu_sort_by_size_desc.png b/android-filechooser/res/drawable-hdpi/afc_ic_menu_sort_by_size_desc.png
new file mode 100644
index 0000000..3fab84c
Binary files /dev/null and b/android-filechooser/res/drawable-hdpi/afc_ic_menu_sort_by_size_desc.png differ
diff --git a/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_gridview.png b/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_gridview.png
new file mode 100644
index 0000000..d65bb4e
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_gridview.png differ
diff --git a/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_home.png b/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_home.png
new file mode 100644
index 0000000..1b85f9a
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_home.png differ
diff --git a/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_listview.png b/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_listview.png
new file mode 100644
index 0000000..fc28878
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_listview.png differ
diff --git a/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_reload.png b/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_reload.png
new file mode 100644
index 0000000..16f86cf
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_reload.png differ
diff --git a/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_sort_by_date_asc.png b/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_sort_by_date_asc.png
new file mode 100644
index 0000000..0bdf02a
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_sort_by_date_asc.png differ
diff --git a/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_sort_by_date_desc.png b/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_sort_by_date_desc.png
new file mode 100644
index 0000000..d51b86b
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_sort_by_date_desc.png differ
diff --git a/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_sort_by_name_asc.png b/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_sort_by_name_asc.png
new file mode 100644
index 0000000..7dd1e11
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_sort_by_name_asc.png differ
diff --git a/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_sort_by_name_desc.png b/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_sort_by_name_desc.png
new file mode 100644
index 0000000..79838ec
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_sort_by_name_desc.png differ
diff --git a/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_sort_by_size_asc.png b/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_sort_by_size_asc.png
new file mode 100644
index 0000000..44fda63
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_sort_by_size_asc.png differ
diff --git a/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_sort_by_size_desc.png b/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_sort_by_size_desc.png
new file mode 100644
index 0000000..76c061a
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi-v11/afc_ic_menu_sort_by_size_desc.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_button_navi_left.png b/android-filechooser/res/drawable-ldpi/afc_button_navi_left.png
new file mode 100644
index 0000000..9d730f8
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_button_navi_left.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_button_navi_left_disabled.png b/android-filechooser/res/drawable-ldpi/afc_button_navi_left_disabled.png
new file mode 100644
index 0000000..33346b2
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_button_navi_left_disabled.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_button_navi_left_pressed.png b/android-filechooser/res/drawable-ldpi/afc_button_navi_left_pressed.png
new file mode 100644
index 0000000..d668d8f
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_button_navi_left_pressed.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_button_navi_right.png b/android-filechooser/res/drawable-ldpi/afc_button_navi_right.png
new file mode 100644
index 0000000..03c67d5
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_button_navi_right.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_button_navi_right_disabled.png b/android-filechooser/res/drawable-ldpi/afc_button_navi_right_disabled.png
new file mode 100644
index 0000000..1734c0a
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_button_navi_right_disabled.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_button_navi_right_pressed.png b/android-filechooser/res/drawable-ldpi/afc_button_navi_right_pressed.png
new file mode 100644
index 0000000..c57ab9e
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_button_navi_right_pressed.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_button_ok_saveas.png b/android-filechooser/res/drawable-ldpi/afc_button_ok_saveas.png
new file mode 100644
index 0000000..2551cb0
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_button_ok_saveas.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_button_ok_saveas_pressed.png b/android-filechooser/res/drawable-ldpi/afc_button_ok_saveas_pressed.png
new file mode 100644
index 0000000..32cbaf1
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_button_ok_saveas_pressed.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_context_menu_item_divider.png b/android-filechooser/res/drawable-ldpi/afc_context_menu_item_divider.png
new file mode 100644
index 0000000..31988f9
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_context_menu_item_divider.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_file.png b/android-filechooser/res/drawable-ldpi/afc_file.png
new file mode 100644
index 0000000..3df85c8
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_file.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_file_audio.png b/android-filechooser/res/drawable-ldpi/afc_file_audio.png
new file mode 100644
index 0000000..c0432e9
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_file_audio.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_file_compressed.png b/android-filechooser/res/drawable-ldpi/afc_file_compressed.png
new file mode 100644
index 0000000..4483258
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_file_compressed.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_file_image.png b/android-filechooser/res/drawable-ldpi/afc_file_image.png
new file mode 100644
index 0000000..1ff8c52
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_file_image.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_file_plain_text.png b/android-filechooser/res/drawable-ldpi/afc_file_plain_text.png
new file mode 100644
index 0000000..8e3c81a
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_file_plain_text.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_file_video.png b/android-filechooser/res/drawable-ldpi/afc_file_video.png
new file mode 100644
index 0000000..4424cac
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_file_video.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_folder.png b/android-filechooser/res/drawable-ldpi/afc_folder.png
new file mode 100644
index 0000000..fa67860
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_folder.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_ic_menu_gridview.png b/android-filechooser/res/drawable-ldpi/afc_ic_menu_gridview.png
new file mode 100644
index 0000000..9756336
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_ic_menu_gridview.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_ic_menu_home.png b/android-filechooser/res/drawable-ldpi/afc_ic_menu_home.png
new file mode 100644
index 0000000..be4e35b
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_ic_menu_home.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_ic_menu_listview.png b/android-filechooser/res/drawable-ldpi/afc_ic_menu_listview.png
new file mode 100644
index 0000000..bfa02fd
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_ic_menu_listview.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_ic_menu_reload.png b/android-filechooser/res/drawable-ldpi/afc_ic_menu_reload.png
new file mode 100644
index 0000000..e8f658a
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_ic_menu_reload.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_ic_menu_sort_by_date_asc.png b/android-filechooser/res/drawable-ldpi/afc_ic_menu_sort_by_date_asc.png
new file mode 100644
index 0000000..af94a13
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_ic_menu_sort_by_date_asc.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_ic_menu_sort_by_date_desc.png b/android-filechooser/res/drawable-ldpi/afc_ic_menu_sort_by_date_desc.png
new file mode 100644
index 0000000..2bd3fe6
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_ic_menu_sort_by_date_desc.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_ic_menu_sort_by_name_asc.png b/android-filechooser/res/drawable-ldpi/afc_ic_menu_sort_by_name_asc.png
new file mode 100644
index 0000000..80b408e
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_ic_menu_sort_by_name_asc.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_ic_menu_sort_by_name_desc.png b/android-filechooser/res/drawable-ldpi/afc_ic_menu_sort_by_name_desc.png
new file mode 100644
index 0000000..cc69cc2
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_ic_menu_sort_by_name_desc.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_ic_menu_sort_by_size_asc.png b/android-filechooser/res/drawable-ldpi/afc_ic_menu_sort_by_size_asc.png
new file mode 100644
index 0000000..a724374
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_ic_menu_sort_by_size_asc.png differ
diff --git a/android-filechooser/res/drawable-ldpi/afc_ic_menu_sort_by_size_desc.png b/android-filechooser/res/drawable-ldpi/afc_ic_menu_sort_by_size_desc.png
new file mode 100644
index 0000000..e61dc50
Binary files /dev/null and b/android-filechooser/res/drawable-ldpi/afc_ic_menu_sort_by_size_desc.png differ
diff --git a/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_gridview.png b/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_gridview.png
new file mode 100644
index 0000000..69f7662
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_gridview.png differ
diff --git a/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_home.png b/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_home.png
new file mode 100644
index 0000000..cb89c8f
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_home.png differ
diff --git a/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_listview.png b/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_listview.png
new file mode 100644
index 0000000..226042a
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_listview.png differ
diff --git a/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_reload.png b/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_reload.png
new file mode 100644
index 0000000..a75b6d7
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_reload.png differ
diff --git a/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_sort_by_date_asc.png b/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_sort_by_date_asc.png
new file mode 100644
index 0000000..ca2f1a7
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_sort_by_date_asc.png differ
diff --git a/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_sort_by_date_desc.png b/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_sort_by_date_desc.png
new file mode 100644
index 0000000..ba96587
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_sort_by_date_desc.png differ
diff --git a/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_sort_by_name_asc.png b/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_sort_by_name_asc.png
new file mode 100644
index 0000000..8daa7fe
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_sort_by_name_asc.png differ
diff --git a/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_sort_by_name_desc.png b/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_sort_by_name_desc.png
new file mode 100644
index 0000000..6e53d23
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_sort_by_name_desc.png differ
diff --git a/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_sort_by_size_asc.png b/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_sort_by_size_asc.png
new file mode 100644
index 0000000..777c949
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_sort_by_size_asc.png differ
diff --git a/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_sort_by_size_desc.png b/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_sort_by_size_desc.png
new file mode 100644
index 0000000..b9290a3
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi-v11/afc_ic_menu_sort_by_size_desc.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_button_navi_left.png b/android-filechooser/res/drawable-mdpi/afc_button_navi_left.png
new file mode 100644
index 0000000..0c7e069
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_button_navi_left.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_button_navi_left_disabled.png b/android-filechooser/res/drawable-mdpi/afc_button_navi_left_disabled.png
new file mode 100644
index 0000000..fb744df
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_button_navi_left_disabled.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_button_navi_left_pressed.png b/android-filechooser/res/drawable-mdpi/afc_button_navi_left_pressed.png
new file mode 100644
index 0000000..81329de
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_button_navi_left_pressed.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_button_navi_right.png b/android-filechooser/res/drawable-mdpi/afc_button_navi_right.png
new file mode 100644
index 0000000..44fe22b
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_button_navi_right.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_button_navi_right_disabled.png b/android-filechooser/res/drawable-mdpi/afc_button_navi_right_disabled.png
new file mode 100644
index 0000000..989209d
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_button_navi_right_disabled.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_button_navi_right_pressed.png b/android-filechooser/res/drawable-mdpi/afc_button_navi_right_pressed.png
new file mode 100644
index 0000000..32183b1
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_button_navi_right_pressed.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_button_ok_saveas.png b/android-filechooser/res/drawable-mdpi/afc_button_ok_saveas.png
new file mode 100644
index 0000000..01eff98
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_button_ok_saveas.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_button_ok_saveas_pressed.png b/android-filechooser/res/drawable-mdpi/afc_button_ok_saveas_pressed.png
new file mode 100644
index 0000000..90bafe8
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_button_ok_saveas_pressed.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_context_menu_item_divider.png b/android-filechooser/res/drawable-mdpi/afc_context_menu_item_divider.png
new file mode 100644
index 0000000..1cb23d9
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_context_menu_item_divider.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_file.png b/android-filechooser/res/drawable-mdpi/afc_file.png
new file mode 100644
index 0000000..91a494a
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_file.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_file_audio.png b/android-filechooser/res/drawable-mdpi/afc_file_audio.png
new file mode 100644
index 0000000..6614e53
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_file_audio.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_file_compressed.png b/android-filechooser/res/drawable-mdpi/afc_file_compressed.png
new file mode 100644
index 0000000..bd522fa
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_file_compressed.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_file_image.png b/android-filechooser/res/drawable-mdpi/afc_file_image.png
new file mode 100644
index 0000000..677ce77
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_file_image.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_file_plain_text.png b/android-filechooser/res/drawable-mdpi/afc_file_plain_text.png
new file mode 100644
index 0000000..74e5fc8
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_file_plain_text.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_file_video.png b/android-filechooser/res/drawable-mdpi/afc_file_video.png
new file mode 100644
index 0000000..7e68e8b
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_file_video.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_folder.png b/android-filechooser/res/drawable-mdpi/afc_folder.png
new file mode 100644
index 0000000..5c992d7
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_folder.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_ic_menu_gridview.png b/android-filechooser/res/drawable-mdpi/afc_ic_menu_gridview.png
new file mode 100644
index 0000000..db52be1
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_ic_menu_gridview.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_ic_menu_home.png b/android-filechooser/res/drawable-mdpi/afc_ic_menu_home.png
new file mode 100644
index 0000000..284fbe0
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_ic_menu_home.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_ic_menu_listview.png b/android-filechooser/res/drawable-mdpi/afc_ic_menu_listview.png
new file mode 100644
index 0000000..cd10256
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_ic_menu_listview.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_ic_menu_reload.png b/android-filechooser/res/drawable-mdpi/afc_ic_menu_reload.png
new file mode 100644
index 0000000..9841ba4
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_ic_menu_reload.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_ic_menu_sort_by_date_asc.png b/android-filechooser/res/drawable-mdpi/afc_ic_menu_sort_by_date_asc.png
new file mode 100644
index 0000000..77cc5b2
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_ic_menu_sort_by_date_asc.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_ic_menu_sort_by_date_desc.png b/android-filechooser/res/drawable-mdpi/afc_ic_menu_sort_by_date_desc.png
new file mode 100644
index 0000000..dd10b07
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_ic_menu_sort_by_date_desc.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_ic_menu_sort_by_name_asc.png b/android-filechooser/res/drawable-mdpi/afc_ic_menu_sort_by_name_asc.png
new file mode 100644
index 0000000..15ee746
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_ic_menu_sort_by_name_asc.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_ic_menu_sort_by_name_desc.png b/android-filechooser/res/drawable-mdpi/afc_ic_menu_sort_by_name_desc.png
new file mode 100644
index 0000000..05a0a90
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_ic_menu_sort_by_name_desc.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_ic_menu_sort_by_size_asc.png b/android-filechooser/res/drawable-mdpi/afc_ic_menu_sort_by_size_asc.png
new file mode 100644
index 0000000..e30b379
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_ic_menu_sort_by_size_asc.png differ
diff --git a/android-filechooser/res/drawable-mdpi/afc_ic_menu_sort_by_size_desc.png b/android-filechooser/res/drawable-mdpi/afc_ic_menu_sort_by_size_desc.png
new file mode 100644
index 0000000..c71524a
Binary files /dev/null and b/android-filechooser/res/drawable-mdpi/afc_ic_menu_sort_by_size_desc.png differ
diff --git a/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_gridview.png b/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_gridview.png
new file mode 100644
index 0000000..019dc18
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_gridview.png differ
diff --git a/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_home.png b/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_home.png
new file mode 100644
index 0000000..bec48ec
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_home.png differ
diff --git a/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_listview.png b/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_listview.png
new file mode 100644
index 0000000..1e2c31a
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_listview.png differ
diff --git a/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_reload.png b/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_reload.png
new file mode 100644
index 0000000..4531d20
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_reload.png differ
diff --git a/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_sort_by_date_asc.png b/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_sort_by_date_asc.png
new file mode 100644
index 0000000..f38791b
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_sort_by_date_asc.png differ
diff --git a/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_sort_by_date_desc.png b/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_sort_by_date_desc.png
new file mode 100644
index 0000000..98d53e8
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_sort_by_date_desc.png differ
diff --git a/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_sort_by_name_asc.png b/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_sort_by_name_asc.png
new file mode 100644
index 0000000..c9b2460
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_sort_by_name_asc.png differ
diff --git a/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_sort_by_name_desc.png b/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_sort_by_name_desc.png
new file mode 100644
index 0000000..0711902
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_sort_by_name_desc.png differ
diff --git a/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_sort_by_size_asc.png b/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_sort_by_size_asc.png
new file mode 100644
index 0000000..9296083
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_sort_by_size_asc.png differ
diff --git a/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_sort_by_size_desc.png b/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_sort_by_size_desc.png
new file mode 100644
index 0000000..ddb53f8
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi-v11/afc_ic_menu_sort_by_size_desc.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_button_navi_left.png b/android-filechooser/res/drawable-xhdpi/afc_button_navi_left.png
new file mode 100644
index 0000000..7ff958b
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_button_navi_left.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_button_navi_left_disabled.png b/android-filechooser/res/drawable-xhdpi/afc_button_navi_left_disabled.png
new file mode 100644
index 0000000..3aaface
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_button_navi_left_disabled.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_button_navi_left_pressed.png b/android-filechooser/res/drawable-xhdpi/afc_button_navi_left_pressed.png
new file mode 100644
index 0000000..ccc0a1a
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_button_navi_left_pressed.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_button_navi_right.png b/android-filechooser/res/drawable-xhdpi/afc_button_navi_right.png
new file mode 100644
index 0000000..778dc24
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_button_navi_right.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_button_navi_right_disabled.png b/android-filechooser/res/drawable-xhdpi/afc_button_navi_right_disabled.png
new file mode 100644
index 0000000..8f3362d
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_button_navi_right_disabled.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_button_navi_right_pressed.png b/android-filechooser/res/drawable-xhdpi/afc_button_navi_right_pressed.png
new file mode 100644
index 0000000..ff0d91b
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_button_navi_right_pressed.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_button_ok_saveas.png b/android-filechooser/res/drawable-xhdpi/afc_button_ok_saveas.png
new file mode 100644
index 0000000..7a70073
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_button_ok_saveas.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_button_ok_saveas_pressed.png b/android-filechooser/res/drawable-xhdpi/afc_button_ok_saveas_pressed.png
new file mode 100644
index 0000000..02994cc
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_button_ok_saveas_pressed.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_context_menu_item_divider.png b/android-filechooser/res/drawable-xhdpi/afc_context_menu_item_divider.png
new file mode 100644
index 0000000..d69823b
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_context_menu_item_divider.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_file.png b/android-filechooser/res/drawable-xhdpi/afc_file.png
new file mode 100644
index 0000000..3744656
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_file.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_file_audio.png b/android-filechooser/res/drawable-xhdpi/afc_file_audio.png
new file mode 100644
index 0000000..c936781
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_file_audio.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_file_compressed.png b/android-filechooser/res/drawable-xhdpi/afc_file_compressed.png
new file mode 100644
index 0000000..87270f8
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_file_compressed.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_file_image.png b/android-filechooser/res/drawable-xhdpi/afc_file_image.png
new file mode 100644
index 0000000..9da2f5d
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_file_image.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_file_plain_text.png b/android-filechooser/res/drawable-xhdpi/afc_file_plain_text.png
new file mode 100644
index 0000000..6ae1b98
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_file_plain_text.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_file_video.png b/android-filechooser/res/drawable-xhdpi/afc_file_video.png
new file mode 100644
index 0000000..c508431
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_file_video.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_folder.png b/android-filechooser/res/drawable-xhdpi/afc_folder.png
new file mode 100644
index 0000000..776ae6c
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_folder.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_ic_menu_gridview.png b/android-filechooser/res/drawable-xhdpi/afc_ic_menu_gridview.png
new file mode 100644
index 0000000..b5ca4d0
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_ic_menu_gridview.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_ic_menu_home.png b/android-filechooser/res/drawable-xhdpi/afc_ic_menu_home.png
new file mode 100644
index 0000000..903dbbe
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_ic_menu_home.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_ic_menu_listview.png b/android-filechooser/res/drawable-xhdpi/afc_ic_menu_listview.png
new file mode 100644
index 0000000..9ce6bb7
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_ic_menu_listview.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_ic_menu_reload.png b/android-filechooser/res/drawable-xhdpi/afc_ic_menu_reload.png
new file mode 100644
index 0000000..6d2e14a
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_ic_menu_reload.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_ic_menu_sort_by_date_asc.png b/android-filechooser/res/drawable-xhdpi/afc_ic_menu_sort_by_date_asc.png
new file mode 100644
index 0000000..b618ef5
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_ic_menu_sort_by_date_asc.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_ic_menu_sort_by_date_desc.png b/android-filechooser/res/drawable-xhdpi/afc_ic_menu_sort_by_date_desc.png
new file mode 100644
index 0000000..eff5fce
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_ic_menu_sort_by_date_desc.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_ic_menu_sort_by_name_asc.png b/android-filechooser/res/drawable-xhdpi/afc_ic_menu_sort_by_name_asc.png
new file mode 100644
index 0000000..3377d28
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_ic_menu_sort_by_name_asc.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_ic_menu_sort_by_name_desc.png b/android-filechooser/res/drawable-xhdpi/afc_ic_menu_sort_by_name_desc.png
new file mode 100644
index 0000000..8aa3d49
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_ic_menu_sort_by_name_desc.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_ic_menu_sort_by_size_asc.png b/android-filechooser/res/drawable-xhdpi/afc_ic_menu_sort_by_size_asc.png
new file mode 100644
index 0000000..0a71054
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_ic_menu_sort_by_size_asc.png differ
diff --git a/android-filechooser/res/drawable-xhdpi/afc_ic_menu_sort_by_size_desc.png b/android-filechooser/res/drawable-xhdpi/afc_ic_menu_sort_by_size_desc.png
new file mode 100644
index 0000000..477acaf
Binary files /dev/null and b/android-filechooser/res/drawable-xhdpi/afc_ic_menu_sort_by_size_desc.png differ
diff --git a/android-filechooser/res/drawable/afc_button_location_dark_pressed.xml b/android-filechooser/res/drawable/afc_button_location_dark_pressed.xml
new file mode 100644
index 0000000..0cfca12
--- /dev/null
+++ b/android-filechooser/res/drawable/afc_button_location_dark_pressed.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/drawable/afc_selector_button_location_dark.xml b/android-filechooser/res/drawable/afc_selector_button_location_dark.xml
new file mode 100644
index 0000000..dc2f94d
--- /dev/null
+++ b/android-filechooser/res/drawable/afc_selector_button_location_dark.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/drawable/afc_selector_button_navi_left.xml b/android-filechooser/res/drawable/afc_selector_button_navi_left.xml
new file mode 100644
index 0000000..4734e37
--- /dev/null
+++ b/android-filechooser/res/drawable/afc_selector_button_navi_left.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/drawable/afc_selector_button_navi_right.xml b/android-filechooser/res/drawable/afc_selector_button_navi_right.xml
new file mode 100644
index 0000000..d0a3620
--- /dev/null
+++ b/android-filechooser/res/drawable/afc_selector_button_navi_right.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/drawable/afc_selector_button_ok_saveas.xml b/android-filechooser/res/drawable/afc_selector_button_ok_saveas.xml
new file mode 100644
index 0000000..2d4b37e
--- /dev/null
+++ b/android-filechooser/res/drawable/afc_selector_button_ok_saveas.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/drawable/afc_view_locations_divider_dark.xml b/android-filechooser/res/drawable/afc_view_locations_divider_dark.xml
new file mode 100644
index 0000000..4bedaba
--- /dev/null
+++ b/android-filechooser/res/drawable/afc_view_locations_divider_dark.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/layout-v11/afc_file_chooser.xml b/android-filechooser/res/layout-v11/afc_file_chooser.xml
new file mode 100644
index 0000000..fa7c847
--- /dev/null
+++ b/android-filechooser/res/layout-v11/afc_file_chooser.xml
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/layout-v11/afc_settings_sort_view.xml b/android-filechooser/res/layout-v11/afc_settings_sort_view.xml
new file mode 100644
index 0000000..9bdad46
--- /dev/null
+++ b/android-filechooser/res/layout-v11/afc_settings_sort_view.xml
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/layout/afc_button_location.xml b/android-filechooser/res/layout/afc_button_location.xml
new file mode 100644
index 0000000..ca4b26c
--- /dev/null
+++ b/android-filechooser/res/layout/afc_button_location.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/layout/afc_context_menu_item.xml b/android-filechooser/res/layout/afc_context_menu_item.xml
new file mode 100644
index 0000000..22bb8cf
--- /dev/null
+++ b/android-filechooser/res/layout/afc_context_menu_item.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/layout/afc_context_menu_view.xml b/android-filechooser/res/layout/afc_context_menu_view.xml
new file mode 100644
index 0000000..6e6d319
--- /dev/null
+++ b/android-filechooser/res/layout/afc_context_menu_view.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/layout/afc_file_chooser.xml b/android-filechooser/res/layout/afc_file_chooser.xml
new file mode 100644
index 0000000..b63bb8d
--- /dev/null
+++ b/android-filechooser/res/layout/afc_file_chooser.xml
@@ -0,0 +1,152 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/layout/afc_file_item.xml b/android-filechooser/res/layout/afc_file_item.xml
new file mode 100644
index 0000000..8a4f72a
--- /dev/null
+++ b/android-filechooser/res/layout/afc_file_item.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/layout/afc_gridview_files.xml b/android-filechooser/res/layout/afc_gridview_files.xml
new file mode 100644
index 0000000..97d04bd
--- /dev/null
+++ b/android-filechooser/res/layout/afc_gridview_files.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/layout/afc_listview_files.xml b/android-filechooser/res/layout/afc_listview_files.xml
new file mode 100644
index 0000000..f7bc4f7
--- /dev/null
+++ b/android-filechooser/res/layout/afc_listview_files.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/layout/afc_settings_sort_view.xml b/android-filechooser/res/layout/afc_settings_sort_view.xml
new file mode 100644
index 0000000..0d4da1b
--- /dev/null
+++ b/android-filechooser/res/layout/afc_settings_sort_view.xml
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/layout/afc_simple_text_input_view.xml b/android-filechooser/res/layout/afc_simple_text_input_view.xml
new file mode 100644
index 0000000..7ed8f48
--- /dev/null
+++ b/android-filechooser/res/layout/afc_simple_text_input_view.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/layout/afc_view_locations_divider.xml b/android-filechooser/res/layout/afc_view_locations_divider.xml
new file mode 100644
index 0000000..887042a
--- /dev/null
+++ b/android-filechooser/res/layout/afc_view_locations_divider.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/menu/afc_file_chooser_activity.xml b/android-filechooser/res/menu/afc_file_chooser_activity.xml
new file mode 100644
index 0000000..6e5b21a
--- /dev/null
+++ b/android-filechooser/res/menu/afc_file_chooser_activity.xml
@@ -0,0 +1,47 @@
+
+
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/values-hdpi/dimens.xml b/android-filechooser/res/values-hdpi/dimens.xml
new file mode 100644
index 0000000..8e072f9
--- /dev/null
+++ b/android-filechooser/res/values-hdpi/dimens.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ 48px
+ 48px
+ 72px
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/values-ldpi/dimens.xml b/android-filechooser/res/values-ldpi/dimens.xml
new file mode 100644
index 0000000..5b8d51f
--- /dev/null
+++ b/android-filechooser/res/values-ldpi/dimens.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ 24px
+ 24px
+ 36px
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/values-mdpi/dimens.xml b/android-filechooser/res/values-mdpi/dimens.xml
new file mode 100644
index 0000000..35c4477
--- /dev/null
+++ b/android-filechooser/res/values-mdpi/dimens.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ 32px
+ 32px
+ 48px
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/values-v11/styles.xml b/android-filechooser/res/values-v11/styles.xml
new file mode 100644
index 0000000..d3ab3b2
--- /dev/null
+++ b/android-filechooser/res/values-v11/styles.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/values-v14/styles.xml b/android-filechooser/res/values-v14/styles.xml
new file mode 100644
index 0000000..da87829
--- /dev/null
+++ b/android-filechooser/res/values-v14/styles.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/values-xhdpi/dimens.xml b/android-filechooser/res/values-xhdpi/dimens.xml
new file mode 100644
index 0000000..bf7c5bf
--- /dev/null
+++ b/android-filechooser/res/values-xhdpi/dimens.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ 72px
+ 72px
+ 96px
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/values/colors.xml b/android-filechooser/res/values/colors.xml
new file mode 100644
index 0000000..9addc64
--- /dev/null
+++ b/android-filechooser/res/values/colors.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+ #cc00ffff
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/values/dimens.xml b/android-filechooser/res/values/dimens.xml
new file mode 100644
index 0000000..e41c230
--- /dev/null
+++ b/android-filechooser/res/values/dimens.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+ 30dp
+ 15dp
+ 10dp
+ 5dp
+ 256sp
+ 80sp
+ 18sp
+ 192sp
+ 1dp
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/values/fc_strings.xml b/android-filechooser/res/values/fc_strings.xml
new file mode 100644
index 0000000..914ec90
--- /dev/null
+++ b/android-filechooser/res/values/fc_strings.xml
@@ -0,0 +1,69 @@
+
+
+
+
+
+ android-filechooser
+ All
+ Invert selection
+ None
+ Clear
+ Grid view
+ Home
+ List view
+ New folder…
+ Reload
+ Remove from list
+ Select all files
+ Select all folders
+ Sort…
+ Switch Viewmode
+ …
+ file
+ folder
+ Double tap to select file/ folder
+ folder name
+ filename
+ This application does not have permission to create files/ folders
+ This application does not have permission to delete files/ folders
+ Cancelled
+ Can not connect to file provider service
+ Done
+ …empty
+ Filename is empty
+ Loading…
+ Can not access \"%1$s\"
+ Can not create folder \"%1$s\"
+ Can not delete %1$s \"%2$s\"
+ Are you sure you want to delete this %1$s \"%2$s\"?
+ This file \"%1$s\" already exists.\n\nDo you want to replace it?
+ Deleting %1$s \"%2$s\"…
+ …%1$s \"%2$s\" has been deleted
+ \"%1$s\" is a folder
+ File name \"%1$s\" is invalid
+ …has more files, max allowed: %1$,d
+ Unknown error: %1$s
+ %1$,d items
+ Root
+ Select…
+ Alert
+ Choose a folder
+ Choose files…
+ Choose files/ folders…
+ Confirmation
+ Date
+ Error
+ History
+ Info
+ Name
+ Save as…
+ Size
+ Sort by…
+ Yesterday
+
+
diff --git a/android-filechooser/res/values/preferences.xml b/android-filechooser/res/values/preferences.xml
new file mode 100644
index 0000000..c1a5707
--- /dev/null
+++ b/android-filechooser/res/values/preferences.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+ afc.display.view_type
+ afc.display.sort_type
+ afc.display.sort_ascending
+ afc.display.show_time_for_old_days_this_year
+ afc.display.show_time_for_old_days
+ afc.display.remember_last_location
+ afc.display.last_location
+
+ 0
+ 0
+
+ true
+ false
+ false
+ true
+
+
\ No newline at end of file
diff --git a/android-filechooser/res/values/styles.xml b/android-filechooser/res/values/styles.xml
new file mode 100644
index 0000000..e6fb734
--- /dev/null
+++ b/android-filechooser/res/values/styles.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android-filechooser/src/group/pals/android/lib/ui/filechooser/FileChooserActivity.java b/android-filechooser/src/group/pals/android/lib/ui/filechooser/FileChooserActivity.java
new file mode 100644
index 0000000..bbfa0cb
--- /dev/null
+++ b/android-filechooser/src/group/pals/android/lib/ui/filechooser/FileChooserActivity.java
@@ -0,0 +1,1806 @@
+/*
+ * Copyright (c) 2012 Hai Bison
+ *
+ * See the file LICENSE at the root directory of this project for copying
+ * permission.
+ */
+
+package group.pals.android.lib.ui.filechooser;
+
+import group.pals.android.lib.ui.filechooser.io.IFile;
+import group.pals.android.lib.ui.filechooser.io.IFileFilter;
+import group.pals.android.lib.ui.filechooser.prefs.DisplayPrefs;
+import group.pals.android.lib.ui.filechooser.services.FileProviderService;
+import group.pals.android.lib.ui.filechooser.services.IFileProvider;
+import group.pals.android.lib.ui.filechooser.services.IFileProvider.FilterMode;
+import group.pals.android.lib.ui.filechooser.services.IFileProvider.SortOrder;
+import group.pals.android.lib.ui.filechooser.services.IFileProvider.SortType;
+import group.pals.android.lib.ui.filechooser.services.LocalFileProvider;
+import group.pals.android.lib.ui.filechooser.utils.ActivityCompat;
+import group.pals.android.lib.ui.filechooser.utils.E;
+import group.pals.android.lib.ui.filechooser.utils.FileComparator;
+import group.pals.android.lib.ui.filechooser.utils.FileUtils;
+import group.pals.android.lib.ui.filechooser.utils.Ui;
+import group.pals.android.lib.ui.filechooser.utils.Utils;
+import group.pals.android.lib.ui.filechooser.utils.history.History;
+import group.pals.android.lib.ui.filechooser.utils.history.HistoryFilter;
+import group.pals.android.lib.ui.filechooser.utils.history.HistoryListener;
+import group.pals.android.lib.ui.filechooser.utils.history.HistoryStore;
+import group.pals.android.lib.ui.filechooser.utils.ui.Dlg;
+import group.pals.android.lib.ui.filechooser.utils.ui.LoadingDialog;
+import group.pals.android.lib.ui.filechooser.utils.ui.TaskListener;
+import group.pals.android.lib.ui.filechooser.utils.ui.ViewFilesContextMenuUtils;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import android.Manifest;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.SharedPreferences;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.GestureDetector;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.EditorInfo;
+import android.widget.AbsListView;
+import android.widget.AdapterView;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.GridView;
+import android.widget.HorizontalScrollView;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.TextView;
+
+/**
+ * Main activity for this library.
+ *
+ * Notes:
+ *
+ * I. About keys {@link FileChooserActivity#_Rootpath},
+ * {@link FileChooserActivity#_SelectFile} and preference
+ * {@link DisplayPrefs#isRememberLastLocation(Context)}, the priorities of them
+ * are:
+ *
+ *
+ * @since v4.3 beta
+ */
+ public static final String _Theme = _ClassName + ".theme";
+
+ /**
+ * Key to hold the root path.
+ *
+ * If {@link LocalFileProvider} is used, then default is sdcard, if sdcard
+ * is not available, "/" will be used.
+ *
+ * Note: The value of this key is a {@link IFile}
+ */
+ public static final String _Rootpath = _ClassName + ".rootpath";
+
+ /**
+ * Key to hold the service class which implements {@link IFileProvider}.
+ * Default is {@link LocalFileProvider}
+ */
+ public static final String _FileProviderClass = _ClassName + ".file_provider_class";
+
+ // ---------------------------------------------------------
+
+ /**
+ * Key to hold {@link IFileProvider.FilterMode}, default is
+ * {@link IFileProvider.FilterMode#FilesOnly}.
+ */
+ public static final String _FilterMode = IFileProvider.FilterMode.class.getName();
+
+ // flags
+
+ // ---------------------------------------------------------
+
+ /**
+ * Key to hold max file count that's allowed to be listed, default =
+ * {@code 1024}
+ */
+ public static final String _MaxFileCount = _ClassName + ".max_file_count";
+ /**
+ * Key to hold multi-selection mode, default = {@code false}
+ */
+ public static final String _MultiSelection = _ClassName + ".multi_selection";
+ /**
+ * Key to hold the component class implementing {@link IFileFilter}, default
+ * is {@code null}.
+ *
+ * @since v5.1 beta
+ */
+ public static final String _IFileFilterClass = _ClassName + ".ifile_filter_class";
+ /**
+ * Key to hold display-hidden-files, default = {@code false}
+ */
+ public static final String _DisplayHiddenFiles = _ClassName + ".display_hidden_files";
+ /**
+ * Sets this to {@code true} to enable double tapping to choose files/
+ * directories. In older versions, double tapping is default. However, since
+ * v4.7 beta, single tapping is default. So if you want to keep the old way,
+ * please set this key to {@code true}.
+ *
+ * @since v4.7 beta
+ */
+ public static final String _DoubleTapToChooseFiles = _ClassName + ".double_tap_to_choose_files";
+ /**
+ * Sets the file you want to select when starting this activity. The file is
+ * an {@link IFile}.
+ * Notes:
+ *
Currently this key is only used for single selection mode.
+ *
+ *
If you use save dialog mode, this key will override key
+ * {@link #_DefaultFilename}.
+ *
+ * @since v4.7 beta
+ */
+ public static final String _SelectFile = _ClassName + ".select_file";
+
+ // ---------------------------------------------------------
+
+ /**
+ * Key to hold property save-dialog, default = {@code false}
+ */
+ public static final String _SaveDialog = _ClassName + ".save_dialog";
+ /**
+ * Key to hold default filename, default = {@code null}
+ */
+ public static final String _DefaultFilename = _ClassName + ".default_filename";
+ /**
+ * Key to hold results (can be one or multiple files)
+ */
+ public static final String _Results = _ClassName + ".results";
+
+ /**
+ * This key holds current location (an {@link IFile}), to restore it after
+ * screen orientation changed
+ */
+ static final String _CurrentLocation = _ClassName + ".current_location";
+ /**
+ * This key holds current history (a {@link History}<{@link IFile}>),
+ * to restore it after screen orientation changed
+ */
+ static final String _History = _ClassName + ".history";
+
+ /**
+ * This key holds current full history (a {@link History}< {@link IFile}
+ * >), to restore it after screen orientation changed.
+ */
+ static final String _FullHistory = History.class.getName() + "_full";
+
+ // ====================
+ // "CONSTANT" VARIABLES
+
+ private Class> mFileProviderServiceClass;
+ /**
+ * The file provider service.
+ */
+ private IFileProvider mFileProvider;
+ /**
+ * The service connection.
+ */
+ private ServiceConnection mServiceConnection;
+
+ private IFile mRoot;
+ private boolean mIsMultiSelection;
+ private boolean mIsSaveDialog;
+ private boolean mDoubleTapToChooseFiles;
+
+ /**
+ * The history.
+ */
+ private History mHistory;
+
+ /**
+ * The full history, to store and show the users whatever they have been
+ * gone to.
+ */
+ private History mFullHistory;
+
+ /**
+ * The adapter of list view.
+ */
+ private IFileAdapter mFileAdapter;
+
+ /*
+ * controls
+ */
+ private HorizontalScrollView mViewLocationsContainer;
+ private ViewGroup mViewLocations;
+ private ViewGroup mViewFilesContainer;
+ private TextView mTxtFullDirName;
+ private AbsListView mViewFiles;
+ private TextView mFooterView;
+ private Button mBtnOk;
+ private EditText mTxtSaveas;
+ private ImageView mViewGoBack;
+ private ImageView mViewGoForward;
+
+ public static SharedPreferences settings;
+ public static final String PREFS_NAME = "dentex.youtube.downloader_preferences";
+
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ /*
+ * THEME
+ */
+
+ /*if (getIntent().hasExtra(_Theme)) {
+ int theme;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
+ theme = getIntent().getIntExtra(_Theme, android.R.style.Theme_DeviceDefault);
+ else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
+ theme = getIntent().getIntExtra(_Theme, android.R.style.Theme_Holo);
+ else
+ theme = getIntent().getIntExtra(_Theme, android.R.style.Theme);
+ setTheme(theme);
+ }*/
+
+ // Theme init
+ settings = getSharedPreferences(PREFS_NAME, 0);
+ String theme = settings.getString("choose_theme", "D");
+ if (theme.equals("D")) {
+ this.setTheme(R.style.AppThemeDark);
+ } else {
+ this.setTheme(R.style.AppThemeLight);
+ }
+
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.afc_file_chooser);
+
+ initGestureDetector();
+
+ // load configurations
+
+ mFileProviderServiceClass = (Class>) getIntent().getSerializableExtra(_FileProviderClass);
+ if (mFileProviderServiceClass == null)
+ mFileProviderServiceClass = LocalFileProvider.class;
+
+ mIsMultiSelection = getIntent().getBooleanExtra(_MultiSelection, false);
+
+ mIsSaveDialog = getIntent().getBooleanExtra(_SaveDialog, false);
+ if (mIsSaveDialog)
+ mIsMultiSelection = false;
+
+ mDoubleTapToChooseFiles = getIntent().getBooleanExtra(_DoubleTapToChooseFiles, false);
+
+ // load controls
+
+ mViewGoBack = (ImageView) findViewById(R.id.afc_filechooser_activity_button_go_back);
+ mViewGoForward = (ImageView) findViewById(R.id.afc_filechooser_activity_button_go_forward);
+ mViewLocations = (ViewGroup) findViewById(R.id.afc_filechooser_activity_view_locations);
+ mViewLocationsContainer = (HorizontalScrollView) findViewById(R.id.afc_filechooser_activity_view_locations_container);
+ mTxtFullDirName = (TextView) findViewById(R.id.afc_filechooser_activity_textview_full_dir_name);
+ mViewFilesContainer = (ViewGroup) findViewById(R.id.afc_filechooser_activity_view_files_container);
+ mFooterView = (TextView) findViewById(R.id.afc_filechooser_activity_view_files_footer_view);
+ mTxtSaveas = (EditText) findViewById(R.id.afc_filechooser_activity_textview_saveas_filename);
+ mBtnOk = (Button) findViewById(R.id.afc_filechooser_activity_button_ok);
+
+ // history
+ if (savedInstanceState != null && savedInstanceState.get(_History) instanceof HistoryStore>)
+ mHistory = savedInstanceState.getParcelable(_History);
+ else
+ mHistory = new HistoryStore(DisplayPrefs._DefHistoryCapacity);
+ mHistory.addListener(new HistoryListener() {
+
+ @Override
+ public void onChanged(History history) {
+ int idx = history.indexOf(getLocation());
+ mViewGoBack.setEnabled(idx > 0);
+ mViewGoForward.setEnabled(idx >= 0 && idx < history.size() - 1);
+ }
+ });
+
+ // full history
+ if (savedInstanceState != null && savedInstanceState.get(_FullHistory) instanceof HistoryStore>)
+ mFullHistory = savedInstanceState.getParcelable(_FullHistory);
+ else
+ mFullHistory = new HistoryStore(DisplayPrefs._DefHistoryCapacity) {
+
+ @Override
+ public void push(IFile newItem) {
+ int i = indexOf(newItem);
+ if (i >= 0) {
+ if (i == size() - 1)
+ return;
+ else
+ remove(newItem);
+ }
+ super.push(newItem);
+ }// push()
+ };
+
+ // make sure RESULT_CANCELED is default
+ setResult(RESULT_CANCELED);
+
+ bindService(savedInstanceState);
+ }// onCreate()
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.afc_file_chooser_activity, menu);
+ return true;
+ }// onCreateOptionsMenu()
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ /*
+ * sorting
+ */
+
+ final boolean _sortAscending = DisplayPrefs.isSortAscending(this);
+ MenuItem miSort = menu.findItem(R.id.afc_filechooser_activity_menuitem_sort);
+
+ switch (DisplayPrefs.getSortType(this)) {
+ case SortByName:
+ miSort.setIcon(_sortAscending ? R.drawable.afc_ic_menu_sort_by_name_asc
+ : R.drawable.afc_ic_menu_sort_by_name_desc);
+ break;
+ case SortBySize:
+ miSort.setIcon(_sortAscending ? R.drawable.afc_ic_menu_sort_by_size_asc
+ : R.drawable.afc_ic_menu_sort_by_size_desc);
+ break;
+ case SortByDate:
+ miSort.setIcon(_sortAscending ? R.drawable.afc_ic_menu_sort_by_date_asc
+ : R.drawable.afc_ic_menu_sort_by_date_desc);
+ break;
+ }
+
+ /*
+ * view type
+ */
+
+ MenuItem menuItem = menu.findItem(R.id.afc_filechooser_activity_menuitem_switch_viewmode);
+ switch (DisplayPrefs.getViewType(this)) {
+ case Grid:
+ menuItem.setIcon(R.drawable.afc_ic_menu_listview);
+ menuItem.setTitle(R.string.afc_cmd_list_view);
+ break;
+ case List:
+ menuItem.setIcon(R.drawable.afc_ic_menu_gridview);
+ menuItem.setTitle(R.string.afc_cmd_grid_view);
+ break;
+ }
+
+ return true;
+ }// onPrepareOptionsMenu()
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getGroupId() == R.id.afc_filechooser_activity_menugroup_sorter) {
+ doResortViewFiles();
+ }// group_sorter
+ else if (item.getItemId() == R.id.afc_filechooser_activity_menuitem_new_folder) {
+ doCreateNewDir();
+ } else if (item.getItemId() == R.id.afc_filechooser_activity_menuitem_switch_viewmode) {
+ doSwitchViewType();
+ } else if (item.getItemId() == R.id.afc_filechooser_activity_menuitem_home) {
+ doGoHome();
+ } else if (item.getItemId() == R.id.afc_filechooser_activity_menuitem_reload) {
+ doReloadCurrentLocation();
+ }
+
+ return true;
+ }// onOptionsItemSelected()
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ }// onConfigurationChanged()
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ outState.putParcelable(_CurrentLocation, getLocation());
+ outState.putParcelable(_History, mHistory);
+ outState.putParcelable(_FullHistory, mFullHistory);
+ }// onSaveInstanceState()
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ if (!mIsMultiSelection && !mIsSaveDialog && mDoubleTapToChooseFiles)
+ Dlg.toast(this, R.string.afc_hint_double_tap_to_select_file, Dlg._LengthShort);
+ }// onStart()
+
+ @Override
+ protected void onDestroy() {
+ if (mFileProvider != null) {
+ try {
+ unbindService(mServiceConnection);
+ } catch (Throwable t) {
+ /*
+ * due to this error:
+ * https://groups.google.com/d/topic/android-developers
+ * /Gv-80mQnyhc/discussion
+ */
+ Log.e(_ClassName, "onDestroy() - unbindService() - exception: " + t);
+ }
+
+ try {
+ stopService(new Intent(this, mFileProviderServiceClass));
+ } catch (SecurityException e) {
+ /*
+ * we have permission to stop our own service, so this exception
+ * should never be thrown
+ */
+ }
+ }
+
+ super.onDestroy();
+ }
+
+ /**
+ * Connects to file provider service, then loads root directory. If can not,
+ * then finishes this activity with result code =
+ * {@link Activity#RESULT_CANCELED}
+ *
+ * @param savedInstanceState
+ */
+ private void bindService(final Bundle savedInstanceState) {
+ if (startService(new Intent(this, mFileProviderServiceClass)) == null) {
+ doShowCannotConnectToServiceAndFinish();
+ return;
+ }
+
+ mServiceConnection = new ServiceConnection() {
+
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ try {
+ mFileProvider = ((FileProviderService.LocalBinder) service).getService();
+ } catch (Throwable t) {
+ Log.e(_ClassName, "mServiceConnection.onServiceConnected() -> " + t);
+ }
+ }// onServiceConnected()
+
+ public void onServiceDisconnected(ComponentName className) {
+ mFileProvider = null;
+ }// onServiceDisconnected()
+ };
+
+ bindService(new Intent(this, mFileProviderServiceClass), mServiceConnection, Context.BIND_AUTO_CREATE);
+
+ new LoadingDialog(this, R.string.afc_msg_loading, false) {
+
+ private static final int _WaitTime = 200;
+ private static final int _MaxWaitTime = 3000; // 3 seconds
+
+ @Override
+ protected Object doInBackground(Void... params) {
+ int totalWaitTime = 0;
+ while (mFileProvider == null) {
+ try {
+ totalWaitTime += _WaitTime;
+ Thread.sleep(_WaitTime);
+ if (totalWaitTime >= _MaxWaitTime)
+ break;
+ } catch (InterruptedException e) {
+ break;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Object result) {
+ super.onPostExecute(result);
+
+ if (mFileProvider == null) {
+ doShowCannotConnectToServiceAndFinish();
+ } else {
+ setupService();
+ setupHeader();
+ setupViewFiles();
+ setupFooter();
+
+ /*
+ * Priorities for starting path:
+ *
+ * 1. Current location (in case the activity has been killed
+ * after configurations changed).
+ *
+ * 2. Selected file from key _SelectFile.
+ *
+ * 3. Last location.
+ *
+ * 4. Root path from key _Rootpath.
+ */
+
+ // current location
+ IFile path = savedInstanceState != null ? (IFile) savedInstanceState.get(_CurrentLocation) : null;
+
+ // selected file
+ IFile selectedFile = null;
+ if (path == null) {
+ selectedFile = (IFile) getIntent().getParcelableExtra(_SelectFile);
+ if (selectedFile != null && selectedFile.exists())
+ path = selectedFile.parentFile();
+ if (path == null)
+ selectedFile = null;
+ }
+
+ // last location
+ if (path == null && DisplayPrefs.isRememberLastLocation(FileChooserActivity.this)) {
+ String lastLocation = DisplayPrefs.getLastLocation(FileChooserActivity.this);
+ if (lastLocation != null)
+ path = mFileProvider.fromPath(lastLocation);
+ }
+
+ final IFile _selectedFile = selectedFile;
+
+ // or root path
+ setLocation(path != null && path.isDirectory() ? path : mRoot, new TaskListener() {
+
+ @Override
+ public void onFinish(boolean ok, Object any) {
+ if (ok && _selectedFile != null && _selectedFile.isFile() && mIsSaveDialog)
+ mTxtSaveas.setText(_selectedFile.getName());
+
+ // don't push current location into history
+ boolean isCurrentLocation = savedInstanceState != null
+ && any.equals(savedInstanceState.get(_CurrentLocation));
+ if (isCurrentLocation) {
+ mHistory.notifyHistoryChanged();
+ } else {
+ mHistory.push((IFile) any);
+ mFullHistory.push((IFile) any);
+ }
+ }// onFinish()
+ }, selectedFile);
+ }
+ }// onPostExecute()
+ }.execute();// LoadingDialog
+ }// bindService()
+
+ /**
+ * Setup the file provider:
+ * - filter mode;
+ * - display hidden files;
+ * - max file count;
+ * - ...
+ */
+ @SuppressWarnings("unchecked")
+ private void setupService() {
+ /*
+ * set root path, if not specified, try using
+ * IFileProvider#defaultPath()
+ */
+ if (getIntent().getParcelableExtra(_Rootpath) != null)
+ mRoot = (IFile) getIntent().getSerializableExtra(_Rootpath);
+ if (mRoot == null || !mRoot.isDirectory())
+ mRoot = mFileProvider.defaultPath();
+
+ IFileProvider.FilterMode filterMode = (FilterMode) getIntent().getSerializableExtra(_FilterMode);
+ if (filterMode == null)
+ filterMode = IFileProvider.FilterMode.FilesOnly;
+
+ IFileProvider.SortType sortType = DisplayPrefs.getSortType(this);
+ boolean sortAscending = DisplayPrefs.isSortAscending(this);
+
+ mFileProvider.setDisplayHiddenFiles(getIntent().getBooleanExtra(_DisplayHiddenFiles, false));
+ mFileProvider.setFilterMode(mIsSaveDialog ? IFileProvider.FilterMode.FilesOnly : filterMode);
+ mFileProvider.setMaxFileCount(getIntent().getIntExtra(_MaxFileCount, 1024));
+ mFileProvider.setFileFilterClass((Class) getIntent().getSerializableExtra(_IFileFilterClass));
+ mFileProvider.setSortOrder(sortAscending ? IFileProvider.SortOrder.Ascending
+ : IFileProvider.SortOrder.Descending);
+ mFileProvider.setSortType(sortType);
+ }// setupService()
+
+ /**
+ * Setup:
+ * - title of activity;
+ * - button go back;
+ * - button location;
+ * - button go forward;
+ */
+ private void setupHeader() {
+ if (mIsSaveDialog) {
+ setTitle(R.string.afc_title_save_as);
+ } else {
+ switch (mFileProvider.getFilterMode()) {
+ case FilesOnly:
+ setTitle(R.string.afc_title_choose_files);
+ break;
+ case FilesAndDirectories:
+ setTitle(R.string.afc_title_choose_files_and_directories);
+ break;
+ case DirectoriesOnly:
+ setTitle(R.string.afc_title_choose_directories);
+ break;
+ }
+ }// title of activity
+
+ mViewGoBack.setEnabled(false);
+ mViewGoBack.setOnClickListener(mBtnGoBackOnClickListener);
+
+ mViewGoForward.setEnabled(false);
+ mViewGoForward.setOnClickListener(mBtnGoForwardOnClickListener);
+
+ for (ImageView v : new ImageView[] { mViewGoBack, mViewGoForward })
+ v.setOnLongClickListener(mBtnGoBackForwardOnLongClickListener);
+ }// setupHeader()
+
+ /**
+ * Setup:
+ * - {@link #mViewFiles}
+ * - {@link #mViewFilesContainer}
+ * - {@link #mFileAdapter}
+ */
+ private void setupViewFiles() {
+ switch (DisplayPrefs.getViewType(this)) {
+ case Grid:
+ mViewFiles = (AbsListView) getLayoutInflater().inflate(R.layout.afc_gridview_files, null);
+ break;
+ case List:
+ mViewFiles = (AbsListView) getLayoutInflater().inflate(R.layout.afc_listview_files, null);
+ break;
+ }
+
+ mViewFilesContainer.removeAllViews();
+ mViewFilesContainer.addView(mViewFiles, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT, 1));
+
+ mViewFiles.setOnItemClickListener(mViewFilesOnItemClickListener);
+ mViewFiles.setOnItemLongClickListener(mViewFilesOnItemLongClickListener);
+ mViewFiles.setOnTouchListener(new View.OnTouchListener() {
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ return mListviewFilesGestureDetector.onTouchEvent(event);
+ }
+ });
+
+ createIFileAdapter();
+
+ // no comments :-D
+ mFooterView.setOnLongClickListener(new View.OnLongClickListener() {
+
+ @Override
+ public boolean onLongClick(View v) {
+ E.show(FileChooserActivity.this);
+ return false;
+ }
+ });
+ }// setupViewFiles()
+
+ /**
+ * Creates {@link IFileAdapter} and assign it to list view/ grid view of
+ * files.
+ */
+ private void createIFileAdapter() {
+ if (mFileAdapter != null)
+ mFileAdapter.clear();
+
+ mFileAdapter = new IFileAdapter(FileChooserActivity.this, new ArrayList(),
+ mFileProvider.getFilterMode(), mIsMultiSelection);
+ /*
+ * API 13+ does not recognize AbsListView.setAdapter(), so we cast it to
+ * explicit class
+ */
+ if (mViewFiles instanceof ListView)
+ ((ListView) mViewFiles).setAdapter(mFileAdapter);
+ else
+ ((GridView) mViewFiles).setAdapter(mFileAdapter);
+ }// createIFileAdapter()
+
+ /**
+ * Setup:
+ * - button Cancel;
+ * - text field "save as" filename;
+ * - button Ok;
+ */
+ private void setupFooter() {
+ // by default, view group footer and all its child views are hidden
+
+ ViewGroup viewGroupFooterContainer = (ViewGroup) findViewById(R.id.afc_filechooser_activity_viewgroup_footer_container);
+ ViewGroup viewGroupFooter = (ViewGroup) findViewById(R.id.afc_filechooser_activity_viewgroup_footer);
+
+ if (mIsSaveDialog) {
+ viewGroupFooterContainer.setVisibility(View.VISIBLE);
+ viewGroupFooter.setVisibility(View.VISIBLE);
+
+ mTxtSaveas.setVisibility(View.VISIBLE);
+ mTxtSaveas.setText(getIntent().getStringExtra(_DefaultFilename));
+ mTxtSaveas.setOnEditorActionListener(mTxtFilenameOnEditorActionListener);
+
+ mBtnOk.setVisibility(View.VISIBLE);
+ mBtnOk.setOnClickListener(mBtnOk_SaveDialog_OnClickListener);
+ mBtnOk.setBackgroundResource(R.drawable.afc_selector_button_ok_saveas);
+
+ int size = getResources().getDimensionPixelSize(R.dimen.afc_button_ok_saveas_size);
+ LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mBtnOk.getLayoutParams();
+ lp.width = size;
+ lp.height = size;
+ mBtnOk.setLayoutParams(lp);
+ }// this is in save mode
+ else {
+ if (mIsMultiSelection) {
+ viewGroupFooterContainer.setVisibility(View.VISIBLE);
+ viewGroupFooter.setVisibility(View.VISIBLE);
+
+ ViewGroup.LayoutParams lp = viewGroupFooter.getLayoutParams();
+ lp.width = ViewGroup.LayoutParams.WRAP_CONTENT;
+ viewGroupFooter.setLayoutParams(lp);
+
+ mBtnOk.setMinWidth(getResources().getDimensionPixelSize(R.dimen.afc_single_button_min_width));
+ mBtnOk.setText(android.R.string.ok);
+ mBtnOk.setVisibility(View.VISIBLE);
+ mBtnOk.setOnClickListener(mBtnOk_OpenDialog_OnClickListener);
+ }
+ }// this is in open mode
+ }// setupFooter()
+
+ private void doReloadCurrentLocation() {
+ setLocation(getLocation(), null);
+ }// doReloadCurrentLocation()
+
+ private void doShowCannotConnectToServiceAndFinish() {
+ Dlg.showError(FileChooserActivity.this, R.string.afc_msg_cannot_connect_to_file_provider_service,
+ new DialogInterface.OnCancelListener() {
+
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ setResult(RESULT_CANCELED);
+ finish();
+ }
+ });
+ }// doShowCannotConnectToServiceAndFinish()
+
+ private void doGoHome() {
+ // TODO explain why?
+ goTo(mRoot.clone());
+ }// doGoHome()
+
+ private static final int[] _BtnSortIds = { R.id.afc_settings_sort_view_button_sort_by_name_asc,
+ R.id.afc_settings_sort_view_button_sort_by_name_desc, R.id.afc_settings_sort_view_button_sort_by_size_asc,
+ R.id.afc_settings_sort_view_button_sort_by_size_desc, R.id.afc_settings_sort_view_button_sort_by_date_asc,
+ R.id.afc_settings_sort_view_button_sort_by_date_desc };
+
+ /**
+ * Show a dialog for sorting options and resort file list after user
+ * selected an option.
+ */
+ private void doResortViewFiles() {
+ final AlertDialog _dialog = Dlg.newDlg(this);
+
+ // get the index of button of current sort type
+ int btnCurrentSortTypeIdx = 0;
+ switch (DisplayPrefs.getSortType(this)) {
+ case SortByName:
+ btnCurrentSortTypeIdx = 0;
+ break;
+ case SortBySize:
+ btnCurrentSortTypeIdx = 2;
+ break;
+ case SortByDate:
+ btnCurrentSortTypeIdx = 4;
+ break;
+ }
+ if (!DisplayPrefs.isSortAscending(this))
+ btnCurrentSortTypeIdx++;
+
+ View.OnClickListener listener = new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ _dialog.dismiss();
+
+ Context c = FileChooserActivity.this;
+
+ if (v.getId() == R.id.afc_settings_sort_view_button_sort_by_name_asc) {
+ DisplayPrefs.setSortType(c, SortType.SortByName);
+ DisplayPrefs.setSortAscending(c, true);
+ } else if (v.getId() == R.id.afc_settings_sort_view_button_sort_by_name_desc) {
+ DisplayPrefs.setSortType(c, SortType.SortByName);
+ DisplayPrefs.setSortAscending(c, false);
+ } else if (v.getId() == R.id.afc_settings_sort_view_button_sort_by_size_asc) {
+ DisplayPrefs.setSortType(c, SortType.SortBySize);
+ DisplayPrefs.setSortAscending(c, true);
+ } else if (v.getId() == R.id.afc_settings_sort_view_button_sort_by_size_desc) {
+ DisplayPrefs.setSortType(c, SortType.SortBySize);
+ DisplayPrefs.setSortAscending(c, false);
+ } else if (v.getId() == R.id.afc_settings_sort_view_button_sort_by_date_asc) {
+ DisplayPrefs.setSortType(c, SortType.SortByDate);
+ DisplayPrefs.setSortAscending(c, true);
+ } else if (v.getId() == R.id.afc_settings_sort_view_button_sort_by_date_desc) {
+ DisplayPrefs.setSortType(c, SortType.SortByDate);
+ DisplayPrefs.setSortAscending(c, false);
+ }
+
+ resortViewFiles();
+ }// onClick()
+ };// listener
+
+ View view = getLayoutInflater().inflate(R.layout.afc_settings_sort_view, null);
+ for (int i = 0; i < _BtnSortIds.length; i++) {
+ Button btn = (Button) view.findViewById(_BtnSortIds[i]);
+ btn.setOnClickListener(listener);
+ if (i == btnCurrentSortTypeIdx) {
+ btn.setEnabled(false);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
+ btn.setText(R.string.afc_ellipsize);
+ }
+ }
+
+ _dialog.setTitle(R.string.afc_title_sort_by);
+ _dialog.setView(view);
+
+ _dialog.show();
+ }// doResortViewFiles()
+
+ /**
+ * Resort view files.
+ */
+ private void resortViewFiles() {
+ if (mFileProvider.getSortType().equals(DisplayPrefs.getSortType(this))
+ && mFileProvider.getSortOrder().isAsc() == (DisplayPrefs.isSortAscending(this)))
+ return;
+
+ /*
+ * Re-sort the listview by re-loading current location; NOTE: re-sort
+ * the adapter does not repaint the listview, even if we call
+ * notifyDataSetChanged(), invalidateViews()...
+ */
+ mFileProvider.setSortType(DisplayPrefs.getSortType(this));
+ mFileProvider.setSortOrder(DisplayPrefs.isSortAscending(this) ? SortOrder.Ascending : SortOrder.Descending);
+ doReloadCurrentLocation();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
+ ActivityCompat.invalidateOptionsMenu(this);
+ }// resortViewFiles()
+
+ /**
+ * Switch view type between {@link ViewType#List} and {@link ViewType#Grid}
+ */
+ private void doSwitchViewType() {
+ new LoadingDialog(this, R.string.afc_msg_loading, false) {
+
+ @Override
+ protected void onPreExecute() {
+ // call this first, to let the parent prepare the dialog
+ super.onPreExecute();
+
+ switch (DisplayPrefs.getViewType(FileChooserActivity.this)) {
+ case Grid:
+ DisplayPrefs.setViewType(FileChooserActivity.this, ViewType.List);
+ break;
+ case List:
+ DisplayPrefs.setViewType(FileChooserActivity.this, ViewType.Grid);
+ break;
+ }
+
+ setupViewFiles();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
+ ActivityCompat.invalidateOptionsMenu(FileChooserActivity.this);
+
+ doReloadCurrentLocation();
+ }// onPreExecute()
+
+ @Override
+ protected Object doInBackground(Void... params) {
+ // do nothing :-)
+ return null;
+ }// doInBackground()
+ }.execute();
+ }// doSwitchViewType()
+
+ /**
+ * Confirms user to create new directory.
+ */
+ private void doCreateNewDir() {
+ if (mFileProvider instanceof LocalFileProvider
+ && !Utils.hasPermissions(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
+ Dlg.toast(this, R.string.afc_msg_app_doesnot_have_permission_to_create_files, Dlg._LengthShort);
+ return;
+ }
+
+ final AlertDialog _dlg = Dlg.newDlg(this);
+
+ View view = getLayoutInflater().inflate(R.layout.afc_simple_text_input_view, null);
+ final EditText _textFile = (EditText) view.findViewById(R.id.afc_simple_text_input_view_text1);
+ _textFile.setHint(R.string.afc_hint_folder_name);
+ _textFile.setOnEditorActionListener(new TextView.OnEditorActionListener() {
+
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ if (actionId == EditorInfo.IME_ACTION_DONE) {
+ Ui.hideSoftKeyboard(FileChooserActivity.this, _textFile.getWindowToken());
+ _dlg.getButton(DialogInterface.BUTTON_POSITIVE).performClick();
+ return true;
+ }
+ return false;
+ }
+ });
+
+ _dlg.setView(view);
+ _dlg.setTitle(R.string.afc_cmd_new_folder);
+ _dlg.setIcon(android.R.drawable.ic_menu_add);
+ _dlg.setButton(DialogInterface.BUTTON_POSITIVE, getString(android.R.string.ok),
+ new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ String name = _textFile.getText().toString().trim();
+ if (!FileUtils.isFilenameValid(name)) {
+ Dlg.toast(FileChooserActivity.this, getString(R.string.afc_pmsg_filename_is_invalid, name),
+ Dlg._LengthShort);
+ return;
+ }
+
+ IFile dir = mFileProvider.fromPath(String
+ .format("%s/%s", getLocation().getAbsolutePath(), name));
+ if (dir.mkdir()) {
+ Dlg.toast(FileChooserActivity.this, getString(R.string.afc_msg_done), Dlg._LengthShort);
+ setLocation(getLocation(), null);
+ } else
+ Dlg.toast(FileChooserActivity.this,
+ getString(R.string.afc_pmsg_cannot_create_folder, name), Dlg._LengthShort);
+ }// onClick()
+ });
+ _dlg.show();
+
+ final Button _btnOk = _dlg.getButton(DialogInterface.BUTTON_POSITIVE);
+ _btnOk.setEnabled(false);
+
+ _textFile.addTextChangedListener(new TextWatcher() {
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ _btnOk.setEnabled(FileUtils.isFilenameValid(s.toString().trim()));
+ }
+ });
+ }// doCreateNewDir()
+
+ /**
+ * Updates UI that {@code data} will not be deleted.
+ *
+ * @param data
+ * {@link IFileDataModel}
+ */
+ private void notifyDataModelNotDeleted(IFileDataModel data) {
+ data.setTobeDeleted(false);
+ mFileAdapter.notifyDataSetChanged();
+ }// notifyDataModelNotDeleted(()
+
+ /**
+ * Deletes a file.
+ *
+ * @param file
+ * {@link IFile}
+ */
+ private void doDeleteFile(final IFileDataModel data) {
+ if (mFileProvider instanceof LocalFileProvider
+ && !Utils.hasPermissions(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
+ notifyDataModelNotDeleted(data);
+ Dlg.toast(this, R.string.afc_msg_app_doesnot_have_permission_to_delete_files, Dlg._LengthShort);
+ return;
+ }
+
+ Dlg.confirmYesno(
+ this,
+ getString(R.string.afc_pmsg_confirm_delete_file, data.getFile().isFile() ? getString(R.string.afc_file)
+ : getString(R.string.afc_folder), data.getFile().getName()),
+ new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ new LoadingDialog(FileChooserActivity.this, getString(R.string.afc_pmsg_deleting_file, data
+ .getFile().isFile() ? getString(R.string.afc_file) : getString(R.string.afc_folder),
+ data.getFile().getName()), true) {
+
+ private Thread mThread = FileUtils.createDeleteFileThread(data.getFile(), mFileProvider,
+ true);
+ private final boolean _isFile = data.getFile().isFile();
+
+ private void notifyFileDeleted() {
+ mFileAdapter.remove(data);
+ mFileAdapter.notifyDataSetChanged();
+
+ refreshHistories();
+ // TODO remove all duplicate history items
+
+ Dlg.toast(
+ FileChooserActivity.this,
+ getString(
+ R.string.afc_pmsg_file_has_been_deleted,
+ _isFile ? getString(R.string.afc_file) : getString(R.string.afc_folder),
+ data.getFile().getName()), Dlg._LengthShort);
+ }// notifyFileDeleted()
+
+ @Override
+ protected void onPreExecute() {
+ super.onPreExecute();
+ mThread.start();
+ }// onPreExecute()
+
+ @Override
+ protected Object doInBackground(Void... arg0) {
+ while (mThread.isAlive()) {
+ try {
+ mThread.join(DisplayPrefs._DelayTimeWaitingThreads);
+ } catch (InterruptedException e) {
+ mThread.interrupt();
+ }
+ }
+ return null;
+ }// doInBackground()
+
+ @Override
+ protected void onCancelled() {
+ mThread.interrupt();
+
+ if (data.getFile().exists()) {
+ notifyDataModelNotDeleted(data);
+ Dlg.toast(FileChooserActivity.this, R.string.afc_msg_cancelled, Dlg._LengthShort);
+ } else
+ notifyFileDeleted();
+
+ super.onCancelled();
+ }// onCancelled()
+
+ @Override
+ protected void onPostExecute(Object result) {
+ super.onPostExecute(result);
+
+ if (data.getFile().exists()) {
+ notifyDataModelNotDeleted(data);
+ Dlg.toast(
+ FileChooserActivity.this,
+ getString(R.string.afc_pmsg_cannot_delete_file,
+ data.getFile().isFile() ? getString(R.string.afc_file)
+ : getString(R.string.afc_folder), data.getFile().getName()),
+ Dlg._LengthShort);
+ } else
+ notifyFileDeleted();
+ }// onPostExecute()
+ }.execute();// LoadingDialog
+ }// onClick()
+ }, new DialogInterface.OnCancelListener() {
+
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ notifyDataModelNotDeleted(data);
+ }// onCancel()
+ });
+ }// doDeleteFile()
+
+ /**
+ * As the name means.
+ *
+ * @param filename
+ * @since v1.91
+ */
+ private void doCheckSaveasFilenameAndFinish(String filename) {
+ if (filename.length() == 0) {
+ Dlg.toast(this, R.string.afc_msg_filename_is_empty, Dlg._LengthShort);
+ } else {
+ final IFile _file = mFileProvider.fromPath(getLocation().getAbsolutePath() + File.separator + filename);
+
+ if (!FileUtils.isFilenameValid(filename)) {
+ Dlg.toast(this, getString(R.string.afc_pmsg_filename_is_invalid, filename), Dlg._LengthShort);
+ } else if (_file.isFile()) {
+ Dlg.confirmYesno(FileChooserActivity.this,
+ getString(R.string.afc_pmsg_confirm_replace_file, _file.getName()),
+ new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ doFinish(_file);
+ }
+ });
+ } else if (_file.isDirectory()) {
+ Dlg.toast(this, getString(R.string.afc_pmsg_filename_is_directory, _file.getName()), Dlg._LengthShort);
+ } else
+ doFinish(_file);
+ }
+ }// doCheckSaveasFilenameAndFinish()
+
+ /**
+ * Gets current location.
+ *
+ * @return current location, can be {@code null}.
+ */
+ private IFile getLocation() {
+ return (IFile) mViewLocations.getTag();
+ }// getLocation()
+
+ /**
+ * Sets current location.
+ *
+ * @param path
+ * the path
+ * @param listener
+ * {@link TaskListener}: the second parameter {@code any} in
+ * {@link TaskListener#onFinish(boolean, Object)} will be
+ * {@code path}.
+ */
+ private void setLocation(final IFile path, final TaskListener listener) {
+ setLocation(path, listener, null);
+ }// setLocation()
+
+ /**
+ * Sets current location.
+ *
+ * @param path
+ * the path
+ * @param listener
+ * {@link TaskListener}: the second parameter {@code any} in
+ * {@link TaskListener#onFinish(boolean, Object)} will be
+ * {@code path}.
+ * @param selectedFile
+ * the file should be selected after loading location done. Can
+ * be {@code null}.
+ */
+ private void setLocation(final IFile path, final TaskListener listener, final IFile selectedFile) {
+ new LoadingDialog(this, R.string.afc_msg_loading, true) {
+
+ // IFile[] files = new IFile[0];
+ List files;
+ boolean hasMoreFiles = false;
+ int shouldBeSelectedIdx = -1;
+ /**
+ * Used to focus last directory on list view.
+ */
+ String mLastPath = getLocation() != null ? getLocation().getAbsolutePath() : null;
+
+ @Override
+ protected Object doInBackground(Void... params) {
+ try {
+ if (path.isDirectory() && path.canRead()) {
+ files = new ArrayList();
+ mFileProvider.listAllFiles(path, new IFileFilter() {
+
+ @Override
+ public boolean accept(IFile pathname) {
+ if (mFileProvider.accept(pathname)) {
+ if (files.size() < mFileProvider.getMaxFileCount())
+ files.add(pathname);
+ else
+ hasMoreFiles = true;
+ }
+
+ return false;
+ }// accept()
+ });
+ } else
+ files = null;
+
+ if (files != null) {
+ Collections.sort(files,
+ new FileComparator(mFileProvider.getSortType(), mFileProvider.getSortOrder()));
+ if (selectedFile != null && selectedFile.exists()
+ && selectedFile.parentFile().equalsToPath(path)) {
+ for (int i = 0; i < files.size(); i++) {
+ if (files.get(i).equalsToPath(selectedFile)) {
+ shouldBeSelectedIdx = i;
+ break;
+ }
+ }
+ } else if (mLastPath != null && mLastPath.length() >= path.getAbsolutePath().length()) {
+ for (int i = 0; i < files.size(); i++) {
+ IFile f = files.get(i);
+ if (f.isDirectory() && mLastPath.startsWith(f.getAbsolutePath())) {
+ shouldBeSelectedIdx = i;
+ break;
+ }
+ }
+ }
+ }// if files != null
+ } catch (Throwable t) {
+ setLastException(t);
+ cancel(false);
+ }
+ return null;
+ }// doInBackground()
+
+ @Override
+ protected void onCancelled() {
+ super.onCancelled();
+ Dlg.toast(FileChooserActivity.this, R.string.afc_msg_cancelled, Dlg._LengthShort);
+ }// onCancelled()
+
+ @Override
+ protected void onPostExecute(Object result) {
+ super.onPostExecute(result);
+
+ if (files == null) {
+ Dlg.toast(FileChooserActivity.this, getString(R.string.afc_pmsg_cannot_access_dir, path.getName()),
+ Dlg._LengthShort);
+ if (listener != null)
+ listener.onFinish(false, path);
+ return;
+ }
+
+ // update list view
+
+ createIFileAdapter();
+ for (IFile f : files)
+ mFileAdapter.add(new IFileDataModel(f));
+ mFileAdapter.notifyDataSetChanged();
+
+ // update footers
+
+ mFooterView.setVisibility(hasMoreFiles || mFileAdapter.isEmpty() ? View.VISIBLE : View.GONE);
+ if (hasMoreFiles)
+ mFooterView.setText(getString(R.string.afc_pmsg_max_file_count_allowed,
+ mFileProvider.getMaxFileCount()));
+ else if (mFileAdapter.isEmpty())
+ mFooterView.setText(R.string.afc_msg_empty);
+
+ /*
+ * We use a Runnable to make sure this work. Because if the list
+ * view is handling data, this might not work.
+ */
+ mViewFiles.post(new Runnable() {
+
+ @Override
+ public void run() {
+ if (shouldBeSelectedIdx >= 0 && shouldBeSelectedIdx < mFileAdapter.getCount()) {
+ mViewFiles.setSelection(shouldBeSelectedIdx);
+ } else if (!mFileAdapter.isEmpty())
+ mViewFiles.setSelection(0);
+ }// run()
+ });
+
+ /*
+ * navigation buttons
+ */
+ createLocationButtons(path);
+
+ if (listener != null)
+ listener.onFinish(true, path);
+ }// onPostExecute()
+ }.execute();// new LoadingDialog()
+ }// setLocation()
+
+ /**
+ * Goes to a specified location.
+ *
+ * @param dir
+ * a directory, of course.
+ * @return {@code true} if {@code dir} can be browsed to.
+ * @since v4.3 beta
+ */
+ private boolean goTo(final IFile dir) {
+ if (dir.equalsToPath(getLocation()))
+ return false;
+
+ setLocation(dir, new TaskListener() {
+
+ IFile mLastPath = getLocation();
+
+ @Override
+ public void onFinish(boolean ok, Object any) {
+ if (ok) {
+ mHistory.truncateAfter(mLastPath);
+ mHistory.push(dir);
+ mFullHistory.push(dir);
+ }
+ }
+ });
+ return true;
+ }// goTo()
+
+ private void createLocationButtons(IFile path) {
+ mViewLocations.setTag(path);
+ mViewLocations.removeAllViews();
+
+ LinearLayout.LayoutParams lpBtnLoc = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT);
+ lpBtnLoc.gravity = Gravity.CENTER;
+ LinearLayout.LayoutParams lpDivider = null;
+ LayoutInflater inflater = getLayoutInflater();
+ final int _dim = getResources().getDimensionPixelSize(R.dimen.afc_5dp);
+ int count = 0;
+ while (path != null) {
+ TextView btnLoc = (TextView) inflater.inflate(R.layout.afc_button_location, null);
+ btnLoc.setText(path.parentFile() != null ? path.getName() : getString(R.string.afc_root));
+ btnLoc.setTag(path);
+ btnLoc.setOnClickListener(mBtnLocationOnClickListener);
+ btnLoc.setOnLongClickListener(mBtnLocationOnLongClickListener);
+ mViewLocations.addView(btnLoc, 0, lpBtnLoc);
+
+ if (count++ == 0) {
+ Rect r = new Rect();
+ btnLoc.getPaint().getTextBounds(path.getName(), 0, path.getName().length(), r);
+ if (r.width() >= getResources().getDimensionPixelSize(R.dimen.afc_button_location_max_width)
+ - btnLoc.getPaddingLeft() - btnLoc.getPaddingRight()) {
+ mTxtFullDirName.setText(path.getName());
+ mTxtFullDirName.setVisibility(View.VISIBLE);
+ } else
+ mTxtFullDirName.setVisibility(View.GONE);
+ }
+
+ path = path.parentFile();
+ if (path != null) {
+ View divider = inflater.inflate(R.layout.afc_view_locations_divider, null);
+
+ if (lpDivider == null) {
+ lpDivider = new LinearLayout.LayoutParams(_dim, _dim);
+ lpDivider.gravity = Gravity.CENTER;
+ lpDivider.setMargins(_dim, _dim, _dim, _dim);
+ }
+ mViewLocations.addView(divider, 0, lpDivider);
+ }
+ }
+
+ mViewLocationsContainer.postDelayed(new Runnable() {
+
+ public void run() {
+ mViewLocationsContainer.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
+ }
+ }, 100);
+ }// createLocationButtons()
+
+ /**
+ * Refreshes all the histories. This removes invalid items (which are not
+ * existed anymore).
+ */
+ private void refreshHistories() {
+ HistoryFilter historyFilter = new HistoryFilter() {
+
+ @Override
+ public boolean accept(IFile item) {
+ return !item.isDirectory();
+ }
+ };
+
+ mHistory.removeAll(historyFilter);
+ mFullHistory.removeAll(historyFilter);
+ }// refreshHistories()
+
+ /**
+ * Finishes this activity.
+ *
+ * @param files
+ * list of {@link IFile}
+ */
+ private void doFinish(IFile... files) {
+ List list = new ArrayList();
+ for (IFile f : files)
+ list.add(f);
+ doFinish((ArrayList) list);
+ }
+
+ /**
+ * Finishes this activity.
+ *
+ * @param files
+ * list of {@link IFile}
+ */
+ private void doFinish(ArrayList files) {
+ if (files == null || files.isEmpty()) {
+ setResult(RESULT_CANCELED);
+ finish();
+ return;
+ }
+
+ Intent intent = new Intent();
+
+ // set results
+ intent.putExtra(_Results, files);
+
+ // return flags for further use (in case the caller needs)
+ intent.putExtra(_FilterMode, mFileProvider.getFilterMode());
+ intent.putExtra(_SaveDialog, mIsSaveDialog);
+
+ setResult(RESULT_OK, intent);
+
+ if (DisplayPrefs.isRememberLastLocation(this) && getLocation() != null) {
+ DisplayPrefs.setLastLocation(this, getLocation().getAbsolutePath());
+ } else
+ DisplayPrefs.setLastLocation(this, null);
+
+ finish();
+ }// doFinish()
+
+ /**********************************************************
+ * BUTTON LISTENERS
+ */
+
+ private final View.OnClickListener mBtnGoBackOnClickListener = new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ /*
+ * if user deleted a dir which was one in history, then maybe there
+ * are duplicates, so we check and remove them here
+ */
+ IFile currentLoc = getLocation();
+ IFile preLoc = null;
+ while (currentLoc.equalsToPath(preLoc = mHistory.prevOf(currentLoc)))
+ mHistory.remove(preLoc);
+
+ if (preLoc != null) {
+ setLocation(preLoc, new TaskListener() {
+
+ @Override
+ public void onFinish(boolean ok, Object any) {
+ if (ok) {
+ mViewGoBack.setEnabled(mHistory.prevOf(getLocation()) != null);
+ mViewGoForward.setEnabled(true);
+ mFullHistory.push((IFile) any);
+ }
+ }
+ });
+ } else {
+ mViewGoBack.setEnabled(false);
+ }
+ }
+ };// mBtnGoBackOnClickListener
+
+ private final View.OnClickListener mBtnLocationOnClickListener = new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ if (v.getTag() instanceof IFile)
+ goTo((IFile) v.getTag());
+ }
+ };// mBtnLocationOnClickListener
+
+ private final View.OnLongClickListener mBtnLocationOnLongClickListener = new View.OnLongClickListener() {
+
+ @Override
+ public boolean onLongClick(View v) {
+ if (IFileProvider.FilterMode.FilesOnly.equals(mFileProvider.getFilterMode()) || mIsSaveDialog)
+ return false;
+
+ doFinish((IFile) v.getTag());
+
+ return false;
+ }
+
+ };// mBtnLocationOnLongClickListener
+
+ private final View.OnClickListener mBtnGoForwardOnClickListener = new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ /*
+ * if user deleted a dir which was one in history, then maybe there
+ * are duplicates, so we check and remove them here
+ */
+ IFile currentLoc = getLocation();
+ IFile nextLoc = null;
+ while (currentLoc.equalsToPath(nextLoc = mHistory.nextOf(currentLoc)))
+ mHistory.remove(nextLoc);
+
+ if (nextLoc != null) {
+ setLocation(nextLoc, new TaskListener() {
+
+ @Override
+ public void onFinish(boolean ok, Object any) {
+ if (ok) {
+ mViewGoBack.setEnabled(true);
+ mViewGoForward.setEnabled(mHistory.nextOf(getLocation()) != null);
+ mFullHistory.push((IFile) any);
+ }
+ }
+ });
+ } else {
+ mViewGoForward.setEnabled(false);
+ }
+ }
+ };// mBtnGoForwardOnClickListener
+
+ private final View.OnLongClickListener mBtnGoBackForwardOnLongClickListener = new View.OnLongClickListener() {
+
+ @Override
+ public boolean onLongClick(View v) {
+ ViewFilesContextMenuUtils.doShowHistoryContents(FileChooserActivity.this, mFileProvider, mFullHistory,
+ getLocation(), new TaskListener() {
+
+ @Override
+ public void onFinish(boolean ok, Object any) {
+ mHistory.removeAll(new HistoryFilter() {
+
+ @Override
+ public boolean accept(IFile item) {
+ return mFullHistory.indexOf(item) < 0;
+ }
+ });
+
+ if (any instanceof IFile) {
+ setLocation((IFile) any, new TaskListener() {
+
+ @Override
+ public void onFinish(boolean ok, Object any) {
+ if (ok)
+ mHistory.notifyHistoryChanged();
+ }
+ });
+ } else if (mHistory.isEmpty()) {
+ mHistory.push(getLocation());
+ mFullHistory.push(getLocation());
+ }
+ }// onFinish()
+ });
+ return false;
+ }// onLongClick()
+ };// mBtnGoBackForwardOnLongClickListener
+
+ private final TextView.OnEditorActionListener mTxtFilenameOnEditorActionListener = new TextView.OnEditorActionListener() {
+
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ if (actionId == EditorInfo.IME_ACTION_DONE) {
+ Ui.hideSoftKeyboard(FileChooserActivity.this, mTxtSaveas.getWindowToken());
+ mBtnOk.performClick();
+ return true;
+ }
+ return false;
+ }
+ };// mTxtFilenameOnEditorActionListener
+
+ private final View.OnClickListener mBtnOk_SaveDialog_OnClickListener = new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ Ui.hideSoftKeyboard(FileChooserActivity.this, mTxtSaveas.getWindowToken());
+ String filename = mTxtSaveas.getText().toString().trim();
+ doCheckSaveasFilenameAndFinish(filename);
+ }
+ };// mBtnOk_SaveDialog_OnClickListener
+
+ private final View.OnClickListener mBtnOk_OpenDialog_OnClickListener = new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ List list = new ArrayList();
+ for (int i = 0; i < mViewFiles.getAdapter().getCount(); i++) {
+ // NOTE: header and footer don't have data
+ Object obj = mViewFiles.getAdapter().getItem(i);
+ if (obj instanceof IFileDataModel) {
+ IFileDataModel dm = (IFileDataModel) obj;
+ if (dm.isSelected())
+ list.add(dm.getFile());
+ }
+ }
+ doFinish((ArrayList) list);
+ }
+ };// mBtnOk_OpenDialog_OnClickListener
+
+ /*
+ * LIST VIEW HELPER
+ */
+
+ private GestureDetector mListviewFilesGestureDetector;
+
+ private void initGestureDetector() {
+ mListviewFilesGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
+
+ private Object getData(float x, float y) {
+ int i = getSubViewId(x, y);
+ if (i >= 0)
+ return mViewFiles.getItemAtPosition(mViewFiles.getFirstVisiblePosition() + i);
+ return null;
+ }// getSubView()
+
+ /**
+ * Gets {@link IFileDataModel} from {@code e}.
+ *
+ * @param e
+ * {@link MotionEvent}.
+ * @return the data model, or {@code null} if not available.
+ */
+ private IFileDataModel getDataModel(MotionEvent e) {
+ Object o = getData(e.getX(), e.getY());
+ return o instanceof IFileDataModel ? (IFileDataModel) o : null;
+ }// getDataModel()
+
+ private int getSubViewId(float x, float y) {
+ Rect r = new Rect();
+ for (int i = 0; i < mViewFiles.getChildCount(); i++) {
+ mViewFiles.getChildAt(i).getHitRect(r);
+ if (r.contains((int) x, (int) y))
+ return i;
+ }
+
+ return -1;
+ }// getSubViewId()
+
+ @Override
+ public void onLongPress(MotionEvent e) {
+ // do nothing
+ }// onLongPress()
+
+ @Override
+ public boolean onSingleTapConfirmed(MotionEvent e) {
+ // do nothing
+ return false;
+ }// onSingleTapConfirmed()
+
+ @Override
+ public boolean onDoubleTap(MotionEvent e) {
+ if (mDoubleTapToChooseFiles) {
+ if (mIsMultiSelection)
+ return false;
+
+ IFileDataModel data = getDataModel(e);
+ if (data == null)
+ return false;
+
+ if (data.getFile().isDirectory()
+ && IFileProvider.FilterMode.FilesOnly.equals(mFileProvider.getFilterMode()))
+ return false;
+
+ // if mFilterMode == DirectoriesOnly, files won't be
+ // shown
+
+ if (mIsSaveDialog) {
+ if (data.getFile().isFile()) {
+ mTxtSaveas.setText(data.getFile().getName());
+ doCheckSaveasFilenameAndFinish(data.getFile().getName());
+ } else
+ return false;
+ } else
+ doFinish(data.getFile());
+ }// double tap to choose files
+ else {
+ // do nothing
+ return false;
+ }// single tap to choose files
+
+ return true;
+ }// onDoubleTap()
+
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+ final int _max_y_distance = 19;// 10 is too short :-D
+ final int _min_x_distance = 80;
+ final int _min_x_velocity = 200;
+ if (Math.abs(e1.getY() - e2.getY()) < _max_y_distance
+ && Math.abs(e1.getX() - e2.getX()) > _min_x_distance && Math.abs(velocityX) > _min_x_velocity) {
+ Object o = getData(e1.getX(), e1.getY());
+ if (o instanceof IFileDataModel) {
+ ((IFileDataModel) o).setTobeDeleted(true);
+ mFileAdapter.notifyDataSetChanged();
+ doDeleteFile((IFileDataModel) o);
+ }
+ }
+
+ /*
+ * always return false to let the default handler draw the item
+ * properly
+ */
+ return false;
+ }// onFling()
+ });// mListviewFilesGestureDetector
+ }// initGestureDetector()
+
+ private final AdapterView.OnItemClickListener mViewFilesOnItemClickListener = new AdapterView.OnItemClickListener() {
+
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ IFileDataModel data = mFileAdapter.getItem(position);
+
+ if (data.getFile().isDirectory()) {
+ goTo(data.getFile());
+ return;
+ }
+
+ if (mIsSaveDialog)
+ mTxtSaveas.setText(data.getFile().getName());
+
+ if (mDoubleTapToChooseFiles) {
+ // do nothing
+ return;
+ }// double tap to choose files
+ else {
+ if (mIsMultiSelection)
+ return;
+
+ if (mIsSaveDialog)
+ doCheckSaveasFilenameAndFinish(data.getFile().getName());
+ else
+ doFinish(data.getFile());
+ }// single tap to choose files
+ }// onItemClick()
+ };// mViewFilesOnItemClickListener
+
+ private final AdapterView.OnItemLongClickListener mViewFilesOnItemLongClickListener = new AdapterView.OnItemLongClickListener() {
+
+ @Override
+ public boolean onItemLongClick(AdapterView> parent, View view, int position, long id) {
+ IFileDataModel data = mFileAdapter.getItem(position);
+
+ if (mDoubleTapToChooseFiles) {
+ // do nothing
+ }// double tap to choose files
+ else {
+ if (!mIsSaveDialog
+ && !mIsMultiSelection
+ && data.getFile().isDirectory()
+ && (IFileProvider.FilterMode.DirectoriesOnly.equals(mFileProvider.getFilterMode()) || IFileProvider.FilterMode.FilesAndDirectories
+ .equals(mFileProvider.getFilterMode()))) {
+ doFinish(data.getFile());
+ }
+ }// single tap to choose files
+
+ // notify that we already handled long click here
+ return true;
+ }// onItemLongClick()
+ };// mViewFilesOnItemLongClickListener
+}
\ No newline at end of file
diff --git a/android-filechooser/src/group/pals/android/lib/ui/filechooser/IFileAdapter.java b/android-filechooser/src/group/pals/android/lib/ui/filechooser/IFileAdapter.java
new file mode 100644
index 0000000..e521757
--- /dev/null
+++ b/android-filechooser/src/group/pals/android/lib/ui/filechooser/IFileAdapter.java
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2012 Hai Bison
+ *
+ * See the file LICENSE at the root directory of this project for copying
+ * permission.
+ */
+
+package group.pals.android.lib.ui.filechooser;
+
+import group.pals.android.lib.ui.filechooser.io.IFile;
+import group.pals.android.lib.ui.filechooser.io.IFileFilter;
+import group.pals.android.lib.ui.filechooser.prefs.DisplayPrefs;
+import group.pals.android.lib.ui.filechooser.prefs.DisplayPrefs.FileTimeDisplay;
+import group.pals.android.lib.ui.filechooser.services.IFileProvider;
+import group.pals.android.lib.ui.filechooser.services.IFileProvider.FilterMode;
+import group.pals.android.lib.ui.filechooser.utils.Converter;
+import group.pals.android.lib.ui.filechooser.utils.DateUtils;
+import group.pals.android.lib.ui.filechooser.utils.FileUtils;
+import group.pals.android.lib.ui.filechooser.utils.ui.ContextMenuUtils;
+import group.pals.android.lib.ui.filechooser.utils.ui.LoadingDialog;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import android.content.Context;
+import android.graphics.Paint;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceFragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.GridView;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+/**
+ * The adapter to be used in {@link android.widget.ListView}
+ *
+ * @author Hai Bison
+ *
+ */
+public class IFileAdapter extends BaseAdapter {
+
+ /**
+ * Used for logging...
+ */
+ public static final String _ClassName = IFileAdapter.class.getName();
+
+ private final Integer[] mAdvancedSelectionOptions;
+ private final IFileProvider.FilterMode mFilterMode;
+ private final Context mContext;
+ private final FileTimeDisplay mFileTimeDisplay;
+
+ private List mData;
+ private LayoutInflater mInflater;
+ private boolean mMultiSelection;
+
+ /**
+ * Creates new {@link IFileAdapter}
+ *
+ * @param context
+ * {@link Context}
+ * @param objects
+ * the data
+ * @param filterMode
+ * see {@link IFileProvider.FilterMode}
+ * @param multiSelection
+ * see {@link FileChooserActivity#_MultiSelection}
+ */
+ public IFileAdapter(Context context, List objects, IFileProvider.FilterMode filterMode,
+ boolean multiSelection) {
+ // DO NOT use getApplicationContext(), due to this bug:
+ // http://stackoverflow.com/questions/2634991/android-1-6-android-view-windowmanagerbadtokenexception-unable-to-add-window
+ // http://code.google.com/p/android/issues/detail?id=11199
+ mContext = context;
+ mData = objects;
+ mInflater = LayoutInflater.from(mContext);
+ mFilterMode = filterMode;
+ mMultiSelection = multiSelection;
+
+ switch (mFilterMode) {
+ case DirectoriesOnly:
+ case FilesOnly:
+ mAdvancedSelectionOptions = new Integer[] { R.string.afc_cmd_advanced_selection_all,
+ R.string.afc_cmd_advanced_selection_none, R.string.afc_cmd_advanced_selection_invert };
+ break;// DirectoriesOnly and FilesOnly
+ default:
+ mAdvancedSelectionOptions = new Integer[] { R.string.afc_cmd_advanced_selection_all,
+ R.string.afc_cmd_advanced_selection_none, R.string.afc_cmd_advanced_selection_invert,
+ R.string.afc_cmd_select_all_files, R.string.afc_cmd_select_all_folders };
+ break;// FilesAndDirectories
+ }
+
+ mFileTimeDisplay = new FileTimeDisplay(DisplayPrefs.isShowTimeForOldDaysThisYear(mContext),
+ DisplayPrefs.isShowTimeForOldDays(mContext));
+ }// IFileAdapter
+
+ @Override
+ public void notifyDataSetChanged() {
+ updateEnvironments();
+ super.notifyDataSetChanged();
+ }// notifyDataSetChanged()
+
+ /**
+ * Updates environments such as file time display... For example, this
+ * method is useful if you have {@link PreferenceActivity} or
+ * {@link PreferenceFragment} to let the user change preferences. So after
+ * the user changed preferences, you just simply call this method and
+ * {@link #notifyDataSetChanged()}, or just call
+ * {@link #notifyDataSetChanged()} (which also calls this method) to update
+ * the UI of this adapter.
+ */
+ public void updateEnvironments() {
+ mFileTimeDisplay.setShowTimeForOldDaysThisYear(DisplayPrefs.isShowTimeForOldDaysThisYear(mContext));
+ mFileTimeDisplay.setShowTimeForOldDays(DisplayPrefs.isShowTimeForOldDays(mContext));
+ }// updateEnvironments()
+
+ @Override
+ public int getCount() {
+ return mData != null ? mData.size() : 0;
+ }
+
+ @Override
+ public IFileDataModel getItem(int position) {
+ return mData != null ? mData.get(position) : null;
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ public boolean isMultiSelection() {
+ return mMultiSelection;
+ }
+
+ /**
+ * Sets multi-selection mode.
+ * Note:
+ *
+ *
If {@code v = true}, this method will also update adapter.
+ *
+ *
If {@code v = false}, this method will iterate all items, set their
+ * selection to {@code false}. So you should consider using a
+ * {@link LoadingDialog}. This will not update adapter, you must do it
+ * yourself.
+ *
+ * @param v
+ * {@code true} if multi-selection is enabled
+ */
+ public void setMultiSelection(boolean v) {
+ if (mMultiSelection != v) {
+ mMultiSelection = v;
+ if (mMultiSelection) {
+ notifyDataSetChanged();
+ } else {
+ if (getCount() > 0) {
+ for (int i = 0; i < mData.size(); i++)
+ mData.get(i).setSelected(false);
+ }
+ }
+ }
+ }// setMultiSelection()
+
+ /**
+ * Gets selected items.
+ *
+ * @return list of selected items, can be empty but never be {@code null}
+ */
+ public ArrayList getSelectedItems() {
+ ArrayList res = new ArrayList();
+
+ for (int i = 0; i < getCount(); i++)
+ if (getItem(i).isSelected())
+ res.add(getItem(i));
+
+ return res;
+ }// getSelectedItems()
+
+ /**
+ * Adds an {@code item}. Note: this does not notify the adapter that
+ * data set has been changed.
+ *
+ * @param item
+ * {@link IFileDataModel}
+ */
+ public void add(IFileDataModel item) {
+ if (mData != null)
+ mData.add(item);
+ }
+
+ /**
+ * Removes {@code item}. Note: this does not notify the adapter that
+ * data set has been changed.
+ *
+ * @param item
+ * {@link IFileDataModel}
+ */
+ public void remove(IFileDataModel item) {
+ if (mData != null) {
+ mData.remove(item);
+ }
+ }// remove()
+
+ /**
+ * Removes all {@code items}. Note: this does not notify the adapter
+ * that data set has been changed.
+ *
+ * @param items
+ * the items you want to remove.
+ */
+ public void removeAll(Collection items) {
+ if (mData != null)
+ mData.removeAll(items);
+ }// removeAll()
+
+ /**
+ * Clears all items.
+ * Note:
+ *
This does not notify the adapter that data set has been changed.