/* IfExplorer, an open source file manager for the Android system. Copyright (C) 2014 Kevin Lin <chenbin.lin@tpv-tech.com> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.sparseboolean.ifexplorer; import gem.android.widget.SlidingDrawerEx; import gem.com.slidinglayer.SlidingLayer; import gem.kevin.innov.FilePathUrlManager; import gem.kevin.provider.ClipSourceProvider; import gem.kevin.task.FileOperationTask; import gem.kevin.task.FileOperationTask.FileOperationOptions; import gem.kevin.util.DataUtil; import gem.kevin.util.FileUtil; import gem.kevin.util.FileUtil.SimpleCopyCallback; import gem.kevin.util.FileUtil.SimpleCreateCallback; import gem.kevin.util.FileUtil.SimpleDeleteCallback; import gem.kevin.util.FileUtil.SimpleRenameCallback; import gem.kevin.util.StorageUtil; import gem.kevin.widget.ClipItemAdapter; import gem.kevin.widget.ClipItemAdapter.DeleteDelegate; import gem.kevin.widget.ClipItemAdapter.PasteDelegate; import gem.kevin.widget.DropableGridView; import gem.kevin.widget.DropableListView; import gem.kevin.widget.FileClip; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.app.SearchManager; import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.media.MediaScannerConnection; import android.media.MediaScannerConnection.OnScanCompletedListener; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.preference.PreferenceManager; import android.provider.MediaStore; import android.text.format.Time; import android.util.Log; import android.util.SparseBooleanArray; import android.view.ActionMode; 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.View.OnClickListener; import android.view.View.OnTouchListener; import android.widget.AbsListView; import android.widget.AbsListView.MultiChoiceModeListener; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.EditText; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.RelativeLayout.LayoutParams; import android.widget.SearchView; import android.widget.SearchView.OnQueryTextListener; import android.widget.TextView; import android.widget.Toast; import com.sparseboolean.ifexplorer.IfAppController.FileDataGridAdapter; import com.sparseboolean.ifexplorer.IfAppController.FileDataListAdapter; import com.sparseboolean.ifexplorer.ui.ClipHistoryAdapter; import com.sparseboolean.ifexplorer.ui.ClipHistoryAdapter.ClipHistoryCallback; import com.sparseboolean.ifexplorer.ui.DeviceDataAdapter; import com.sparseboolean.ifexplorer.ui.FavoriteDataAdapter; import com.sparseboolean.ifexplorer.ui.FilePathNavigator; import com.sparseboolean.ifexplorer.ui.TaskGroupListWidget; public class IfExplorer extends Activity implements OnTouchListener, OnItemClickListener, ClipHistoryCallback, PasteDelegate, DeleteDelegate, IfAppController.DeviceDataListener, IfAppController.UiCallback, FilePathNavigator.NavigationCallback, OnQueryTextListener, SimpleCreateCallback, SimpleDeleteCallback, SimpleRenameCallback, SimpleCopyCallback { public class FileMultiChoiceListener implements MultiChoiceModeListener { private CheckBox selectAllCheckBox; public HashSet<Object> getSelections() { HashSet<Object> result = new HashSet<Object>(); SparseBooleanArray choices = mCurrentShownFileList .getCheckedItemPositions(); ListAdapter adapter = mCurrentShownFileList.getAdapter(); int total = adapter.getCount(); for (int i = 0; i < total; i++) { if (choices.get(i)) { result.add(adapter.getItem(i)); } } return result; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { switch (item.getItemId()) { case R.id.menu_copyFile: MultiChoiceConsumeOptions copyOptions = new MultiChoiceConsumeOptions( ClipHistoryAdapter.CLIP_COPY); mClipHistoryAdapter.consumeChoice( mFileListMultiChoiceListener.getSelections(), copyOptions); mode.finish(); mOptionPasteAvailable = true; IfExplorer.this.invalidateOptionsMenu(); return true; case R.id.menu_cutFile: MultiChoiceConsumeOptions cutOptions = new MultiChoiceConsumeOptions( ClipHistoryAdapter.CLIP_CUT); mClipHistoryAdapter.consumeChoice( mFileListMultiChoiceListener.getSelections(), cutOptions); mode.finish(); mOptionPasteAvailable = true; IfExplorer.this.invalidateOptionsMenu(); return true; case R.id.menu_deleteFile: MultiChoiceConsumeOptions deleteOptions = new MultiChoiceConsumeOptions( ClipHistoryAdapter.CLIP_DELETE); mClipHistoryAdapter.consumeChoice( mFileListMultiChoiceListener.getSelections(), deleteOptions); mode.finish(); return true; case R.id.menu_renameFile: MultiChoiceConsumeOptions renameOptions = new MultiChoiceConsumeOptions( ClipHistoryAdapter.CLIP_RENAME_SINGLE); mClipHistoryAdapter.consumeChoice( mFileListMultiChoiceListener.getSelections(), renameOptions); mode.finish(); return true; case R.id.menu_detail: IfExplorer.this.showDetailDialog(mFileListMultiChoiceListener .getSelections()); mode.finish(); return true; default: return false; } } @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { MenuInflater menuInflater = getMenuInflater(); menuInflater.inflate(R.menu.file_list_select_menu, menu); View customView = LayoutInflater.from(IfExplorer.this).inflate( R.layout.select_mode_custom_views, null); selectAllCheckBox = (CheckBox) customView .findViewById(R.id.select_all_checkbox); selectAllCheckBox .setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { for (int i = 0; i < mCurrentShownFileList.getAdapter() .getCount(); i++) { mCurrentShownFileList.setItemChecked(i, isChecked); } } }); mode.setCustomView(customView); setSubtitle(mode); updateUiForActionMode(true, true); IfExplorer.this.setActivatingActionMode(mode); return true; } @Override public void onDestroyActionMode(ActionMode mode) { updateUiForActionMode(false, true); IfExplorer.this.setActivatingActionMode(null); } @Override public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) { setSubtitle(mode); View targetItemView = mCurrentShownFileList.getChildAt(position); if (targetItemView != null) { CheckBox checkbox = (CheckBox) targetItemView .findViewById(R.id.file_selected); if (checkbox != null) { checkbox.setChecked(checked); } } mOptionRenameAvailable = (mCurrentShownFileList.getCheckedItemCount() == 1); HashSet<Object> selections = getSelections(); for (Object selection : selections) { if (selection instanceof FileItem) { if (((FileItem) selection).isSystemFile()) { mSelectionContainSysFiles = true; break; } else { mSelectionContainSysFiles = false; } } } mode.invalidate(); // Kevin Lin // It might be a bug that the associated list won't get correct // display for CheckBox of the checked item // if the items are not in the first page(In vision without scroll // the list) // So we force to refresh the list mAppController.forceRefreshFileListView(); } @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { MenuItem renameItem = menu.findItem(R.id.menu_renameFile); MenuItem deleteItem = menu.findItem(R.id.menu_deleteFile); MenuItem copyItem = menu.findItem(R.id.menu_copyFile); MenuItem cutItem = menu.findItem(R.id.menu_cutFile); // visibility // renameItem.setVisible(sCurrentDir != null ? true : false); // deleteItem.setVisible(sCurrentDir != null ? true : false); renameItem.setVisible(true); deleteItem.setVisible(true); // enable/disable renameItem .setEnabled((mOptionRenameAvailable && !mSelectionContainSysFiles) ? true : false); deleteItem.setEnabled(!mSelectionContainSysFiles ? true : false); copyItem.setEnabled(!mSelectionContainSysFiles ? true : false); cutItem.setEnabled(!mSelectionContainSysFiles ? true : false); setSubtitle(mode); return true; } private void setSubtitle(ActionMode actionMode) { int totalNum = mCurrentShownFileList.getCount(); int checkedNum = mCurrentShownFileList.getCheckedItemCount(); // Could possibly restore from a savedStateInstance, // with a wrong count of current show list if (totalNum == 0 && mSavedStateInstatnce != null) { totalNum = mSavedStateInstatnce.getInt( KEY_SAVE_FILE_LIST_TOTAL_NUM, 0); checkedNum = mSavedStateInstatnce.getInt( KEY_SAVE_FILE_LIST_SELECTED_NUM, 0); if (totalNum == checkedNum && totalNum != 0) { selectAllCheckBox.setChecked(true); } } String title = String.format("%d/%d", checkedNum, totalNum); // actionMode.setTitle(title); TextView textView = (TextView) actionMode.getCustomView() .findViewById(R.id.selected_count); if (textView != null) { textView.setText(title); } } private void updateUiForActionMode(boolean inActionMode, boolean clearChoice) { Log.i(TAG, "updateUiForActionMode " + inActionMode); // sliding layer if (mLibrarySlidingLayer != null) { mLibrarySlidingLayer.setVisibility(inActionMode ? View.GONE : View.VISIBLE); } mCurrentShownFileList.setVisibility(View.VISIBLE); mNavBackwardButton.setVisibility(inActionMode ? View.INVISIBLE : View.VISIBLE); mNavForwardButton.setVisibility(inActionMode ? View.INVISIBLE : View.VISIBLE); mLibrarySwitchButton.setVisibility(inActionMode ? View.INVISIBLE : (mLibrarySlidingLayer != null ? View.VISIBLE : View.INVISIBLE)); if (inActionMode) { mPathNavigator.switchToIndicateMode(); } else { mPathNavigator.switchToNavigateMode(); } // file list if (mAppController.hasActionModeBunchedViews() && !inActionMode) { Log.i("FileMultiChoiceListener", "split bunched up views if we are not in action mode."); mAppController.splitActionModeBunchedViews(); } } } public static class MultiChoiceConsumeOptions { public String consumeDescription = null; public MultiChoiceConsumeOptions(String consumeDescription) { this.consumeDescription = consumeDescription; } } public interface MultiChoiceConsumer { public boolean consumeChoice(HashSet<Object> choices, MultiChoiceConsumeOptions options); } private static final int VIEW_AS_LIST = 1; private static final int VIEW_AS_GRID = 2; private static final int DEVICE_UNKNOWN = 0; private static final int DEVICE_TAB_LAND = 1; private static final int DEVICE_TAB_PORT = 2; private static final int DEVICE_PHONE_LAND = 3; private static final int DEVICE_PHONE_PORT = 4; private static final String KEY_VIEW_MODE = "view_mode"; private static final String KEY_SAVE_LOCATION = "location"; private static final String KEY_SAVE_BROWSE_HISTORY = "browse_history"; private static final String KEY_SAVE_HISTORY_POSITION = "history_position"; private static final String KEY_SAVE_SLIDING_LAYER_OPEN = "sliding_open"; private static final String KEY_SAVE_SEARCH_RESULTS = "search_results"; private static final String KEY_SAVE_CACHED_AUDIO_FILEPATHS = "audio_file_paths"; private static final String KEY_SAVE_CACHED_VIDEO_FILEPATHS = "video_file_paths"; private static final String KEY_SAVE_CACHED_APK_FILEPATHS = "apk_file_paths"; private static final String KEY_SAVE_FILE_LIST_TOTAL_NUM = "file_list_total_num"; private static final String KEY_SAVE_FILE_LIST_SELECTED_NUM = "file_list_selected_num"; private static final String TAG = "IfExplorer"; private static final boolean KLOG = true; private static final boolean tempLOG = false; private Bundle mSavedStateInstatnce; public static String sCurrentDir = null; public static void setCurrentDir(String currentPath) { if (FilePathUrlManager.isExistingDirPath(currentPath)) { sCurrentDir = currentPath; } else { sCurrentDir = null; } } private FilePathUrlManager mFileManager; private String mInitLocation = null; private ArrayList<String> mSavedBrowseHistory = null; private int mSavedHistoryPosition = -1; private IfAppController mAppController; private FileDataListAdapter mFileDataListAdapter; private FileDataGridAdapter mFileDataGridAdapter; private AbsListView mCurrentShownFileList; private int mCurrentViewMode = VIEW_AS_GRID; private DropableListView mFileListView; private DropableGridView mFileGridView; private int mDeviceDisplayType; private View mAddressBar; private FilePathNavigator mPathNavigator; private SearchView mSearchView; private ImageView mLibrarySwitchButton; private ImageView mCloudSwitchButton; private ImageView mNavBackwardButton; private ImageView mNavForwardButton; private HashSet<SlidingLayer> mSlidingLayers = new HashSet<SlidingLayer>(); private HashMap<View, SlidingLayer> mSwitchSlidingLayerMap = new HashMap<View, SlidingLayer>(); private SlidingLayer mLibrarySlidingLayer; private SlidingLayer mCloudSlidingLayer; private SlidingDrawerEx mClipBoardDrawer; private View mClipBoardIndicator; private Button mButtonClearClipboard; private Button mButtonCloseClipboard; private ListView mClipHistoryListView; private ClipHistoryAdapter mClipHistoryAdapter; private boolean mOptionPasteAvailable = false; private boolean mOptionRenameAvailable = false; private boolean mSelectionContainSysFiles = false; /* Storage monitoring */ private IntentFilter mStorageIntentFilter; private BroadcastReceiver mStorageBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); String path = intent.getData().getPath(); Log.i(TAG, "ACTION: " + action + " happened on path: " + path); mAppController.resetCachedFilePaths(); if (mAppController != null) { if (mFileManager.getCurrentUrl().contains(path)) { if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED) || action.equals(Intent.ACTION_MEDIA_BAD_REMOVAL) || action.equals(Intent.ACTION_MEDIA_EJECT) || action.equals(Intent.ACTION_MEDIA_REMOVED)) { // Update to a null directory at once. // It's a tricky to make IF release possible possessive // file descriptors // so it won't get killed by ActivityManager mAppController.updateDirectory(null); mAppController.updateDirectory(mFileManager .getNextUrlContent(StorageUtil.getHomeDir(), true, false)); } else if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) { mAppController.updateDirectory(mFileManager .refreshUrlContent()); } } else { int searchType = -1; String filePattern = FilePathUrlManager .getSmartPattern(mFileManager.getCurrentUrl()); if (filePattern != null) { if (filePattern .endsWith(FilePathUrlManager.SMART_MUSIC)) { searchType = StorageUtil.TYPE_AUDIO; } else if (filePattern .endsWith(FilePathUrlManager.SMART_MOVIES)) { searchType = StorageUtil.TYPE_VIDEO; } else if (filePattern .endsWith(FilePathUrlManager.SMART_IMAGE)) { searchType = StorageUtil.TYPE_IMAGE; } else if (filePattern .endsWith(FilePathUrlManager.SMART_APK)) { searchType = StorageUtil.TYPE_APKFILE; } mAppController.searchFiles(searchType, FileUtil.FILE_PATTERN_ALL, "/", IfConfig.MAX_SEARCH_DEPTH, false); } else { mAppController.updateDirectory(mFileManager .refreshUrlContent()); } } if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) { mAppController.updateStorageDevice(path, Environment.MEDIA_MOUNTED, true); } else if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED)) { mAppController.updateStorageDevice(path, Environment.MEDIA_UNMOUNTED, true); // URL starts with this path now become invalid mFileManager.removeInvalidUrls(path); } else if (action.equals(Intent.ACTION_MEDIA_REMOVED) || action.equals(Intent.ACTION_MEDIA_EJECT)) { mAppController.updateStorageDevice(path, Environment.MEDIA_REMOVED, true); mFileManager.removeInvalidUrls(path); } else if (action.equals(Intent.ACTION_MEDIA_BAD_REMOVAL)) { mAppController.updateStorageDevice(path, Environment.MEDIA_BAD_REMOVAL, true); mFileManager.removeInvalidUrls(path); } else { return; } refreshTaskGroups(); preScanCategoriedFiles(); } } }; // Task groups private HashSet<TaskGroupListWidget> mMiniPanelWidgets = new HashSet<TaskGroupListWidget>(); // Favorites private TaskGroupListWidget mFavoritesMiniWidget; // Devices private TaskGroupListWidget mInternalStorageMiniWidget; private TaskGroupListWidget mSdcardMiniWidget; private TaskGroupListWidget mUsb0StorageMiniWidget; private TaskGroupListWidget mUsb1StorageMiniWidget; private TaskGroupListWidget mUsb2StorageMiniWidget; private TaskGroupListWidget mUsb3StorageMiniWidget; private TaskGroupListWidget mUsb4StorageMiniWidget; private TaskGroupListWidget mUsb5StorageMiniWidget; private TaskGroupListWidget mStorageA_MiniWidget; private TaskGroupListWidget mStorageB_MiniWidget; private TaskGroupListWidget mStorageC_MiniWidget; private TaskGroupListWidget mStorageD_MiniWidget; private static final int kTagTaskGroupBase = 0; private FileOperationTaskAutoExecutor mFileOpAutoExecutor = new FileOperationTaskAutoExecutor(); private FileMultiChoiceListener mFileListMultiChoiceListener; private ActionMode mActivatingActionMode; @Override public void cancelDelete(ClipItemAdapter assignor, boolean rollback) { // TODO: implement roll back function HashSet<FileOperationTask> combinedTasks = assignor .getOneShotClipTask(); if (combinedTasks != null) { for (FileOperationTask task : combinedTasks) { mFileOpAutoExecutor.dequeueFileOpTask(task); } } } @Override public void cancelPaste(ClipItemAdapter assignor, boolean rollback) { // TODO: implement roll back function HashSet<FileOperationTask> combinedTasks = assignor .getOneShotClipTask(); if (combinedTasks != null) { for (FileOperationTask task : combinedTasks) { mFileOpAutoExecutor.dequeueFileOpTask(task); } } } @Override public void doDelete(HashSet<FileClip> clipToDelete, ClipItemAdapter assignor) { if (clipToDelete == null) { return; } if (clipToDelete.size() != 0) { Time time = new Time(); time.setToNow(); String taskId = String.format("%02d:%02d:%02d-delete", time.hour, time.minute, time.second); FileOperationOptions options = FileOperationTask .makeDefaultOptions(FileOperationTask.OP_TYPE_DELETE_FILE); HashSet<FileOperationTask> combinedTasks = new HashSet<FileOperationTask>(); FileOperationTask deleteTask = null; ArrayList<String> toDelete = new ArrayList<String>(); for (FileClip clip : clipToDelete) { float clipType = clip.getType(); if (ClipSourceProvider.CLIP_TYPE_DELETE_SOURCE == clipType) { toDelete.add(clip.getFilePath()); } } deleteTask = new FileOperationTask(this, taskId, options, toDelete, assignor); combinedTasks.add(deleteTask); assignor.setOneShotClipTask(combinedTasks); mFileOpAutoExecutor.enqueueFileOpTask(deleteTask); } } @Override public void doPaste(HashSet<FileClip> clipToPaste, String pasteDir, ClipItemAdapter assignor) { mOptionPasteAvailable = false; invalidateOptionsMenu(); if (clipToPaste == null) { return; } if (clipToPaste.size() != 0) { boolean doCopy = false; boolean doCut = false; ArrayList<String> toCopy = new ArrayList<String>(); ArrayList<String> toCut = new ArrayList<String>(); for (FileClip clip : clipToPaste) { float clipType = clip.getType(); if (ClipSourceProvider.CLIP_TYPE_COPY_SOURCE == clipType) { doCopy = true; toCopy.add(clip.getFilePath()); } else if (ClipSourceProvider.CLIP_TYPE_CUT_SOURCE == clipType) { doCut = true; toCut.add(clip.getFilePath()); } } if (!doCopy && !doCut) { Log.i(TAG, "No actual copy or cut tasks!"); return; } FileOperationOptions options; Time time = new Time(); time.setToNow(); String taskId; // TODO: find out why a three level control (ClipItemAdapter => // ClipTask => FileOperationTask // can't synchronize UI? (CPU over load?) // ClipTask clipTask = new ClipTask(this); HashSet<FileOperationTask> combinedTasks = new HashSet<FileOperationTask>(); FileOperationTask copyTask = null; FileOperationTask renameTask = null; FileOperationTask moveTask = null; if (doCopy) { options = FileOperationTask .makeDefaultOptions(FileOperationTask.OP_TYPE_COPY_FILE); options.targetDirectoryPath = pasteDir; taskId = String.format("%02d:%02d:%02d-copy", time.hour, time.minute, time.second); copyTask = new FileOperationTask(this, taskId, options, toCopy, assignor); combinedTasks.add(copyTask); } if (doCut) { // Filter the two types of 'Cut' // (1) Moving on same file system => Rename // (2) Moving between different file system => Copy and delete ArrayList<String> toMove = new ArrayList<String>(); ArrayList<String> toRename = new ArrayList<String>(); for (String srcFilePath : toCut) { try { if (onSameFileSystem(srcFilePath, pasteDir)) { toRename.add(srcFilePath); } else { toMove.add(srcFilePath); } } catch (IOException e) { e.printStackTrace(); } } if (toRename.size() > 0) { options = FileOperationTask .makeDefaultOptions(FileOperationTask.OP_TYPE_RENAME_FILE); options.targetDirectoryPath = pasteDir; taskId = String.format("%d:%d:%d-rename", time.hour, time.minute, time.second); renameTask = new FileOperationTask(this, taskId, options, toRename, assignor); combinedTasks.add(renameTask); } if (toMove.size() > 0) { options = FileOperationTask .makeDefaultOptions(FileOperationTask.OP_TYPE_MOVE_FILE); options.targetDirectoryPath = pasteDir; taskId = String.format("%d:%d:%d-move", time.hour, time.minute, time.second); moveTask = new FileOperationTask(this, taskId, options, toMove, assignor); combinedTasks.add(moveTask); } } assignor.setOneShotClipTask(combinedTasks); // enqueue file operation tasks after combined clip task initialized if (copyTask != null) { mFileOpAutoExecutor.enqueueFileOpTask(copyTask); } else if (renameTask != null) { mFileOpAutoExecutor.enqueueFileOpTask(renameTask); } else if (moveTask != null) { mFileOpAutoExecutor.enqueueFileOpTask(moveTask); } } } public ActionMode getActivatingActionMode() { return mActivatingActionMode; } public ClipHistoryAdapter getClipHistoryAdapter() { return mClipHistoryAdapter; } @Override public String getClipPasteDir() { return sCurrentDir; } public FileMultiChoiceListener getFileMultiChoiceListener() { return mFileListMultiChoiceListener; } public void handleFileItemClick(ArrayAdapter<FileItem> fileDataAdapter, View view, int position, long id) { Log.i(TAG, "handleFileItemClick"); final String path = fileDataAdapter.getItem(position).getPath(); File file = new File(path); String item_ext = null; try { item_ext = path.substring(path.lastIndexOf("."), path.length()); } catch (IndexOutOfBoundsException e) { item_ext = ""; } if (!item_ext.equals("")) { item_ext = DataUtil.getFileExtensionWithoutDot(item_ext); } if (file.isDirectory()) { if (file.canRead()) { mAppController.stopThumbnailThread(); mAppController.updateDirectory(mFileManager.getNextUrlContent( path, true, false)); // When entering a folder, always focus on // the first item mCurrentShownFileList.setSelection(0); } else { Toast.makeText(this, R.string.read_fail_permission, Toast.LENGTH_SHORT).show(); } } /* special handle for vender MIME type */ else if (item_ext.equalsIgnoreCase("apk")) { if (file.exists()) { Intent intent = new Intent(); intent.setAction(android.content.Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); try { startActivity(intent); } catch (ActivityNotFoundException e) { Toast.makeText(this, R.string.cannot_find_application, Toast.LENGTH_SHORT).show(); } } } /* audio file */ else if (DataUtil.getSupportedAudioFileExtensions().contains( item_ext.toLowerCase())) { if (file.exists()) { Intent intent = new Intent(); intent.setAction(android.content.Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(file), "audio/*"); try { startActivity(intent); } catch (ActivityNotFoundException e) { Toast.makeText(this, R.string.cannot_find_application, Toast.LENGTH_SHORT).show(); } } } /* image file */ else if (DataUtil.getSupportedImageFileExtensions().contains( item_ext.toLowerCase())) { if (file.exists()) { Intent intent = new Intent(); intent.setAction(android.content.Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(file), "image/*"); try { startActivity(intent); } catch (ActivityNotFoundException e) { Toast.makeText(this, R.string.cannot_find_application, Toast.LENGTH_SHORT).show(); } } } /* video file */ else if (DataUtil.getSupportedVideoFileExtensions().contains( item_ext.toLowerCase())) { if (file.exists()) { Intent intent = new Intent(); intent.setAction(android.content.Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(file), "video/*"); try { startActivity(intent); } catch (ActivityNotFoundException e) { Toast.makeText(this, R.string.cannot_find_application, Toast.LENGTH_SHORT).show(); } } } else { String extensionWithoutDot = DataUtil .getFileExtensionWithoutDot(file.getPath()); String mimeType = DataUtil.getMimeType(extensionWithoutDot); if (mimeType != null) { Intent intent = new Intent(); intent.setAction(android.content.Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(file), mimeType); try { startActivity(intent); } catch (ActivityNotFoundException e) { Toast.makeText(this, R.string.cannot_find_application, Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, R.string.cannot_find_application, Toast.LENGTH_SHORT).show(); } } } @Override public void navigateToPath(String path) { Log.i(TAG, "navigateToPath - path: " + path); mAppController.updateDirectory(mFileManager.getNextUrlContent(path, true, false)); } @Override public void onClipHistoryChanged(ClipHistoryAdapter adapter) { if (adapter == null) { return; } if (adapter.getCount() == 0) { mClipBoardIndicator.setVisibility(View.GONE); if (mClipBoardDrawer.isOpened()) { mClipBoardDrawer.close(); } setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); } else { mClipBoardIndicator.setVisibility(View.VISIBLE); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR); } invalidateOptionsMenu(); mAppController.updateDirectory(mFileManager.refreshUrlContent()); } @Override public void onConfigurationChanged(Configuration newConfig) { Log.i(TAG, "onConfigurationChanged" + newConfig.keyboard); if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) { Log.i(TAG, "hard keyboard presented."); } else if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) { Log.i(TAG, "hard keyboard quits."); } super.onConfigurationChanged(newConfig); } @Override public boolean onCreateOptionsMenu(Menu menu) { menu.clear(); MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.file_explorer_options_menu, menu); return super.onCreateOptionsMenu(menu); } @Override public void onFileCopied(String srcFilePath, String copiedFilePath) { callMediaScanOnCreatedFile(copiedFilePath); String pattern = null; String extension = DataUtil.getFileExtensionWithoutDot(copiedFilePath); if (DataUtil.isSupportedAppInstaller(extension)) { pattern = FilePathUrlManager.SMART_APK; } else if (DataUtil.isSupportedAudioFile(extension)) { pattern = FilePathUrlManager.SMART_MUSIC; } else if (DataUtil.isSupportedImageFile(extension)) { pattern = FilePathUrlManager.SMART_IMAGE; } else if (DataUtil.isSupportedVideoFile(extension)) { pattern = FilePathUrlManager.SMART_MOVIES; } if (pattern != null) { HashMap<String, String> changeSet = new HashMap<String, String>(); changeSet.put(FileUtil.NEW_GENERATED_FILE, copiedFilePath); updateCachedFilePaths(pattern, changeSet); } } @Override public void onFileCreated(String filePath) { callMediaScanOnCreatedFile(filePath); String pattern = null; String extension = DataUtil.getFileExtensionWithoutDot(filePath); if (DataUtil.isSupportedAppInstaller(extension)) { pattern = FilePathUrlManager.SMART_APK; } else if (DataUtil.isSupportedAudioFile(extension)) { pattern = FilePathUrlManager.SMART_MUSIC; } else if (DataUtil.isSupportedImageFile(extension)) { pattern = FilePathUrlManager.SMART_IMAGE; } else if (DataUtil.isSupportedVideoFile(extension)) { pattern = FilePathUrlManager.SMART_MOVIES; } if (pattern != null) { HashMap<String, String> changeSet = new HashMap<String, String>(); changeSet.put(FileUtil.NEW_GENERATED_FILE, filePath); updateCachedFilePaths(pattern, changeSet); } } @Override public void onFileDeleted(String filePath) { @SuppressWarnings("unchecked") HashMap<String, ArrayList<String>> cachedSearchResult = (HashMap<String, ArrayList<String>>) mAppController .getCachedSearchResult().clone(); if (cachedSearchResult != null) { for (String searchId : cachedSearchResult.keySet()) { ArrayList<String> searchResult = cachedSearchResult .get(searchId); if (searchResult != null && searchResult.contains(filePath)) { handleFileSearch( FilePathUrlManager.parseSearchStr(searchId), FilePathUrlManager.parseSearchDir(searchId), true); } } } String pattern = null; String extension = DataUtil.getFileExtensionWithoutDot(filePath); if (DataUtil.isSupportedAppInstaller(extension)) { pattern = FilePathUrlManager.SMART_APK; } else if (DataUtil.isSupportedAudioFile(extension)) { pattern = FilePathUrlManager.SMART_MUSIC; } else if (DataUtil.isSupportedImageFile(extension)) { pattern = FilePathUrlManager.SMART_IMAGE; } else if (DataUtil.isSupportedVideoFile(extension)) { pattern = FilePathUrlManager.SMART_MOVIES; } updateMediaStoreOnDeletedFile(filePath, pattern); if (pattern != null) { HashMap<String, String> changeSet = new HashMap<String, String>(); changeSet.put(filePath, null); updateCachedFilePaths(pattern, changeSet); } } @Override public void onFileRenamed(String originalFilePath, String newFilePath) { callMediaScanOnCreatedFile(newFilePath); @SuppressWarnings("unchecked") HashMap<String, ArrayList<String>> cachedSearchResult = (HashMap<String, ArrayList<String>>) mAppController .getCachedSearchResult().clone(); if (cachedSearchResult != null) { for (String searchId : cachedSearchResult.keySet()) { ArrayList<String> searchResult = cachedSearchResult .get(searchId); if (searchResult != null && searchResult.contains(originalFilePath)) { handleFileSearch( FilePathUrlManager.parseSearchStr(searchId), FilePathUrlManager.parseSearchDir(searchId), true); } } } String patternOriginal = null; String extensionOriginal = DataUtil .getFileExtensionWithoutDot(originalFilePath); if (DataUtil.isSupportedAppInstaller(extensionOriginal)) { patternOriginal = FilePathUrlManager.SMART_APK; } else if (DataUtil.isSupportedAudioFile(extensionOriginal)) { patternOriginal = FilePathUrlManager.SMART_MUSIC; } else if (DataUtil.isSupportedImageFile(extensionOriginal)) { patternOriginal = FilePathUrlManager.SMART_IMAGE; } else if (DataUtil.isSupportedVideoFile(extensionOriginal)) { patternOriginal = FilePathUrlManager.SMART_MOVIES; } updateMediaStoreOnDeletedFile(originalFilePath, patternOriginal); String patternNew = null; String extensionNew = DataUtil.getFileExtensionWithoutDot(newFilePath); if (DataUtil.isSupportedAppInstaller(extensionNew)) { patternNew = FilePathUrlManager.SMART_APK; } else if (DataUtil.isSupportedAudioFile(extensionNew)) { patternNew = FilePathUrlManager.SMART_MUSIC; } else if (DataUtil.isSupportedImageFile(extensionNew)) { patternNew = FilePathUrlManager.SMART_IMAGE; } else if (DataUtil.isSupportedVideoFile(extensionNew)) { patternNew = FilePathUrlManager.SMART_MOVIES; } if (patternOriginal != null && patternNew != null && patternOriginal.equals(patternNew)) { HashMap<String, String> changeSet = new HashMap<String, String>(); changeSet.put(originalFilePath, newFilePath); updateCachedFilePaths(patternNew, changeSet); } else { if (patternOriginal != null) { HashMap<String, String> changeSet = new HashMap<String, String>(); changeSet.put(originalFilePath, null); updateCachedFilePaths(patternOriginal, changeSet); } if (patternNew != null) { HashMap<String, String> changeSet = new HashMap<String, String>(); changeSet.put(FileUtil.NEW_GENERATED_FILE, newFilePath); updateCachedFilePaths(patternNew, changeSet); } } } @Override public void onItemClick(AdapterView<?> adapterView, View itemView, int pos, long id) { if (adapterView.getAdapter() instanceof FavoriteDataAdapter) { if (mActivatingActionMode != null) { mActivatingActionMode.finish(); } FavoriteItem favoriteItem = (FavoriteItem) adapterView .getItemAtPosition(pos); String filePattern = favoriteItem.getPath(); // user relay search instead // mHandler.searchForFilesOfPattern(filePattern); int searchType = -1; if (filePattern.endsWith(FilePathUrlManager.SMART_MUSIC)) { searchType = StorageUtil.TYPE_AUDIO; } else if (filePattern.endsWith(FilePathUrlManager.SMART_MOVIES)) { searchType = StorageUtil.TYPE_VIDEO; } else if (filePattern.endsWith(FilePathUrlManager.SMART_IMAGE)) { searchType = StorageUtil.TYPE_IMAGE; } else if (filePattern.endsWith(FilePathUrlManager.SMART_APK)) { searchType = StorageUtil.TYPE_APKFILE; } // TODO: make searchDir configurable from FavoriteItem by user String searchDir = "/"; mAppController.searchFiles(searchType, FileUtil.FILE_PATTERN_ALL, "/", IfConfig.MAX_SEARCH_DEPTH, false); String url = FilePathUrlManager.URL_FIELD_DIR_PATH + FilePathUrlManager.URL_KEY_VALUE_DIVIDER + searchDir + FilePathUrlManager.URL_FIELD_DIVIDER + filePattern + FilePathUrlManager.URL_FIELD_DIVIDER; mAppController.updateDirectory(mFileManager.getNextUrlContent(url, true, false)); // reset current dir sCurrentDir = null; closeAllSlidingLayer(false); } else if (adapterView.getAdapter() instanceof DeviceDataAdapter) { if (mActivatingActionMode != null) { mActivatingActionMode.finish(); } DeviceItem deviceItem = (DeviceItem) adapterView .getItemAtPosition(pos); String path = deviceItem.getPath(); mAppController.updateDirectory(mFileManager.getNextUrlContent(path, true, false)); closeAllSlidingLayer(false); } else if (adapterView.getAdapter() instanceof FileDataListAdapter) { handleFileItemClick(mFileDataListAdapter, itemView, pos, id); } else if (adapterView.getAdapter() instanceof FileDataGridAdapter) { handleFileItemClick(mFileDataGridAdapter, itemView, pos, id); } // refresh options menus invalidateOptionsMenu(); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_BACK: confirmOnAppQuit(); return true; default: return super.onKeyDown(keyCode, event); } } @Override public void onNewIntent(Intent intent) { handleIntent(intent); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_new_file_folder: final Dialog newFolderDialog = createNewSingleFolderDialog(); newFolderDialog.show(); return true; case R.id.menu_list_mode: if (item.isChecked()) { // Do nothing } else { item.setChecked(true); switchViewMode(VIEW_AS_LIST); } return true; case R.id.menu_grid_mode: if (item.isChecked()) { // Do nothing } else { item.setChecked(true); switchViewMode(VIEW_AS_GRID); } return true; case R.id.menu_pasteFile: // last clip int count = mClipHistoryAdapter.getCount(); if (count >= 1) { ClipItemAdapter adapter = mClipHistoryAdapter .getItem(mClipHistoryAdapter.getCount() - 1); if (adapter != null) { HashSet<FileClip> toPaste = adapter.prepare(); if (toPaste.size() > 0) { adapter.pasteFileClip(toPaste); } } } return true; default: return super.onOptionsItemSelected(item); } } @Override public boolean onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); boolean canPaste = false; int clipCount = mClipHistoryAdapter.getCount(); if (clipCount >= 1) { ClipItemAdapter adapter = mClipHistoryAdapter .getItem(clipCount - 1); float clipType = adapter.getClipType(); canPaste = (clipType == ClipSourceProvider.CLIP_TYPE_COPY_SOURCE || clipType == ClipSourceProvider.CLIP_TYPE_CUT_SOURCE); } menu.findItem(R.id.menu_pasteFile) .setVisible( (mOptionPasteAvailable && canPaste && sCurrentDir != null) ? true : false); menu.findItem(R.id.menu_new_file_folder).setVisible( sCurrentDir != null ? true : false); MenuItem searchItem = menu.findItem(R.id.menu_search); mSearchView = (SearchView) searchItem.getActionView(); mSearchView.setOnQueryTextListener(this); searchItem.setVisible(sCurrentDir != null ? true : false); switch (mCurrentViewMode) { case VIEW_AS_LIST: menu.findItem(R.id.menu_list_mode).setChecked(true); break; case VIEW_AS_GRID: menu.findItem(R.id.menu_grid_mode).setChecked(true); break; } return true; } @Override public boolean onQueryTextChange(String newText) { return false; } @Override public boolean onQueryTextSubmit(String query) { String searchDir = FilePathUrlManager.getDir(mFileManager .getCurrentUrl()); handleFileSearch(query, searchDir, false); return true; } public boolean onSameFileSystem(String filePath, String otherFilePath) throws IOException { if (KLOG) { Log.i(TAG, "Check if on same file system for path:" + filePath + " and path:" + otherFilePath); } String fileCanonicalPath = new File(filePath).getCanonicalPath(); String otherFileCanonicalPath = new File(otherFilePath) .getCanonicalPath(); ArrayList<String> mountedFileSystems = mAppController .getCurrentMountedFileSystems(); String fileSystem_1 = null; String fileSystem_2 = null; // Make sure we go through all the device paths, // because different file system path could possibly hold the same // prefix. for (String fileSystem : mountedFileSystems) { if (fileCanonicalPath.startsWith(fileSystem)) { fileSystem_1 = fileSystem; } if (otherFileCanonicalPath.startsWith(fileSystem)) { fileSystem_2 = fileSystem; } } if (fileSystem_1 == null || fileSystem_2 == null || !fileSystem_1.equals(fileSystem_2)) { if (KLOG) { Log.i(TAG, "File: " + filePath + " and file: " + otherFilePath + " are not in the same filesystem!"); } return false; } else { return true; } } // implement EventHandler.DeviceDataListener::onStorageDeviceItemChanged @Override public void onStorageDeviceItemChanged() { refreshTaskGroups(); } @Override public boolean onTouch(View v, MotionEvent event) { if (v instanceof ImageButton) { Bitmap shapedArea = ((BitmapDrawable) ((ImageButton) v) .getDrawable()).getBitmap(); if (shapedArea != null) { if (shapedArea.getPixel((int) event.getX(), (int) event.getY()) != 0) { Log.i(TAG, "File path button valid touch."); v.performClick(); return true; } else { Log.i(TAG, "File path button invalid touch."); return true; } } } return false; } @Override public void onUrlContentUpdated(String newUrl, int contentSize, boolean fromHistory) { Log.i(TAG, "onUrlContentUpdated newUrl:" + newUrl); String smartPattern = FilePathUrlManager.getSmartPattern(newUrl); String extraInfo = null; if (smartPattern != null) { String patternStr = getPatternStrFromPattern(smartPattern); String query = FilePathUrlManager.getQueryStr(newUrl); String searchDir = FilePathUrlManager.getDir(newUrl); String searchDescription = null; Resources resouces = getResources(); if (query != null) { searchDescription = resouces.getString( R.string.rec_search_current_dir, searchDir); extraInfo = String.format( "%s, %s '%s'. %s%d %s", searchDescription, resouces.getString(R.string.file_name_contain), query, contentSize < IfConfig.MAX_LISTITEM_COUNT ? resouces .getString(R.string.found_) : resouces .getString(R.string.show_first_), contentSize, resouces.getString(R.string.items)); } else { searchDescription = resouces.getString(R.string.global_search); extraInfo = String.format( "%s %s. %s%d %s", searchDescription, patternStr, contentSize < IfConfig.MAX_LISTITEM_COUNT ? resouces .getString(R.string.found_) : resouces .getString(R.string.show_first_), contentSize, resouces.getString(R.string.items)); } } mPathNavigator.setStatusInfo(extraInfo); if (FilePathUrlManager.isSearchUrl(newUrl)) { mPathNavigator.switchToIndicateMode(); } else { Log.i(TAG, "Call path navigator to switch to navigate mode."); mPathNavigator.switchToNavigateMode(); } if (mPathNavigator != null) { mPathNavigator.updatePathNodes(mFileManager.getCurrentUrl()); } int currentPosition = mFileManager.getCurrentUrlPosition(); boolean canForward = currentPosition < (mFileManager .getUrlHistoryCount() - 1); boolean canBackward = currentPosition > 0; mNavForwardButton.setEnabled(canForward); mNavBackwardButton.setEnabled(canBackward); setCurrentDir(newUrl); invalidateOptionsMenu(); } @Override public void showDeleteUi() { if (!mClipBoardDrawer.isOpened()) { mClipBoardDrawer.animateOpen(); } } @Override public void showPasteUi() { if (!mClipBoardDrawer.isOpened()) { mClipBoardDrawer.animateOpen(); } } public void switchViewMode(int viewMode) { switch (viewMode) { case VIEW_AS_LIST: if (mLibrarySlidingLayer != null && mLibrarySlidingLayer.isOpened()) { mFileListView.setVisibility(View.GONE); } else { mFileListView.setVisibility(View.VISIBLE); } mFileGridView.setVisibility(View.GONE); mCurrentShownFileList = mFileListView; mCurrentViewMode = VIEW_AS_LIST; break; case VIEW_AS_GRID: if (mLibrarySlidingLayer != null && mLibrarySlidingLayer.isOpened()) { mFileGridView.setVisibility(View.GONE); } else { mFileGridView.setVisibility(View.VISIBLE); } mFileListView.setVisibility(View.GONE); mCurrentShownFileList = mFileGridView; mCurrentViewMode = VIEW_AS_GRID; break; } if (mAppController != null) { mAppController.setCurrentFileListView(mCurrentShownFileList); } SharedPreferences prefs = PreferenceManager .getDefaultSharedPreferences(this); SharedPreferences.Editor editor = prefs.edit(); editor.putInt(KEY_VIEW_MODE, viewMode); editor.apply(); } public void updateCachedFilePaths(String pattern, HashMap<String, String> changeSet) { mFileManager.updateCachedFilePaths(pattern, changeSet); if (pattern.equals(FilePathUrlManager.getSmartPattern(mFileManager .getCurrentUrl()))) { mAppController.updateDirectory(mFileManager.refreshUrlContent()); } } private void callMediaScanOnCreatedFile(String filePath) { File file = new File(filePath); MediaScannerConnection.scanFile(this, new String[] { file.getAbsolutePath() }, null, new OnScanCompletedListener() { @Override public void onScanCompleted(String path, Uri uri) { Log.i(TAG, "Media scanner scan file: " + path + " successfully."); } }); } private void closeAllSlidingLayer(boolean smooth) { for (SlidingLayer layer : mSlidingLayers) { if (layer != null && layer.isOpened()) { layer.closeLayer(smooth); } } mCurrentShownFileList.setVisibility(View.VISIBLE); } private void closeSlidingLayer(SlidingLayer targetLayer, boolean smooth) { if (targetLayer != null && targetLayer.isOpened()) { targetLayer.closeLayer(smooth); } mCurrentShownFileList.setVisibility(View.VISIBLE); } private void confirmOnAppQuit() { Resources resources = getResources(); String message = resources.getString(R.string.confirm_quit, resources.getString(R.string.app_name)); AlertDialog dialog = new AlertDialog.Builder(this) .setTitle(R.string.quit) .setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { IfExplorer.this.finish(); } }).setNegativeButton(R.string.cancel, null) .setMessage(message).create(); dialog.show(); } private Dialog createNewSingleFolderDialog() { View contentRootView = LayoutInflater.from(this).inflate( R.layout.create_folder_dialog, null); final EditText nameEdit = (EditText) contentRootView .findViewById(R.id.name_edit); AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.create_folder) .setView(contentRootView) .setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Resources resources = getResources(); String name = nameEdit.getText().toString(); String typeStr = resources .getString(R.string.folder); String errStr = null; int ret = FileUtil.createFile( IfExplorer.sCurrentDir, name, FileUtil.FILE_TYPE_DIRECTORY, IfExplorer.this); if (ret == FileUtil.OP_SUCCESS) { Toast.makeText( IfExplorer.this, resources.getString( R.string.folder_created, name), Toast.LENGTH_SHORT) .show(); } else { errStr = FileUtil.getDefaultFileOpErrStr( resources, ret); Toast.makeText( IfExplorer.this, resources.getString( R.string.new_failed, typeStr, name, errStr), Toast.LENGTH_LONG).show(); } dialog.dismiss(); } }) .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); return builder.create(); } private int getDeviceDisplayType() { if (findViewById(R.id.phone_port_root) != null) { return DEVICE_PHONE_PORT; } else if (findViewById(R.id.phone_land_root) != null) { return DEVICE_PHONE_LAND; } else if (findViewById(R.id.tablet_land_root) != null) { return DEVICE_TAB_LAND; } else if (findViewById(R.id.tablet_port_root) != null) { return DEVICE_TAB_PORT; } else { return DEVICE_UNKNOWN; } } private String getPatternStrFromPattern(String pattern) { if (pattern.equals(FilePathUrlManager.SMART_IMAGE)) { return getResources().getString(R.string.image_file); } else if (pattern.equals(FilePathUrlManager.SMART_MOVIES)) { return getResources().getString(R.string.video_file); } else if (pattern.equals(FilePathUrlManager.SMART_MUSIC)) { return getResources().getString(R.string.audio_file); } else if (pattern.equals(FilePathUrlManager.SMART_APK)) { return getResources().getString(R.string.apk_file); } else { return getResources().getString(R.string.file); } } private void handleFileSearch(String queryStr, String searchDir, boolean silent) { mAppController.searchFiles(StorageUtil.TYPE_FILE, queryStr, searchDir, IfConfig.MAX_SEARCH_DEPTH, silent); if (!silent) { String url = FilePathUrlManager.buildUrl(searchDir, queryStr, FilePathUrlManager.SMART_FILE); mFileManager.getNextUrlContent(url, true, false); } } private void handleIntent(Intent intent) { String action = intent.getAction(); if (Intent.ACTION_SEARCH.equals(action)) { String query = intent.getStringExtra(SearchManager.QUERY); String searchDir = FilePathUrlManager.getDir(mFileManager .getCurrentUrl()); handleFileSearch(query, searchDir, false); } } private void initSlidingLayerState() { for (SlidingLayer layer : mSlidingLayers) { layer.setStickTo(SlidingLayer.STICK_TO_TOP); LayoutParams rlp = (LayoutParams) layer.getLayoutParams(); rlp.addRule(RelativeLayout.ALIGN_PARENT_TOP); layer.setLayoutParams(rlp); layer.setShadowWidth(0); layer.setShadowDrawable(null); layer.setSlidingEnabled(false); layer.setOpenOnTapEnabled(false); layer.setCloseOnTapEnabled(false); } } private void openSlidingLayer(SlidingLayer targetLayer, boolean smooth) { boolean doSmoothOpen = smooth; for (SlidingLayer layer : mSlidingLayers) { if (layer != null && layer.isOpened()) { doSmoothOpen = false; layer.closeLayer(false); } } if (targetLayer != null && !targetLayer.isOpened()) { targetLayer.openLayer(doSmoothOpen); mCurrentShownFileList.setVisibility(View.GONE); } } private void preScanCategoriedFiles() { } private void setActivatingActionMode(ActionMode actionMode) { mActivatingActionMode = actionMode; } private void setupAddressBar() { mAddressBar = findViewById(R.id.task_bar); mPathNavigator = (FilePathNavigator) mAddressBar .findViewById(R.id.filePath_navigator); mAppController.addExtraFileDragStartedListener(mPathNavigator); mPathNavigator.setNavigationCallback(this); mPathNavigator.setOnDropDelegate(mAppController); mPathNavigator.setPathButtonOnDropDelegate(mAppController); mPathNavigator.setPathButtonOpenDelegate(mAppController); //if (IfConfig.PRODUCT_IS_MONITOR) { // mPathNavigator.setRootNodeIconResId(R.drawable.loc_monitor_dark); //} mNavForwardButton = (ImageView) mPathNavigator .findViewById(R.id.navigation_previous); mNavForwardButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mAppController.updateDirectory( mFileManager.getNextUrlContent(null, false, true), true); } }); mNavBackwardButton = (ImageView) mPathNavigator .findViewById(R.id.navigation_back); mNavBackwardButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mAppController.updateDirectory( mFileManager.getPreviousUrlContent(), true); } }); mLibrarySwitchButton = (ImageView) mPathNavigator .findViewById(R.id.collection_panel_switch); mLibrarySwitchButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mLibrarySlidingLayer != null && mLibrarySlidingLayer.isOpened()) { closeSlidingLayer(mLibrarySlidingLayer, true); } else if (mLibrarySlidingLayer != null && !mLibrarySlidingLayer.isOpened()) { openSlidingLayer(mLibrarySlidingLayer, true); } } }); mCloudSwitchButton = (ImageView) mPathNavigator .findViewById(R.id.cloud_panel_switch); mCloudSwitchButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mCloudSlidingLayer != null && mCloudSlidingLayer.isOpened()) { closeSlidingLayer(mCloudSlidingLayer, true); } else if (mCloudSlidingLayer != null && !mCloudSlidingLayer.isOpened()) { openSlidingLayer(mCloudSlidingLayer, true); } } }); int currentPosition = mFileManager.getCurrentUrlPosition(); boolean canForward = currentPosition < (mFileManager .getUrlHistoryCount() - 1); boolean canBackward = currentPosition > 0; mNavForwardButton.setEnabled(canForward); mNavBackwardButton.setEnabled(canBackward); } private void setupClipBoard() { mClipHistoryAdapter = new ClipHistoryAdapter(this, R.layout.clip_group, R.id.clip_title, new ArrayList<ClipItemAdapter>()); mClipHistoryAdapter.setClipHistoryCallback(this); mClipBoardDrawer = (SlidingDrawerEx) findViewById(R.id.clipboard); mClipBoardIndicator = mClipBoardDrawer .findViewById(R.id.clipboard_indicator); mClipHistoryListView = (ListView) mClipBoardDrawer .findViewById(R.id.clip_history_list); mClipHistoryListView.setAdapter(mClipHistoryAdapter); mButtonClearClipboard = (Button) mClipBoardDrawer .findViewById(R.id.clearAll); mButtonClearClipboard.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mClipHistoryAdapter.clearClipRecords(); } }); mButtonCloseClipboard = (Button) mClipBoardDrawer .findViewById(R.id.close); mButtonCloseClipboard.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mClipBoardDrawer.close(); } }); } private void setupFileList() { mFileDataListAdapter = mAppController.getFileDataListAdapter(); mFileDataGridAdapter = mAppController.getFileDataGridAdapter(); mFileListMultiChoiceListener = new FileMultiChoiceListener(); mFileListView = (DropableListView) findViewById(R.id.file_listview); mFileListView.setAdapter(mFileDataListAdapter); mFileListView.setOnItemClickListener(this); mFileListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); mFileListView.setMultiChoiceModeListener(mFileListMultiChoiceListener); mFileGridView = (DropableGridView) findViewById(R.id.file_gridview); mFileGridView.setAdapter(mFileDataGridAdapter); mFileGridView.setOnItemClickListener(this); mFileGridView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); mFileGridView.setMultiChoiceModeListener(mFileListMultiChoiceListener); mFileGridView.setOnDropDelegate(mAppController); // default SharedPreferences prefs = PreferenceManager .getDefaultSharedPreferences(this); int savedViewMode = prefs.getInt(KEY_VIEW_MODE, VIEW_AS_GRID); switchViewMode(savedViewMode); mAppController.updateDirectory(mFileManager.refreshUrlContent()); } private void showDetailDialog(HashSet<Object> fileItems) { View contentRootView = LayoutInflater.from(this).inflate( R.layout.single_file_detail, null); final ImageView iconView = (ImageView) contentRootView .findViewById(R.id.file_icon); final TextView nameView = (TextView) contentRootView .findViewById(R.id.file_name); for (Object item : fileItems) { if (item instanceof FileItem) { Drawable drawable = ((FileItem) item).getIconDrawable(); if (drawable != null) { iconView.setImageDrawable(drawable); } else { iconView.setImageResource(((FileItem) item) .getIconResource()); } nameView.setText(((FileItem) item).getName()); } } AlertDialog dialog = new AlertDialog.Builder(this) .setTitle(R.string.detail).setView(contentRootView) .setPositiveButton(R.string.cancel, null).create(); dialog.show(); } private void updateMediaStoreOnDeletedFile(String filePath, String pattern) { Uri url; String dbWhereStrPrefix; if (pattern == null) { url = MediaStore.Files.getContentUri("external"); dbWhereStrPrefix = MediaStore.Files.FileColumns.DATA; } else { if (pattern.equals(FilePathUrlManager.SMART_IMAGE)) { url = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; dbWhereStrPrefix = MediaStore.Images.Media.DATA; } else if (pattern.equals(FilePathUrlManager.SMART_MUSIC)) { url = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; dbWhereStrPrefix = MediaStore.Audio.Media.DATA; } else if (pattern.equals(FilePathUrlManager.SMART_MOVIES)) { url = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; dbWhereStrPrefix = MediaStore.Video.Media.DATA; } else { url = MediaStore.Files.getContentUri("external"); dbWhereStrPrefix = MediaStore.Files.FileColumns.DATA; } } String dbWhereStr = dbWhereStrPrefix + "=?"; ContentResolver resolver = getContentResolver(); resolver.delete(url, dbWhereStr, new String[] { filePath }); } protected void initializeSlidingLayer() { // Reset at first mSlidingLayers.clear(); mLibrarySlidingLayer = null; mCloudSlidingLayer = null; if (mLibrarySwitchButton != null) { mLibrarySwitchButton.setVisibility(View.GONE); } if (mCloudSwitchButton != null) { mCloudSwitchButton.setVisibility(View.GONE); } mLibrarySlidingLayer = (SlidingLayer) findViewById(R.id.sliding_panel); if (mLibrarySlidingLayer != null) { mLibrarySwitchButton.setVisibility(View.VISIBLE); mSwitchSlidingLayerMap.put(mLibrarySwitchButton, mLibrarySlidingLayer); mSlidingLayers.add(mLibrarySlidingLayer); } mCloudSlidingLayer = (SlidingLayer) findViewById(R.id.sliding_cloud_panel); if (mCloudSlidingLayer != null) { mCloudSwitchButton.setVisibility(View.VISIBLE); mSwitchSlidingLayerMap.put(mCloudSwitchButton, mCloudSlidingLayer); mSlidingLayers.add(mCloudSlidingLayer); } if (mSlidingLayers.size() > 0) { initSlidingLayerState(); // Using sliding layer means display space is limited, // reduce maximum visible file path node according to device display // type switch (mDeviceDisplayType) { case DEVICE_TAB_PORT: FilePathNavigator.MAX_BUTTON_NUM = 4; break; case DEVICE_PHONE_LAND: FilePathNavigator.MAX_BUTTON_NUM = 4; break; case DEVICE_PHONE_PORT: FilePathNavigator.MAX_BUTTON_NUM = 2; break; } } else { FilePathNavigator.MAX_BUTTON_NUM = 5; } } protected void intializeMiniWidgets() { /* Favorites */ mFavoritesMiniWidget = (TaskGroupListWidget) findViewById(R.id.favorite_collection); mFavoritesMiniWidget.setGroupTag(kTagTaskGroupBase + 1); mFavoritesMiniWidget.setDefaultGroupLabel(getResources().getString( R.string.category)); mFavoritesMiniWidget.setEjectable(false); AbsListView favoriteList = mFavoritesMiniWidget.activateListMode(); favoriteList.setOnItemClickListener(this); favoriteList.setAdapter(mAppController.getFavoriteDataAdapter()); mMiniPanelWidgets.add(mFavoritesMiniWidget); /* Storage devices */ // internal SD card mInternalStorageMiniWidget = (TaskGroupListWidget) findViewById(R.id.internal_collection); mInternalStorageMiniWidget.setGroupTag(kTagTaskGroupBase + 2); mInternalStorageMiniWidget.setDefaultGroupLabel(getResources() .getString(R.string.internal_storage)); mInternalStorageMiniWidget.setEjectable(false); AbsListView intSdcardList = mInternalStorageMiniWidget .activateListMode(); intSdcardList.setOnItemClickListener(this); intSdcardList.setAdapter(mAppController .getDeviceDataAdapter(StorageUtil.Internal)); mMiniPanelWidgets.add(mInternalStorageMiniWidget); // external SD card mSdcardMiniWidget = (TaskGroupListWidget) findViewById(R.id.sdcard_collection); mSdcardMiniWidget.setGroupTag(kTagTaskGroupBase + 3); mSdcardMiniWidget.setDefaultGroupLabel(getResources().getString( R.string.sdcard_storage)); mSdcardMiniWidget.setEjectable(IfConfig.SIGNED_WITH_PLATFORM_KEY); AbsListView extSdcardList = mSdcardMiniWidget.activateListMode(); extSdcardList.setOnItemClickListener(this); extSdcardList.setAdapter(mAppController .getDeviceDataAdapter(StorageUtil.SDSlot)); mMiniPanelWidgets.add(mSdcardMiniWidget); // USB 0 storage mUsb0StorageMiniWidget = (TaskGroupListWidget) findViewById(R.id.usb0_disk_collection); mUsb0StorageMiniWidget.setGroupTag(kTagTaskGroupBase + 4); mUsb0StorageMiniWidget.setDefaultGroupLabel(getResources().getString( R.string.usb_storage)); mUsb0StorageMiniWidget.setEjectable(IfConfig.SIGNED_WITH_PLATFORM_KEY); AbsListView usb0storageList = mUsb0StorageMiniWidget.activateListMode(); usb0storageList.setOnItemClickListener(this); usb0storageList.setAdapter(mAppController .getDeviceDataAdapter(StorageUtil.USBPort0)); mMiniPanelWidgets.add(mUsb0StorageMiniWidget); // USB 1 storage mUsb1StorageMiniWidget = (TaskGroupListWidget) findViewById(R.id.usb1_disk_collection); mUsb1StorageMiniWidget.setGroupTag(kTagTaskGroupBase + 5); mUsb1StorageMiniWidget.setDefaultGroupLabel(getResources().getString( R.string.usb1_storage)); mUsb1StorageMiniWidget.setEjectable(IfConfig.SIGNED_WITH_PLATFORM_KEY); AbsListView usb1storageList = mUsb1StorageMiniWidget.activateListMode(); usb1storageList.setOnItemClickListener(this); usb1storageList.setAdapter(mAppController .getDeviceDataAdapter(StorageUtil.USBPort1)); mMiniPanelWidgets.add(mUsb1StorageMiniWidget); // USB 2 storage mUsb2StorageMiniWidget = (TaskGroupListWidget) findViewById(R.id.usb2_disk_collection); mUsb2StorageMiniWidget.setGroupTag(kTagTaskGroupBase + 6); mUsb2StorageMiniWidget.setDefaultGroupLabel(getResources().getString( R.string.usb2_storage)); mUsb2StorageMiniWidget.setEjectable(IfConfig.SIGNED_WITH_PLATFORM_KEY); AbsListView usb2storageList = mUsb2StorageMiniWidget.activateListMode(); usb2storageList.setOnItemClickListener(this); usb2storageList.setAdapter(mAppController .getDeviceDataAdapter(StorageUtil.USBPort2)); mMiniPanelWidgets.add(mUsb2StorageMiniWidget); // USB 3 storage mUsb3StorageMiniWidget = (TaskGroupListWidget) findViewById(R.id.usb3_disk_collection); mUsb3StorageMiniWidget.setGroupTag(kTagTaskGroupBase + 7); mUsb3StorageMiniWidget.setDefaultGroupLabel(getResources().getString( R.string.usb3_storage)); mUsb3StorageMiniWidget.setEjectable(IfConfig.SIGNED_WITH_PLATFORM_KEY); AbsListView usb3storageList = mUsb3StorageMiniWidget.activateListMode(); usb3storageList.setOnItemClickListener(this); usb3storageList.setAdapter(mAppController .getDeviceDataAdapter(StorageUtil.USBPort3)); mMiniPanelWidgets.add(mUsb3StorageMiniWidget); // USB 4 storage mUsb4StorageMiniWidget = (TaskGroupListWidget) findViewById(R.id.usb4_disk_collection); mUsb4StorageMiniWidget.setGroupTag(kTagTaskGroupBase + 8); mUsb4StorageMiniWidget.setDefaultGroupLabel(getResources().getString( R.string.usb4_storage)); mUsb4StorageMiniWidget.setEjectable(IfConfig.SIGNED_WITH_PLATFORM_KEY); AbsListView usb4storageList = mUsb4StorageMiniWidget.activateListMode(); usb4storageList.setOnItemClickListener(this); usb4storageList.setAdapter(mAppController .getDeviceDataAdapter(StorageUtil.USBPort4)); mMiniPanelWidgets.add(mUsb4StorageMiniWidget); // USB 5 storage mUsb5StorageMiniWidget = (TaskGroupListWidget) findViewById(R.id.usb5_disk_collection); mUsb5StorageMiniWidget.setGroupTag(kTagTaskGroupBase + 9); mUsb5StorageMiniWidget.setDefaultGroupLabel(getResources().getString( R.string.usb5_storage)); mUsb5StorageMiniWidget.setEjectable(IfConfig.SIGNED_WITH_PLATFORM_KEY); AbsListView usb5storageList = mUsb5StorageMiniWidget.activateListMode(); usb5storageList.setOnItemClickListener(this); usb5storageList.setAdapter(mAppController .getDeviceDataAdapter(StorageUtil.USBPort5)); mMiniPanelWidgets.add(mUsb5StorageMiniWidget); // USB Storage A mStorageA_MiniWidget = (TaskGroupListWidget) findViewById(R.id.usb_a_collection); mStorageA_MiniWidget.setGroupTag(kTagTaskGroupBase + 10); mStorageA_MiniWidget.setDefaultGroupLabel(getResources().getString( R.string.usb_storage_a)); mStorageA_MiniWidget.setEjectable(IfConfig.SIGNED_WITH_PLATFORM_KEY); AbsListView usba_storageList = mStorageA_MiniWidget.activateListMode(); usba_storageList.setOnItemClickListener(this); DeviceDataAdapter usba_adapter = mAppController .getDeviceDataAdapter(StorageUtil.USBSDA); usba_storageList.setAdapter(usba_adapter); mMiniPanelWidgets.add(mStorageA_MiniWidget); // USB Storage B mStorageB_MiniWidget = (TaskGroupListWidget) findViewById(R.id.usb_b_collection); mStorageB_MiniWidget.setGroupTag(kTagTaskGroupBase + 11); mStorageB_MiniWidget.setDefaultGroupLabel(getResources().getString( R.string.usb_storage_b)); mStorageB_MiniWidget.setEjectable(IfConfig.SIGNED_WITH_PLATFORM_KEY); AbsListView usbb_storageList = mStorageB_MiniWidget.activateListMode(); usbb_storageList.setOnItemClickListener(this); usbb_storageList.setAdapter(mAppController .getDeviceDataAdapter(StorageUtil.USBSDB)); mMiniPanelWidgets.add(mStorageB_MiniWidget); // USB Storage C mStorageC_MiniWidget = (TaskGroupListWidget) findViewById(R.id.usb_c_collection); mStorageC_MiniWidget.setGroupTag(kTagTaskGroupBase + 12); mStorageC_MiniWidget.setDefaultGroupLabel(getResources().getString( R.string.usb_storage_c)); mStorageC_MiniWidget.setEjectable(IfConfig.SIGNED_WITH_PLATFORM_KEY); AbsListView usbc_storageList = mStorageC_MiniWidget.activateListMode(); usbc_storageList.setOnItemClickListener(this); usbc_storageList.setAdapter(mAppController .getDeviceDataAdapter(StorageUtil.USBSDC)); mMiniPanelWidgets.add(mStorageC_MiniWidget); // USB Storage D mStorageD_MiniWidget = (TaskGroupListWidget) findViewById(R.id.usb_d_collection); mStorageD_MiniWidget.setGroupTag(kTagTaskGroupBase + 13); mStorageD_MiniWidget.setDefaultGroupLabel(getResources().getString( R.string.usb_storage_d)); mStorageD_MiniWidget.setEjectable(IfConfig.SIGNED_WITH_PLATFORM_KEY); AbsListView usbd_storageList = mStorageD_MiniWidget.activateListMode(); usbd_storageList.setOnItemClickListener(this); usbd_storageList.setAdapter(mAppController .getDeviceDataAdapter(StorageUtil.USBSDD)); mMiniPanelWidgets.add(mStorageD_MiniWidget); } @SuppressWarnings("unchecked") @Override protected void onCreate(Bundle savedInstanceState) { Log.i(TAG, "IfExplorer-onCreate"); mSavedStateInstatnce = savedInstanceState; super.onCreate(savedInstanceState); // FIXME: some mechanism might not be interrupted by screen rotation //setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR); // requestWindowFeature(Window.FEATURE_NO_TITLE); // getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, // WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.main_layout); // Get device display type at first, to decide UI variants. mDeviceDisplayType = getDeviceDisplayType(); restoreSavedInfo(savedInstanceState); // file manager mFileManager = FilePathUrlManager.getSingleton(mInitLocation); if (mSavedBrowseHistory != null) { mFileManager.setUrlHistory(mSavedBrowseHistory); } if (mSavedHistoryPosition >= 0) { mFileManager.setHistoryPosition(mSavedHistoryPosition); } // event handler mAppController = new IfAppController(this, mFileManager); mAppController.setDeviceDataListener(this); mAppController.setUiCallback(this); // Restore saved data for file manager and app controller if (savedInstanceState != null) { HashMap<String, ArrayList<String>> savedSearchResult = (HashMap<String, ArrayList<String>>) savedInstanceState .getSerializable(KEY_SAVE_SEARCH_RESULTS); mAppController.setCachedSearchResult(savedSearchResult); mFileManager.setSearchFilePatternPath(savedSearchResult); ArrayList<String> savedAudioFilePaths = savedInstanceState .getStringArrayList(KEY_SAVE_CACHED_AUDIO_FILEPATHS); mAppController.setCachedAudioFilePaths(savedAudioFilePaths); mFileManager.setAudioPatternPath(savedAudioFilePaths); ArrayList<String> savedVideoFilePaths = savedInstanceState .getStringArrayList(KEY_SAVE_CACHED_VIDEO_FILEPATHS); mAppController.setCachedVideoFilePaths(savedVideoFilePaths); mFileManager.setVideoPatternPath(savedVideoFilePaths); ArrayList<String> savedApkFilePaths = savedInstanceState .getStringArrayList(KEY_SAVE_CACHED_APK_FILEPATHS); mAppController.setCachedApkFilePaths(savedApkFilePaths); mFileManager.setApkPatternPath(savedApkFilePaths); } // storage monitoring mStorageIntentFilter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED); mStorageIntentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); mStorageIntentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED); mStorageIntentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED); mStorageIntentFilter.addAction(Intent.ACTION_MEDIA_REMOVED); mStorageIntentFilter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL); mStorageIntentFilter.addAction(Intent.ACTION_MEDIA_SHARED); mStorageIntentFilter.addDataScheme("file"); mStorageIntentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); registerReceiver(mStorageBroadcastReceiver, mStorageIntentFilter); // initialize mini widget intializeMiniWidgets(); // initialize storage device and do pre scan mAppController.intializeStorageDevicesAsync(); // initialize default favorites mAppController.initializeDefaultFavorites(); // refresh collection view refreshTaskGroups(); setupAddressBar(); setupFileList(); setupClipBoard(); // initialize sliding layer initializeSlidingLayer(); // update current directory mAppController.updateDirectory(mFileManager.refreshUrlContent()); // global search pre-scan preScanCategoriedFiles(); handleIntent(getIntent()); } @Override protected void onDestroy() { mAppController.cancelAllBackgroundWork(); unregisterReceiver(mStorageBroadcastReceiver); super.onDestroy(); } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); } @Override protected void onSaveInstanceState(Bundle outState) { outState.putString(KEY_SAVE_LOCATION, mFileManager.getCurrentUrl()); outState.putStringArrayList(KEY_SAVE_BROWSE_HISTORY, mFileManager.getUrlHistory()); outState.putInt(KEY_SAVE_HISTORY_POSITION, mFileManager.getHistoryPosition()); outState.putSerializable(KEY_SAVE_SEARCH_RESULTS, mAppController.getCachedSearchResult()); outState.putStringArrayList(KEY_SAVE_CACHED_AUDIO_FILEPATHS, mAppController.getCachedAudioFilePaths()); outState.putStringArrayList(KEY_SAVE_CACHED_VIDEO_FILEPATHS, mAppController.getCachedVideoFilePaths()); outState.putStringArrayList(KEY_SAVE_CACHED_APK_FILEPATHS, mAppController.getCachedApkFilePaths()); if (mLibrarySlidingLayer != null && mLibrarySlidingLayer.isOpened()) { outState.putBoolean(KEY_SAVE_SLIDING_LAYER_OPEN, true); } else { outState.putBoolean(KEY_SAVE_SLIDING_LAYER_OPEN, false); } outState.putInt(KEY_SAVE_FILE_LIST_TOTAL_NUM, mCurrentShownFileList.getCount()); outState.putInt(KEY_SAVE_FILE_LIST_SELECTED_NUM, mCurrentShownFileList.getCheckedItemCount()); super.onSaveInstanceState(outState); } protected void refreshTaskGroups() { for (TaskGroupListWidget taskGroup : mMiniPanelWidgets) { AbsListView taskList = taskGroup.activateListMode(); if (tempLOG) { Log.i("@temp", "task group: " + taskGroup.getGroupTag() + " items: " + taskList.getCount()); } if (taskList.getCount() == 0) { taskGroup.hideHeader(); } else { if (taskList.getAdapter() instanceof DeviceDataAdapter) { DeviceItem firstItem = (DeviceItem) taskList .getItemAtPosition(0); if (firstItem != null) { String deviceName = firstItem.getContainerDeviceName(); if (deviceName != null) { taskGroup.setLabel(deviceName); } else { taskGroup .setLabel(taskGroup.getDefaultGroupLabel()); } } } taskGroup.showHeader(); } } } protected void restoreSavedInfo(Bundle savedInfo) { if (savedInfo != null) { mInitLocation = savedInfo.getString(KEY_SAVE_LOCATION); mSavedBrowseHistory = savedInfo .getStringArrayList(KEY_SAVE_BROWSE_HISTORY); mSavedHistoryPosition = savedInfo.getInt(KEY_SAVE_HISTORY_POSITION); super.onRestoreInstanceState(savedInfo); } else { mInitLocation = StorageUtil.getHomeDir(); } File initDir = new File(mInitLocation); if (!initDir.exists() || !initDir.isDirectory()) { // Due to backward compatibility, this // path works in all kinds of android devices. mInitLocation = "/sdcard"; } } }