/* * Copyright (C) 2012 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.cyanogenmod.filemanager.activities; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.app.SearchManager; 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.pm.PackageManager; import android.content.res.Configuration; import android.content.res.XmlResourceParser; import android.database.Cursor; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.Manifest; import android.net.Uri; import android.nfc.NfcAdapter; import android.nfc.NfcEvent; import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Parcelable; import android.os.storage.StorageVolume; import android.provider.Settings; import android.support.v4.app.ActionBarDrawerToggle; import android.support.v4.widget.DrawerLayout; import android.text.TextUtils; import android.util.Log; import android.view.Gravity; import android.view.KeyEvent; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListPopupWindow; import android.widget.ListView; import android.widget.PopupWindow; import android.widget.SearchView; import android.widget.TextView; import android.widget.Toast; import android.widget.Toolbar; import android.widget.ArrayAdapter; import com.android.internal.util.XmlUtils; import com.cyanogenmod.filemanager.FileManagerApplication; import com.cyanogenmod.filemanager.R; import com.cyanogenmod.filemanager.activities.preferences.SettingsPreferences; import com.cyanogenmod.filemanager.adapters.MenuSettingsAdapter; import com.cyanogenmod.filemanager.console.Console; import com.cyanogenmod.filemanager.console.ConsoleAllocException; import com.cyanogenmod.filemanager.console.ConsoleBuilder; import com.cyanogenmod.filemanager.console.InsufficientPermissionsException; import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory; import com.cyanogenmod.filemanager.console.VirtualConsole; import com.cyanogenmod.filemanager.console.VirtualMountPointConsole; import com.cyanogenmod.filemanager.console.secure.SecureConsole; import com.cyanogenmod.filemanager.listeners.OnHistoryListener; import com.cyanogenmod.filemanager.listeners.OnRequestRefreshListener; import com.cyanogenmod.filemanager.model.Bookmark; import com.cyanogenmod.filemanager.model.DiskUsage; import com.cyanogenmod.filemanager.model.FileSystemObject; import com.cyanogenmod.filemanager.model.History; import com.cyanogenmod.filemanager.model.MountPoint; import com.cyanogenmod.filemanager.model.Bookmark.BOOKMARK_TYPE; import com.cyanogenmod.filemanager.parcelables.HistoryNavigable; import com.cyanogenmod.filemanager.parcelables.NavigationViewInfoParcelable; import com.cyanogenmod.filemanager.parcelables.SearchInfoParcelable; import com.cyanogenmod.filemanager.preferences.AccessMode; import com.cyanogenmod.filemanager.preferences.Bookmarks; import com.cyanogenmod.filemanager.preferences.FileManagerSettings; import com.cyanogenmod.filemanager.preferences.NavigationLayoutMode; import com.cyanogenmod.filemanager.preferences.ObjectIdentifier; import com.cyanogenmod.filemanager.preferences.Preferences; import com.cyanogenmod.filemanager.ui.IconHolder; import com.cyanogenmod.filemanager.ui.ThemeManager; import com.cyanogenmod.filemanager.ui.ThemeManager.Theme; import com.cyanogenmod.filemanager.ui.dialogs.ActionsDialog; import com.cyanogenmod.filemanager.ui.dialogs.FilesystemInfoDialog; import com.cyanogenmod.filemanager.ui.dialogs.InitialDirectoryDialog; import com.cyanogenmod.filemanager.ui.dialogs.FilesystemInfoDialog.OnMountListener; import com.cyanogenmod.filemanager.ui.widgets.Breadcrumb; import com.cyanogenmod.filemanager.ui.widgets.ButtonItem; import com.cyanogenmod.filemanager.ui.widgets.NavigationCustomTitleView; import com.cyanogenmod.filemanager.ui.widgets.NavigationView; import com.cyanogenmod.filemanager.ui.widgets.NavigationView.OnNavigationRequestMenuListener; import com.cyanogenmod.filemanager.ui.widgets.NavigationView.OnNavigationSelectionChangedListener; import com.cyanogenmod.filemanager.ui.widgets.SelectionView; import com.cyanogenmod.filemanager.util.AndroidHelper; import com.cyanogenmod.filemanager.util.BookmarksHelper; import com.cyanogenmod.filemanager.util.CommandHelper; import com.cyanogenmod.filemanager.util.DialogHelper; import com.cyanogenmod.filemanager.util.ExceptionUtil; import com.cyanogenmod.filemanager.util.ExceptionUtil.OnRelaunchCommandResult; import com.cyanogenmod.filemanager.util.FileHelper; import com.cyanogenmod.filemanager.util.MimeTypeHelper.MimeTypeCategory; import com.cyanogenmod.filemanager.util.MountPointHelper; import com.cyanogenmod.filemanager.util.StorageHelper; import com.cyngn.uicommon.view.Snackbar; import java.io.File; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import static com.cyanogenmod.filemanager.util.MimeTypeHelper.MimeTypeCategory.*; /** * The main navigation activity. This activity is the center of the application. * From this the user can navigate, search, make actions.
* This activity is singleTop, so when it is displayed no other activities exists in * the stack.
* This cause an issue with the saved instance of this class, because if another activity * is displayed, and the process is killed, NavigationActivity is started and the saved * instance gets corrupted.
* For this reason the methods {link {@link Activity#onSaveInstanceState(Bundle)} and * {@link Activity#onRestoreInstanceState(Bundle)} are not implemented, and every time * the app is killed, is restarted from his initial state. */ public class NavigationActivity extends Activity implements OnHistoryListener, OnRequestRefreshListener, OnNavigationRequestMenuListener, OnNavigationSelectionChangedListener { private static final String TAG = "NavigationActivity"; //$NON-NLS-1$ private static boolean DEBUG = false; // Bookmark list XML tags private static final String TAG_BOOKMARKS = "Bookmarks"; //$NON-NLS-1$ private static final String TAG_BOOKMARK = "bookmark"; //$NON-NLS-1$ private static final String STR_USB = "usb"; // $NON-NLS-1$ /** * Intent code for request a search. */ public static final int INTENT_REQUEST_SEARCH = 10001; /** * Intent code for request a search. */ public static final int INTENT_REQUEST_SETTINGS = 20001; /** * Constant for extra information about selected search entry. */ public static final String EXTRA_SEARCH_ENTRY_SELECTION = "extra_search_entry_selection"; //$NON-NLS-1$ /** * Constant for extra information about last search data. */ public static final String EXTRA_SEARCH_LAST_SEARCH_DATA = "extra_search_last_search_data"; //$NON-NLS-1$ /** * Constant for extra information for request a navigation to the passed path. */ public static final String EXTRA_NAVIGATE_TO = "extra_navigate_to"; //$NON-NLS-1$ /** * Constant for extra information for request to add navigation to the history */ public static final String EXTRA_ADD_TO_HISTORY = "extra_add_to_history"; //$NON-NLS-1$ // The timeout needed to reset the exit status for back button // After this time user need to tap 2 times the back button to // exit, and the toast is shown again after the first tap. private static final int RELEASE_EXIT_CHECK_TIMEOUT = 3500; private Toolbar mToolBar; private SearchView mSearchView; private NavigationCustomTitleView mCustomTitleView; private InputMethodManager mImm; private FilesystemInfoDialog.OnConfigChangeListener mOnConfigChangeListener; private ListPopupWindow mPopupWindow; private final BroadcastReceiver mNotificationReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent != null) { if (intent.getAction().compareTo(FileManagerSettings.INTENT_SETTING_CHANGED) == 0) { // The settings has changed String key = intent.getStringExtra(FileManagerSettings.EXTRA_SETTING_CHANGED_KEY); if (key != null) { // Disk usage warning level if (key.compareTo(FileManagerSettings. SETTINGS_DISK_USAGE_WARNING_LEVEL.getId()) == 0) { // Set the free disk space warning level of the breadcrumb widget Breadcrumb breadcrumb = getCurrentNavigationView().getBreadcrumb(); String fds = Preferences.getSharedPreferences().getString( FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getId(), (String)FileManagerSettings. SETTINGS_DISK_USAGE_WARNING_LEVEL.getDefaultValue()); breadcrumb.setFreeDiskSpaceWarningLevel(Integer.parseInt(fds)); breadcrumb.updateMountPointInfo(); return; } // Case sensitive sort if (key.compareTo(FileManagerSettings. SETTINGS_CASE_SENSITIVE_SORT.getId()) == 0) { getCurrentNavigationView().refresh(); return; } // Display thumbs if (key.compareTo(FileManagerSettings. SETTINGS_DISPLAY_THUMBS.getId()) == 0) { // Clean the icon cache applying the current theme applyTheme(); return; } // Use flinger if (key.compareTo(FileManagerSettings. SETTINGS_USE_FLINGER.getId()) == 0) { boolean useFlinger = Preferences.getSharedPreferences().getBoolean( FileManagerSettings.SETTINGS_USE_FLINGER.getId(), ((Boolean)FileManagerSettings. SETTINGS_USE_FLINGER. getDefaultValue()).booleanValue()); getCurrentNavigationView().setUseFlinger(useFlinger); return; } // Access mode if (key.compareTo(FileManagerSettings. SETTINGS_ACCESS_MODE.getId()) == 0) { // Is it necessary to create or exit of the ChRooted? boolean chRooted = FileManagerApplication. getAccessMode().compareTo(AccessMode.SAFE) == 0; if (chRooted != NavigationActivity.this.mChRooted) { if (chRooted) { createChRooted(); } else { exitChRooted(); } } } // Restricted access if (key.compareTo(FileManagerSettings. SETTINGS_RESTRICT_SECONDARY_USERS_ACCESS.getId()) == 0) { if (AndroidHelper.isSecondaryUser(context)) { try { Preferences.savePreference( FileManagerSettings.SETTINGS_ACCESS_MODE, AccessMode.SAFE, true); } catch (Throwable ex) { Log.w(TAG, "can't save console preference", ex); //$NON-NLS-1$ } ConsoleBuilder.changeToNonPrivilegedConsole(context); createChRooted(); } } // Filetime format mode if (key.compareTo(FileManagerSettings. SETTINGS_FILETIME_FORMAT_MODE.getId()) == 0) { // Refresh the data synchronized (FileHelper.DATETIME_SYNC) { FileHelper.sReloadDateTimeFormats = true; NavigationActivity.this.getCurrentNavigationView().refresh(); } } } } else if (intent.getAction().compareTo( FileManagerSettings.INTENT_FILE_CHANGED) == 0) { // Retrieve the file that was changed String file = intent.getStringExtra(FileManagerSettings.EXTRA_FILE_CHANGED_KEY); try { FileSystemObject fso = CommandHelper.getFileInfo(context, file, null); if (fso != null) { getCurrentNavigationView().refresh(fso); } } catch (Exception e) { ExceptionUtil.translateException(context, e, true, false); } } else if (intent.getAction().compareTo( FileManagerSettings.INTENT_THEME_CHANGED) == 0) { applyTheme(); } else if (intent.getAction().compareTo(Intent.ACTION_TIME_CHANGED) == 0 || intent.getAction().compareTo(Intent.ACTION_DATE_CHANGED) == 0 || intent.getAction().compareTo(Intent.ACTION_TIMEZONE_CHANGED) == 0 || intent.getAction().compareTo(Intent.ACTION_LOCALE_CHANGED) == 0) { // Refresh the data synchronized (FileHelper.DATETIME_SYNC) { FileHelper.sReloadDateTimeFormats = true; NavigationActivity.this.getCurrentNavigationView().refresh(); } } else if (intent.getAction().compareTo( FileManagerSettings.INTENT_MOUNT_STATUS_CHANGED) == 0 || intent.getAction().equals(Intent.ACTION_MEDIA_MOUNTED) || intent.getAction().equals(Intent.ACTION_MEDIA_UNMOUNTED)) { MountPointHelper.refreshMountPoints( FileManagerApplication.getBackgroundConsole()); onRequestBookmarksRefresh(); removeUnmountedHistory(); removeUnmountedSelection(); } } } }; private OnClickListener mOnClickDrawerTabListener = new OnClickListener() { @Override public void onClick(View v) { switch (v.getId()) { case R.id.drawer_bookmarks_tab: if (!mBookmarksTab.isSelected()) { mBookmarksTab.setSelected(true); mHistoryTab.setSelected(false); mBookmarksTab.setTextAppearance( NavigationActivity.this, R.style.primary_text_appearance); mHistoryTab.setTextAppearance( NavigationActivity.this, R.style.secondary_text_appearance); mHistoryLayout.setVisibility(View.GONE); mBookmarksLayout.setVisibility(View.VISIBLE); applyTabTheme(); try { Preferences.savePreference(FileManagerSettings.USER_PREF_LAST_DRAWER_TAB, Integer.valueOf(0), true); } catch (Exception ex) { Log.e(TAG, "Can't save last drawer tab", ex); //$NON-NLS-1$ } mClearHistory.setVisibility(View.GONE); } break; case R.id.drawer_history_tab: if (!mHistoryTab.isSelected()) { mHistoryTab.setSelected(true); mBookmarksTab.setSelected(false); mHistoryTab.setTextAppearance( NavigationActivity.this, R.style.primary_text_appearance); mBookmarksTab.setTextAppearance( NavigationActivity.this, R.style.secondary_text_appearance); mBookmarksLayout.setVisibility(View.GONE); mHistoryLayout.setVisibility(View.VISIBLE); applyTabTheme(); try { Preferences.savePreference(FileManagerSettings.USER_PREF_LAST_DRAWER_TAB, Integer.valueOf(1), true); } catch (Exception ex) { Log.e(TAG, "Can't save last drawer tab", ex); //$NON-NLS-1$ } mClearHistory.setVisibility(mHistory.size() > 0 ? View.VISIBLE : View.GONE); } break; default: break; } } }; private OnClickListener mOnClickDrawerActionBarListener = new OnClickListener() { @Override public void onClick(View v) { switch (v.getId()) { case R.id.ab_settings: mDrawerLayout.closeDrawer(Gravity.START); openSettings(); break; case R.id.ab_clear_history: clearHistory(); mClearHistory.setVisibility(View.GONE); break; default: break; } } }; static String MIME_TYPE_LOCALIZED_NAMES[]; /** * @hide */ static Map EASY_MODE_ICONS = new HashMap(); /** * @hide */ NavigationView[] mNavigationViews; /** * @hide */ ListView mEasyModeListView; private List mHistory; private static final List EASY_MODE_LIST = new ArrayList() { { add(NONE); add(IMAGE); add(VIDEO); add(AUDIO); add(DOCUMENT); add(APP); } }; private ArrayAdapter mEasyModeAdapter; private View.OnClickListener mEasyModeItemClickListener = new View.OnClickListener() { @Override public void onClick(View view) { Integer position = (Integer) view.getTag(); onClicked(position); } }; private int mCurrentNavigationView; private ViewGroup mActionBar; private SelectionView mSelectionBar; private DrawerLayout mDrawerLayout; private ViewGroup mDrawer; private ActionBarDrawerToggle mDrawerToggle; private LinearLayout mDrawerHistory; private TextView mDrawerHistoryEmpty; private TextView mBookmarksTab; private TextView mHistoryTab; private View mBookmarksLayout; private View mHistoryLayout; private ButtonItem mSettings; private ButtonItem mClearHistory; private List mBookmarks; private List mSdBookmarks; private LinearLayout mDrawerBookmarks; private boolean mExitFlag = false; private long mExitBackTimeout = -1; private Dialog mActiveDialog = null; private int mOrientation; private boolean mNeedsEasyMode = false; private boolean mDisplayingSearchResults; /** * @hide */ boolean mChRooted; /** * @hide */ Handler mHandler; private AsyncTask mBookmarksTask; private static final int REQUEST_CODE_STORAGE_PERMS = 321; private boolean hasPermissions() { int res = checkCallingOrSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE); return (res == PackageManager.PERMISSION_GRANTED); } private void requestNecessaryPermissions() { String[] permissions = new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE, }; requestPermissions(permissions, REQUEST_CODE_STORAGE_PERMS); } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grandResults) { boolean allowed = true; switch (requestCode) { case REQUEST_CODE_STORAGE_PERMS: for (int res : grandResults) { allowed = allowed && (res == PackageManager.PERMISSION_GRANTED); } break; default: allowed = false; break; } if (allowed) { finishOnCreate(); if (mDrawerToggle != null) { mDrawerToggle.syncState(); } } else { if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { String text = getResources().getString(R.string.storage_permissions_denied); final ViewGroup viewGroup = (ViewGroup) ((ViewGroup) this .findViewById(android.R.id.content)).getChildAt(0); if (viewGroup != null) { Snackbar snackbar = Snackbar.make(viewGroup, text, Snackbar.LENGTH_INDEFINITE, 3); snackbar.setAction(android.R.string.ok, new OnClickListener() { @Override public void onClick(View v) { requestNecessaryPermissions(); } }); snackbar.show(); } } else { StringBuilder builder = new StringBuilder(getString(R.string .storage_permissions_denied)); builder.append("\n\n"); builder.append(getString(R.string.storage_permissions_explanation)); final ViewGroup viewGroup = (ViewGroup) ((ViewGroup) this .findViewById(android.R.id.content)).getChildAt(0); if (viewGroup != null) { Snackbar snackbar = Snackbar.make(viewGroup, builder.toString(), Snackbar.LENGTH_INDEFINITE, 7); snackbar.setAction(R.string.snackbar_settings, new OnClickListener() { @Override public void onClick(View v) { startInstalledAppDetailsActivity(NavigationActivity.this); finish(); } }); snackbar.show(); } } } } public static void startInstalledAppDetailsActivity(final Activity context) { if (context == null) { return; } final Intent i = new Intent(); i.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); i.addCategory(Intent.CATEGORY_DEFAULT); i.setData(Uri.parse("package:" + context.getPackageName())); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); i.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); context.startActivity(i); } private void finishOnCreate() { // Register the broadcast receiver IntentFilter filter = new IntentFilter(); filter.addAction(FileManagerSettings.INTENT_SETTING_CHANGED); filter.addAction(FileManagerSettings.INTENT_FILE_CHANGED); filter.addAction(FileManagerSettings.INTENT_THEME_CHANGED); filter.addAction(Intent.ACTION_DATE_CHANGED); filter.addAction(Intent.ACTION_TIME_CHANGED); filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); filter.addAction(Intent.ACTION_LOCALE_CHANGED); filter.addAction(FileManagerSettings.INTENT_MOUNT_STATUS_CHANGED); registerReceiver(this.mNotificationReceiver, filter); // This filter needs the file data scheme, so it must be defined separately. IntentFilter newFilter = new IntentFilter(); newFilter.addAction(Intent.ACTION_MEDIA_MOUNTED); newFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED); newFilter.addDataScheme(ContentResolver.SCHEME_FILE); registerReceiver(mNotificationReceiver, newFilter); //the input manager service mImm = (InputMethodManager) this.getSystemService( Context.INPUT_METHOD_SERVICE); //Initialize nfc adapter NfcAdapter mNfcAdapter = NfcAdapter.getDefaultAdapter(this); if (mNfcAdapter != null) { mNfcAdapter.setBeamPushUrisCallback(new NfcAdapter.CreateBeamUrisCallback() { @Override public Uri[] createBeamUris(NfcEvent event) { List selectedFiles = getCurrentNavigationView().getSelectedFiles(); if (selectedFiles.size() > 0) { List fileUri = new ArrayList(); for (FileSystemObject f : selectedFiles) { //Beam ignores folders and system files if (!FileHelper.isDirectory(f) && !FileHelper.isSystemFile(f)) { fileUri.add(Uri.fromFile(new File(f.getFullPath()))); } } if (fileUri.size() > 0) { return fileUri.toArray(new Uri[fileUri.size()]); } } return null; } }, this); } //Initialize activity init(); //Navigation views initNavigationViews(); // As we're using a Toolbar, we should retrieve it and set it // to be our ActionBar mToolBar = (Toolbar) findViewById(R.id.material_toolbar); setActionBar(mToolBar); //Initialize action bars initTitleActionBar(); initStatusActionBar(); initSelectionBar(); // Initialize navigation drawer initDrawer(); initBookmarks(); // Adjust layout (only when start on landscape mode) int orientation = getResources().getConfiguration().orientation; if (orientation == Configuration.ORIENTATION_LANDSCAPE) { onLayoutChanged(); } this.mOrientation = orientation; // Apply the theme applyTheme(); // Show welcome message showWelcomeMsg(); this.mHandler = new Handler(); this.mHandler.post(new Runnable() { @Override public void run() { // Initialize console initConsole(); //Initialize navigation int cc = NavigationActivity.this.mNavigationViews.length; for (int i = 0; i < cc; i++) { initNavigation(i, false, getIntent()); } //Check the intent action checkIntent(getIntent()); } }); MIME_TYPE_LOCALIZED_NAMES = MimeTypeCategory.getFriendlyLocalizedNames(NavigationActivity .this); EASY_MODE_ICONS.put(MimeTypeCategory.NONE, getResources().getDrawable(R.drawable .ic_em_all)); EASY_MODE_ICONS.put(MimeTypeCategory.IMAGE, getResources().getDrawable(R.drawable .ic_em_image)); EASY_MODE_ICONS.put(MimeTypeCategory.VIDEO, getResources().getDrawable(R.drawable .ic_em_video)); EASY_MODE_ICONS.put(MimeTypeCategory.AUDIO, getResources().getDrawable(R.drawable .ic_em_music)); EASY_MODE_ICONS.put(MimeTypeCategory.DOCUMENT, getResources().getDrawable(R.drawable .ic_em_document)); EASY_MODE_ICONS.put(MimeTypeCategory.APP, getResources().getDrawable(R.drawable .ic_em_application)); } /** * {@inheritDoc} */ @Override protected void onCreate(Bundle state) { if (DEBUG) { Log.d(TAG, "NavigationActivity.onCreate"); //$NON-NLS-1$ } // Set the theme before setContentView Theme theme = ThemeManager.getCurrentTheme(this); theme.setBaseThemeNoActionBar(this); //Set the main layout of the activity setContentView(R.layout.navigation); //Save state super.onCreate(state); if (!hasPermissions()) { requestNecessaryPermissions(); } else { finishOnCreate(); } } @Override protected void onStart() { super.onStart(); // Check restrictions if (!hasPermissions() || !FileManagerApplication.checkRestrictSecondaryUsersAccess(this, mChRooted)) { return; } // Check that the current dir is mounted (for virtual filesystems) String curDir = mNavigationViews[mCurrentNavigationView].getCurrentDir(); if (curDir != null) { VirtualMountPointConsole vc = VirtualMountPointConsole.getVirtualConsoleForPath( mNavigationViews[mCurrentNavigationView].getCurrentDir()); if (vc != null && !vc.isMounted()) { onRequestBookmarksRefresh(); removeUnmountedHistory(); removeUnmountedSelection(); } if (mDisplayingSearchResults) { mDisplayingSearchResults = false; closeSearch(); } getCurrentNavigationView().refresh(true); } } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); // Sync the toggle state after onRestoreInstanceState has occurred. if (mDrawerToggle != null) { mDrawerToggle.syncState(); } } /** * {@inheritDoc} */ @Override protected void onNewIntent(Intent intent) { // If no directory specified, restore current directory final String navigateTo = intent.getStringExtra(EXTRA_NAVIGATE_TO); final boolean restore = TextUtils.isEmpty(navigateTo); //Initialize navigation if (!hasPermissions()) { requestNecessaryPermissions(); } else { initNavigation(this.mCurrentNavigationView, restore, intent); } //Check the intent action checkIntent(intent); } /** * {@inheritDoc} */ @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (hasPermissions()) { onLayoutChanged(); if (mDrawerToggle != null ) { mDrawerToggle.onConfigurationChanged(newConfig); } } if (mActiveDialog != null && mOnConfigChangeListener != null) { mOnConfigChangeListener.onConfigurationChanged(newConfig); } NavigationView navView = getCurrentNavigationView(); if (navView != null) { navView.refreshViewMode(); } if (mPopupWindow != null) { mPopupWindow.postShow(); } } /** * {@inheritDoc} */ @Override public boolean onOptionsItemSelected(MenuItem item) { if (mDrawerToggle.onOptionsItemSelected(item)) { return true; } if (mNeedsEasyMode) { if (item.getItemId() == android.R.id.home) { if (mHistory.size() == 0 && !isEasyModeVisible()) { performShowEasyMode(); } else { back(); } } } return super.onOptionsItemSelected(item); } /** * {@inheritDoc} */ @Override protected void onDestroy() { if (DEBUG) { Log.d(TAG, "NavigationActivity.onDestroy"); //$NON-NLS-1$ } if (mActiveDialog != null && mActiveDialog.isShowing()) { mActiveDialog.dismiss(); } // Unregister the receiver try { unregisterReceiver(this.mNotificationReceiver); } catch (Throwable ex) { /**NON BLOCK**/ } recycle(); //All destroy. Continue super.onDestroy(); } /** * Method that returns the current navigation view. * * @return NavigationView The current navigation view */ public NavigationView getCurrentNavigationView() { return getNavigationView(this.mCurrentNavigationView); } /** * Method that returns the current navigation view. * * @param viewId The view to return * @return NavigationView The current navigation view */ public NavigationView getNavigationView(int viewId) { if (this.mNavigationViews == null) return null; return this.mNavigationViews[viewId]; } /** * Method that initializes the activity. */ private void init() { this.mHistory = new ArrayList(); this.mChRooted = FileManagerApplication.getAccessMode().compareTo(AccessMode.SAFE) == 0; } /** * Method that displays a welcome message the first time the user * access the application */ private void showWelcomeMsg() { boolean firstUse = Preferences.getSharedPreferences().getBoolean( FileManagerSettings.SETTINGS_FIRST_USE.getId(), ((Boolean)FileManagerSettings.SETTINGS_FIRST_USE.getDefaultValue()).booleanValue()); //Display the welcome message? if (firstUse && FileManagerApplication.hasShellCommands()) { // open navigation drawer to show user that it exists mDrawerLayout.openDrawer(Gravity.START); AlertDialog dialog = DialogHelper.createAlertDialog(this, R.mipmap.ic_launcher_filemanager, R.string.welcome_title, getString(R.string.welcome_msg), false); DialogHelper.delegateDialogShow(this, dialog); // Don't display again this dialog try { Preferences.savePreference( FileManagerSettings.SETTINGS_FIRST_USE, Boolean.FALSE, true); } catch (Exception e) {/**NON BLOCK**/} } } /** * Method that initializes the titlebar of the activity. */ private void initTitleActionBar() { //Inflate the view and associate breadcrumb View titleLayout = getLayoutInflater().inflate( R.layout.navigation_view_customtitle, null, false); NavigationCustomTitleView title = (NavigationCustomTitleView)titleLayout.findViewById(R.id.navigation_title_flipper); title.setOnHistoryListener(this); Breadcrumb breadcrumb = (Breadcrumb)title.findViewById(R.id.breadcrumb_view); int cc = this.mNavigationViews.length; for (int i = 0; i < cc; i++) { this.mNavigationViews[i].setBreadcrumb(breadcrumb); this.mNavigationViews[i].setOnHistoryListener(this); this.mNavigationViews[i].setOnNavigationSelectionChangedListener(this); this.mNavigationViews[i].setOnNavigationOnRequestMenuListener(this); this.mNavigationViews[i].setCustomTitle(title); } // Set the free disk space warning level of the breadcrumb widget String fds = Preferences.getSharedPreferences().getString( FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getId(), (String)FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getDefaultValue()); breadcrumb.setFreeDiskSpaceWarningLevel(Integer.parseInt(fds)); //Configure the action bar options getActionBar().setBackgroundDrawable( getResources().getDrawable(R.drawable.bg_material_titlebar)); mToolBar.addView(titleLayout); } /** * Method that initializes the statusbar of the activity. */ private void initStatusActionBar() { //Performs a width calculation of buttons. Buttons exceeds the width //of the action bar should be hidden //This application not use android ActionBar because the application //make uses of the title and bottom areas, and wants to force to show //the overflow button (without care of physical buttons) this.mActionBar = (ViewGroup)findViewById(R.id.navigation_actionbar); this.mActionBar.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { @Override public void onLayoutChange( View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { //Get the width of the action bar int w = v.getMeasuredWidth(); //Wake through children calculation his dimensions int bw = (int)getResources().getDimension(R.dimen.default_buttom_width); int cw = 0; final ViewGroup abView = ((ViewGroup)v); int cc = abView.getChildCount(); for (int i = 0; i < cc; i++) { View child = abView.getChildAt(i); child.setVisibility(cw + bw > w ? View.INVISIBLE : View.VISIBLE); cw += bw; } } }); // Have overflow menu? Actually no. There is only a search action, so just hide // the overflow View overflow = findViewById(R.id.ab_overflow); overflow.setVisibility(View.GONE); // Show the status bar View statusBar = findViewById(R.id.navigation_statusbar_portrait_holder); statusBar.setVisibility(View.VISIBLE); } /** * Method that initializes the selectionbar of the activity. */ private void initSelectionBar() { this.mSelectionBar = (SelectionView)findViewById(R.id.navigation_selectionbar); } /** * Method that initializes the navigation drawer of the activity. */ private void initDrawer() { mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); //Set our status bar color mDrawerLayout.setStatusBarBackgroundColor(R.color.material_palette_blue_primary_dark); mDrawer = (ViewGroup) findViewById(R.id.drawer); mDrawerBookmarks = (LinearLayout) findViewById(R.id.bookmarks_list); mDrawerHistory = (LinearLayout) findViewById(R.id.history_list); mDrawerHistoryEmpty = (TextView) findViewById(R.id.history_empty); mBookmarksLayout = findViewById(R.id.drawer_bookmarks); mHistoryLayout = findViewById(R.id.drawer_history); mBookmarksTab = (TextView) findViewById(R.id.drawer_bookmarks_tab); mHistoryTab = (TextView) findViewById(R.id.drawer_history_tab); mBookmarksTab.setOnClickListener(mOnClickDrawerTabListener); mHistoryTab.setOnClickListener(mOnClickDrawerTabListener); mSettings = (ButtonItem) findViewById(R.id.ab_settings); mSettings.setOnClickListener(mOnClickDrawerActionBarListener); mClearHistory = (ButtonItem) findViewById(R.id.ab_clear_history); mClearHistory.setOnClickListener(mOnClickDrawerActionBarListener); // Restore the last tab pressed Integer lastTab = Preferences.getSharedPreferences().getInt( FileManagerSettings.USER_PREF_LAST_DRAWER_TAB.getId(), (Integer) FileManagerSettings.USER_PREF_LAST_DRAWER_TAB .getDefaultValue()); mOnClickDrawerTabListener.onClick(lastTab == 0 ? mBookmarksTab : mHistoryTab); // Set the navigation drawer "hamburger" icon mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.drawable.ic_material_light_navigation_drawer, R.string.drawer_open, R.string.drawer_close) { /** Called when a drawer has settled in a completely closed state. */ public void onDrawerClosed(View view) { super.onDrawerClosed(view); } /** Called when a drawer has settled in a completely open state. */ public void onDrawerOpened(View drawerView) { onDrawerLayoutOpened(drawerView); super.onDrawerOpened(drawerView); } }; getActionBar().setDisplayHomeAsUpEnabled(true); // Set the drawer toggle as the DrawerListener mDrawerLayout.setDrawerListener(mDrawerToggle); } /*** * Method that do something when the DrawerLayout opened. */ private void onDrawerLayoutOpened(View drawerView){ if (mSearchView != null && mSearchView.getVisibility() == View.VISIBLE) { closeSearch(); hideSoftInput(drawerView); } } /** * Method that hide the software when the software showing. * * */ private void hideSoftInput(View view){ if (mImm != null) { mImm.hideSoftInputFromWindow(view.getWindowToken(), 0); } } /** * Method that adds a history entry to the history list in the drawer */ private void addHistoryToDrawer(int index, HistoryNavigable navigable) { // hide empty message mDrawerHistoryEmpty.setVisibility(View.GONE); Theme theme = ThemeManager.getCurrentTheme(this); IconHolder iconholder = new IconHolder(this, false); // inflate single bookmark layout item and fill it LinearLayout view = (LinearLayout) getLayoutInflater().inflate( R.layout.history_item, null); ImageView iconView = (ImageView) view .findViewById(R.id.history_item_icon); TextView name = (TextView) view.findViewById(R.id.history_item_name); TextView directory = (TextView) view .findViewById(R.id.history_item_directory); Drawable icon = iconholder.getDrawable("ic_fso_folder_drawable"); //$NON-NLS-1$ if (navigable instanceof SearchInfoParcelable) { icon = iconholder.getDrawable("ic_history_search_drawable"); //$NON-NLS-1$ } iconView.setImageDrawable(icon); String title = navigable.getTitle(); if (title == null || title.trim().length() == 0) { title = getString(R.string.root_directory_name); } name.setText(title); directory.setText(navigable.getDescription()); theme.setTextColor(this, name, "text_color"); theme.setTextColor(this, directory, "text_color"); // handle item click view.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { final int index = mDrawerHistory.indexOfChild(v); final int count = mDrawerHistory.getChildCount(); final History history = mHistory.get(count - index - 1); navigateToHistory(history); mDrawerLayout.closeDrawer(Gravity.START); } }); // add as first child mDrawerHistory.addView(view, 0); // Show clear button if history tab is selected mClearHistory.setVisibility(mHistoryTab.isSelected() ? View.VISIBLE : View.GONE); } /** * Method takes a bookmark as argument and adds it to mBookmarks and the * list in the drawer */ public void addBookmark(Bookmark bookmark) { mBookmarks.add(bookmark); addBookmarkToDrawer(bookmark); } /** * Show the easy mode view */ private void performShowEasyMode() { mEasyModeListView.setVisibility(View.VISIBLE); getCurrentNavigationView().setVisibility(View.GONE); performShowBackArrow(false); } /** * Hide the easy mode view */ private void performHideEasyMode() { mEasyModeListView.setVisibility(View.GONE); getCurrentNavigationView().setVisibility(View.VISIBLE); } private void performShowBackArrow(boolean showBackArrow) { if (mNeedsEasyMode) { mDrawerToggle.setDrawerIndicatorEnabled(!showBackArrow); } } private boolean isEasyModeVisible() { return mEasyModeListView.getVisibility() != View.GONE; } /** * Method takes a bookmark as argument and adds it to the bookmark list in * the drawer */ private void addBookmarkToDrawer(Bookmark bookmark) { Theme theme = ThemeManager.getCurrentTheme(this); IconHolder iconholder = new IconHolder(this, false); // inflate single bookmark layout item and fill it LinearLayout view = (LinearLayout) getLayoutInflater().inflate( R.layout.bookmarks_item, null); ImageView icon = (ImageView) view .findViewById(R.id.bookmarks_item_icon); TextView name = (TextView) view.findViewById(R.id.bookmarks_item_name); TextView path = (TextView) view.findViewById(R.id.bookmarks_item_path); ImageButton actionButton = (ImageButton) view .findViewById(R.id.bookmarks_item_action); name.setText(bookmark.mName); path.setText(bookmark.mPath); theme.setTextColor(this, name, "text_color"); theme.setTextColor(this, path, "text_color"); icon.setImageDrawable(iconholder.getDrawable(BookmarksHelper .getIcon(bookmark))); Drawable action = null; String actionCd = null; if (bookmark.mType.compareTo(BOOKMARK_TYPE.HOME) == 0) { action = iconholder.getDrawable("ic_edit_home_bookmark_drawable"); //$NON-NLS-1$ actionCd = getApplicationContext().getString( R.string.bookmarks_button_config_cd); } else if (bookmark.mType.compareTo(BOOKMARK_TYPE.USER_DEFINED) == 0) { action = iconholder.getDrawable("ic_close_drawable"); //$NON-NLS-1$ actionCd = getApplicationContext().getString( R.string.bookmarks_button_remove_bookmark_cd); } actionButton.setImageDrawable(action); actionButton.setVisibility(action != null ? View.VISIBLE : View.GONE); actionButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { final View v = (View) view.getParent(); final int index = mDrawerBookmarks.indexOfChild(v); final Bookmark bookmark = mBookmarks.get(index); // Configure home if (bookmark.mType.compareTo(BOOKMARK_TYPE.HOME) == 0) { // Show a dialog for configure initial directory InitialDirectoryDialog dialog = new InitialDirectoryDialog( NavigationActivity.this); dialog.setOnValueChangedListener(new InitialDirectoryDialog.OnValueChangedListener() { @Override public void onValueChanged(String newInitialDir) { bookmark.mPath = newInitialDir; // reset drawer bookmarks list initBookmarks(); } }); dialog.show(); return; } // Remove bookmark if (bookmark.mType.compareTo(BOOKMARK_TYPE.USER_DEFINED) == 0) { boolean result = Bookmarks.removeBookmark( getApplicationContext(), bookmark); if (!result) { // Show warning DialogHelper.showToast(getApplicationContext(), R.string.msgs_operation_failure, Toast.LENGTH_SHORT); return; } mBookmarks.remove(bookmark); mDrawerBookmarks.removeView(v); return; } } }); actionButton.setContentDescription(actionCd); // handle item click view.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { final int index = mDrawerBookmarks.indexOfChild(v); final Bookmark bookmark = mBookmarks.get(index); boolean showEasyMode = (mSdBookmarks.contains(bookmark)) && getResources().getBoolean(R.bool.cmcc_show_easy_mode); // try to navigate to the bookmark path try { FileSystemObject fso = CommandHelper.getFileInfo( getApplicationContext(), bookmark.mPath, null); if (fso != null) { if (showEasyMode) { performShowEasyMode(); } else { performHideEasyMode(); } performShowBackArrow(!mDrawerToggle.isDrawerIndicatorEnabled()); getCurrentNavigationView().open(fso); mDrawerLayout.closeDrawer(Gravity.START); } else { // The bookmark does not exist, delete the user-defined // bookmark try { Bookmarks.removeBookmark(getApplicationContext(), bookmark); // reset bookmarks list to default initBookmarks(); } catch (Exception ex) { } } } catch (Exception e) { // Capture the exception ExceptionUtil .translateException(NavigationActivity.this, e); if (e instanceof NoSuchFileOrDirectory || e instanceof FileNotFoundException) { // The bookmark does not exist, delete the user-defined // bookmark try { Bookmarks.removeBookmark(getApplicationContext(), bookmark); // reset bookmarks list to default initBookmarks(); } catch (Exception ex) { } } return; } } }); mDrawerBookmarks.addView(view); } /** * Method that initializes the bookmarks. */ private synchronized void initBookmarks() { if (mBookmarksTask != null && !mBookmarksTask.getStatus().equals(AsyncTask.Status.FINISHED)) { return; } // Retrieve the loading view final View waiting = findViewById(R.id.bookmarks_loading); // Load bookmarks in background mBookmarksTask = new AsyncTask() { Exception mCause; @Override protected Boolean doInBackground(Void... params) { try { mBookmarks = loadBookmarks(); return Boolean.TRUE; } catch (Exception e) { this.mCause = e; return Boolean.FALSE; } } @Override protected void onPreExecute() { waiting.setVisibility(View.VISIBLE); mDrawerBookmarks.removeAllViews(); } @Override protected void onPostExecute(Boolean result) { waiting.setVisibility(View.GONE); if (result.booleanValue()) { for (Bookmark bookmark : mBookmarks) { addBookmarkToDrawer(bookmark); } } else { if (this.mCause != null) { ExceptionUtil.translateException( NavigationActivity.this, this.mCause); } } mBookmarksTask = null; } @Override protected void onCancelled() { waiting.setVisibility(View.GONE); mBookmarksTask = null; } }; mBookmarksTask.execute(); } /** * Method that loads all kind of bookmarks and join in an array to be used * in the listview adapter. * * @return List * @hide */ List loadBookmarks() { // Bookmarks = HOME + FILESYSTEM + SD STORAGES + USER DEFINED // In ChRooted mode = SD STORAGES + USER DEFINED (from SD STORAGES) List bookmarks = new ArrayList(); if (!this.mChRooted) { bookmarks.add(loadHomeBookmarks()); bookmarks.addAll(loadFilesystemBookmarks()); } mSdBookmarks = loadSdStorageBookmarks(); bookmarks.addAll(mSdBookmarks); bookmarks.addAll(loadVirtualBookmarks()); bookmarks.addAll(loadUserBookmarks()); return bookmarks; } /** * Method that loads the home bookmark from the user preference. * * @return Bookmark The bookmark loaded */ private Bookmark loadHomeBookmarks() { String initialDir = Preferences.getSharedPreferences().getString( FileManagerSettings.SETTINGS_INITIAL_DIR.getId(), (String) FileManagerSettings.SETTINGS_INITIAL_DIR .getDefaultValue()); return new Bookmark(BOOKMARK_TYPE.HOME, getString(R.string.bookmarks_home), initialDir); } /** * Method that loads the filesystem bookmarks from the internal xml file. * (defined by this application) * * @return List The bookmarks loaded */ private List loadFilesystemBookmarks() { try { // Initialize the bookmarks List bookmarks = new ArrayList(); // Read the command list xml file XmlResourceParser parser = getResources().getXml( R.xml.filesystem_bookmarks); try { // Find the root element XmlUtils.beginDocument(parser, TAG_BOOKMARKS); while (true) { XmlUtils.nextElement(parser); String element = parser.getName(); if (element == null) { break; } if (TAG_BOOKMARK.equals(element)) { CharSequence name = null; CharSequence directory = null; try { name = getString(parser.getAttributeResourceValue( R.styleable.Bookmark_name, 0)); } catch (Exception e) { /** NON BLOCK **/ } try { directory = getString(parser .getAttributeResourceValue( R.styleable.Bookmark_directory, 0)); } catch (Exception e) { /** NON BLOCK **/ } if (directory == null) { directory = parser .getAttributeValue(R.styleable.Bookmark_directory); } if (name != null && directory != null) { bookmarks.add(new Bookmark( BOOKMARK_TYPE.FILESYSTEM, name.toString(), directory.toString())); } } } // Return the bookmarks return bookmarks; } finally { parser.close(); } } catch (Throwable ex) { Log.e(TAG, "Load filesystem bookmarks failed", ex); //$NON-NLS-1$ } // No data return new ArrayList(); } /** * Method that loads the secure digital card storage bookmarks from the * system. * * @return List The bookmarks loaded */ private List loadSdStorageBookmarks() { // Initialize the bookmarks List bookmarks = new ArrayList(); try { // Recovery sdcards from storage manager StorageVolume[] volumes = StorageHelper .getStorageVolumes(getApplication(), true); for (StorageVolume volume: volumes) { if (volume != null) { String mountedState = volume.getState(); String path = volume.getPath(); if (!Environment.MEDIA_MOUNTED.equalsIgnoreCase(mountedState) && !Environment.MEDIA_MOUNTED_READ_ONLY.equalsIgnoreCase(mountedState)) { Log.w(TAG, "Ignoring '" + path + "' with state of '"+ mountedState + "'"); continue; } if (!TextUtils.isEmpty(path)) { String lowerPath = path.toLowerCase(Locale.ROOT); Bookmark bookmark; if (lowerPath.contains(STR_USB)) { bookmark = new Bookmark(BOOKMARK_TYPE.USB, StorageHelper .getStorageVolumeDescription(getApplication(), volume), path); } else { bookmark = new Bookmark(BOOKMARK_TYPE.SDCARD, StorageHelper .getStorageVolumeDescription(getApplication(), volume), path); } bookmarks.add(bookmark); } } } // Return the bookmarks return bookmarks; } catch (Throwable ex) { Log.e(TAG, "Load filesystem bookmarks failed", ex); //$NON-NLS-1$ } // No data return new ArrayList(); } /** * Method that loads all virtual mount points. * * @return List The bookmarks loaded */ private List loadVirtualBookmarks() { // Initialize the bookmarks List bookmarks = new ArrayList(); List mps = VirtualMountPointConsole.getVirtualMountPoints(); for (MountPoint mp : mps) { BOOKMARK_TYPE type = null; String name = null; if (mp.isSecure()) { type = BOOKMARK_TYPE.SECURE; name = getString(R.string.bookmarks_secure); } else if (mp.isRemote()) { type = BOOKMARK_TYPE.REMOTE; name = getString(R.string.bookmarks_remote); } else { continue; } bookmarks.add(new Bookmark(type, name, mp.getMountPoint())); } return bookmarks; } /** * Method that loads the user bookmarks (added by the user). * * @return List The bookmarks loaded */ private List loadUserBookmarks() { List bookmarks = new ArrayList(); Cursor cursor = Bookmarks.getAllBookmarks(this.getContentResolver()); try { if (cursor != null && cursor.moveToFirst()) { do { Bookmark bm = new Bookmark(cursor); if (this.mChRooted && !StorageHelper.isPathInStorageVolume(bm.mPath)) { continue; } bookmarks.add(bm); } while (cursor.moveToNext()); } } finally { try { if (cursor != null) { cursor.close(); } } catch (Exception e) { /** NON BLOCK **/ } } // Remove bookmarks from virtual storage if the filesystem is not mount int c = bookmarks.size() - 1; for (int i = c; i >= 0; i--) { VirtualMountPointConsole vc = VirtualMountPointConsole.getVirtualConsoleForPath(bookmarks.get(i).mPath); if (vc != null && !vc.isMounted()) { bookmarks.remove(i); } } return bookmarks; } /** * Method that initializes the navigation views of the activity */ private void initNavigationViews() { //Get the navigation views (wishlist: multiple view; for now only one view) this.mNavigationViews = new NavigationView[1]; this.mCurrentNavigationView = 0; //- 0 this.mNavigationViews[0] = (NavigationView)findViewById(R.id.navigation_view); this.mNavigationViews[0].setId(0); this.mEasyModeListView = (ListView) findViewById(R.id.lv_easy_mode); mEasyModeAdapter = new ArrayAdapter(this, R.layout .navigation_view_simple_item) { @Override public View getView(int position, View convertView, ViewGroup parent) { convertView = (convertView == null) ?getLayoutInflater().inflate(R.layout .navigation_view_simple_item, parent, false) : convertView; MimeTypeCategory item = getItem(position); String typeTitle = MIME_TYPE_LOCALIZED_NAMES[item.ordinal()]; TextView typeTitleTV = (TextView) convertView .findViewById(R.id.navigation_view_item_name); ImageView typeIconIV = (ImageView) convertView .findViewById(R.id.navigation_view_item_icon); View checkBoxView = convertView.findViewById(R.id.navigation_view_item_check); checkBoxView.setVisibility(View.GONE); typeTitleTV.setText(typeTitle); typeIconIV.setImageDrawable(EASY_MODE_ICONS.get(item)); convertView.setOnClickListener(mEasyModeItemClickListener); convertView.setTag(position); return convertView; } }; mEasyModeAdapter.addAll(EASY_MODE_LIST); mEasyModeListView.setAdapter(mEasyModeAdapter); } private void onClicked(int position) { Intent intent = new Intent(this, SearchActivity.class); intent.setAction(Intent.ACTION_SEARCH); intent.putExtra(SearchActivity.EXTRA_SEARCH_DIRECTORY, getCurrentNavigationView().getCurrentDir()); intent.putExtra(SearchManager.QUERY, "*"); // Use wild-card '*' if (position == 0) { // the user has selected all items, they want to see their folders so let's do that. performHideEasyMode(); performShowBackArrow(true); return; } else { ArrayList searchCategories = new ArrayList(); MimeTypeCategory selectedCategory = EASY_MODE_LIST.get(position); searchCategories.add(selectedCategory); // a one off case where we implicitly want to also search for TEXT mimetypes when the // DOCUMENTS category is selected if (selectedCategory == MimeTypeCategory.DOCUMENT) { searchCategories.add(MimeTypeCategory.TEXT); } intent.putExtra(SearchActivity.EXTRA_SEARCH_MIMETYPE, searchCategories); } startActivity(intent); } /** * Method that initialize the console * @hide */ void initConsole() { //Create the default console (from the preferences) try { Console console = ConsoleBuilder.getConsole(NavigationActivity.this); if (console == null) { throw new ConsoleAllocException("console == null"); //$NON-NLS-1$ } } catch (Throwable ex) { if (!NavigationActivity.this.mChRooted) { //Show exception and exit Log.e(TAG, getString(R.string.msgs_cant_create_console), ex); // We don't have any console // Show exception and exit DialogHelper.showToast( NavigationActivity.this, R.string.msgs_cant_create_console, Toast.LENGTH_LONG); exit(); return; } // We are in a trouble (something is not allowing creating the console) // Ask the user to return to prompt or root access mode mode with a // non-privileged console, prior to make crash the application askOrExit(); return; } } /** * Method that initializes the navigation. * * @param viewId The navigation view identifier where apply the navigation * @param restore Initialize from a restore info * @param intent The current intent * @hide */ void initNavigation(final int viewId, final boolean restore, final Intent intent) { if (mDisplayingSearchResults || restore) { return; } final NavigationView navigationView = getNavigationView(viewId); this.mHandler.post(new Runnable() { @Override public void run() { //Is necessary navigate? applyInitialDir(navigationView, intent); } }); } /** * Method that applies the user-defined initial directory * * @param navigationView The navigation view * @param intent The current intent * @hide */ void applyInitialDir(final NavigationView navigationView, final Intent intent) { //Load the user-defined initial directory String initialDir = Preferences.getSharedPreferences().getString( FileManagerSettings.SETTINGS_INITIAL_DIR.getId(), (String)FileManagerSettings. SETTINGS_INITIAL_DIR.getDefaultValue()); // Check if request navigation to directory (use as default), and // ensure chrooted and absolute path String navigateTo = intent.getStringExtra(EXTRA_NAVIGATE_TO); String intentAction = intent.getAction(); if (navigateTo != null && navigateTo.length() > 0) { initialDir = navigateTo; } else if (intentAction != null && intentAction.equals(Intent.ACTION_VIEW)) { Uri data = intent.getData(); if (data != null && (FileHelper.FILE_URI_SCHEME.equals(data.getScheme()) || FileHelper.FOLDER_URI_SCHEME.equals(data.getScheme()) || FileHelper.DIRECTORY_URI_SCHEME.equals(data.getScheme()))) { File path = new File(data.getPath()); if (path.isDirectory()) { initialDir = path.getAbsolutePath(); } } } // Add to history final boolean addToHistory = intent.getBooleanExtra(EXTRA_ADD_TO_HISTORY, true); // We cannot navigate to a secure console if it is unmounted. So go to root in that case VirtualConsole vc = VirtualMountPointConsole.getVirtualConsoleForPath(initialDir); if (vc != null && vc instanceof SecureConsole && !((SecureConsole) vc).isMounted()) { initialDir = FileHelper.ROOT_DIRECTORY; } if (this.mChRooted) { // Initial directory is the first external sdcard (sdcard, emmc, usb, ...) if (!StorageHelper.isPathInStorageVolume(initialDir)) { StorageVolume[] volumes = StorageHelper.getStorageVolumes(this, false); if (volumes != null && volumes.length > 0) { initialDir = volumes[0].getPath(); int count = volumes.length; for (int i = 0; i < count; i++) { StorageVolume volume = volumes[i]; if (Environment.MEDIA_MOUNTED.equalsIgnoreCase(volume.getState())) { initialDir = volume.getPath(); break; } } //Ensure that initial directory is an absolute directory initialDir = FileHelper.getAbsPath(initialDir); } else { // Show exception and exit DialogHelper.showToast( this, R.string.msgs_cant_create_console, Toast.LENGTH_LONG); exit(); return; } } } else { //Ensure that initial directory is an absolute directory final String userInitialDir = initialDir; initialDir = FileHelper.getAbsPath(initialDir); final String absInitialDir = initialDir; File f = new File(initialDir); boolean exists = f.exists(); if (!exists) { // Fix for /data/media/0. Libcore doesn't detect it correctly. try { exists = CommandHelper.getFileInfo(this, initialDir, false, null) != null; } catch (InsufficientPermissionsException ipex) { ExceptionUtil.translateException( this, ipex, false, true, new OnRelaunchCommandResult() { @Override public void onSuccess() { navigationView.changeCurrentDir(absInitialDir, addToHistory); } @Override public void onFailed(Throwable cause) { showInitialInvalidDirectoryMsg(userInitialDir); navigationView.changeCurrentDir(FileHelper.ROOT_DIRECTORY, addToHistory); } @Override public void onCancelled() { showInitialInvalidDirectoryMsg(userInitialDir); navigationView.changeCurrentDir(FileHelper.ROOT_DIRECTORY, addToHistory); } }); // Asynchronous mode return; } catch (Exception ex) { // We are not interested in other exceptions ExceptionUtil.translateException(this, ex, true, false); } // Check again the initial directory if (!exists) { showInitialInvalidDirectoryMsg(userInitialDir); initialDir = FileHelper.ROOT_DIRECTORY; } // Weird, but we have a valid initial directory } } boolean needsEasyMode = false; if (mSdBookmarks != null ) { for (Bookmark bookmark :mSdBookmarks) { if (bookmark.mPath.equalsIgnoreCase(initialDir)) { needsEasyMode = true; break; } } } mNeedsEasyMode = getResources().getBoolean(R.bool.cmcc_show_easy_mode); needsEasyMode = needsEasyMode && mNeedsEasyMode; if (needsEasyMode) { performShowEasyMode(); } else { performHideEasyMode(); } // Change the current directory to the user-defined initial directory navigationView.changeCurrentDir(initialDir, addToHistory); } /** * Displays a message reporting invalid directory * * @param initialDir The initial directory * @hide */ void showInitialInvalidDirectoryMsg(String initialDir) { // Change to root directory DialogHelper.showToast( this, getString( R.string.msgs_settings_invalid_initial_directory, initialDir), Toast.LENGTH_SHORT); } /** * Method that verifies the intent passed to the activity, and checks * if a request is made like Search. * * @param intent The intent to check * @hide */ void checkIntent(Intent intent) { //Search action if (Intent.ACTION_SEARCH.equals(intent.getAction())) { Intent searchIntent = new Intent(this, SearchActivity.class); searchIntent.setAction(Intent.ACTION_SEARCH); //- SearchActivity.EXTRA_SEARCH_DIRECTORY searchIntent.putExtra( SearchActivity.EXTRA_SEARCH_DIRECTORY, getCurrentNavigationView().getCurrentDir()); //- SearchManager.APP_DATA if (intent.getBundleExtra(SearchManager.APP_DATA) != null) { Bundle bundle = new Bundle(); bundle.putAll(intent.getBundleExtra(SearchManager.APP_DATA)); searchIntent.putExtra(SearchManager.APP_DATA, bundle); } //-- SearchManager.QUERY String query = intent.getStringExtra(SearchManager.QUERY); if (query != null) { searchIntent.putExtra(SearchManager.QUERY, query); } //- android.speech.RecognizerIntent.EXTRA_RESULTS ArrayList extraResults = intent.getStringArrayListExtra(android.speech.RecognizerIntent.EXTRA_RESULTS); if (extraResults != null) { searchIntent.putStringArrayListExtra( android.speech.RecognizerIntent.EXTRA_RESULTS, extraResults); } startActivityForResult(searchIntent, INTENT_REQUEST_SEARCH); return; } } /** * {@inheritDoc} */ @Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_MENU) { if (mDrawerLayout != null) { if (mDrawerLayout.isDrawerOpen(mDrawer)) { mDrawerLayout.closeDrawer(Gravity.START); } else { mDrawerLayout.openDrawer(Gravity.START); } } return true; } return super.onKeyUp(keyCode, event); } @Override public void onBackPressed() { if (mDrawerLayout != null && mDrawerLayout.isDrawerOpen(Gravity.START)) { mDrawerLayout.closeDrawer(Gravity.START); return; } boolean upToParent = mHistory != null && mHistory.size() > 0; if (mNeedsEasyMode && !isEasyModeVisible() && !upToParent) { performShowEasyMode(); return; } else { if (checkBackAction()) { return; } } // An exit event has occurred, force the destroy the consoles exit(); } /** * Method invoked when an action item is clicked. * * @param view The button pushed */ public void onActionBarItemClick(View view) { switch (view.getId()) { //###################### //Navigation Custom Title //###################### case R.id.ab_configuration: //Show navigation view configuration toolbar getCurrentNavigationView().getCustomTitle().showConfigurationView(); break; case R.id.ab_close: //Hide navigation view configuration toolbar getCurrentNavigationView().getCustomTitle().hideConfigurationView(); break; //###################### //Breadcrumb Actions //###################### case R.id.ab_filesystem_info: //Show information of the filesystem MountPoint mp = getCurrentNavigationView().getBreadcrumb().getMountPointInfo(); DiskUsage du = getCurrentNavigationView().getBreadcrumb().getDiskUsageInfo(); showMountPointInfo(mp, du); break; //###################### //Navigation view options //###################### case R.id.ab_sort_mode: showSettingsPopUp(view, Arrays.asList( new FileManagerSettings[]{ FileManagerSettings.SETTINGS_SORT_MODE})); break; case R.id.ab_layout_mode: showSettingsPopUp(view, Arrays.asList( new FileManagerSettings[]{ FileManagerSettings.SETTINGS_LAYOUT_MODE})); break; case R.id.ab_view_options: // If we are in ChRooted mode, then don't show non-secure items if (this.mChRooted) { showSettingsPopUp(view, Arrays.asList(new FileManagerSettings[]{ FileManagerSettings.SETTINGS_SHOW_DIRS_FIRST})); } else { showSettingsPopUp(view, Arrays.asList(new FileManagerSettings[]{ FileManagerSettings.SETTINGS_SHOW_DIRS_FIRST, FileManagerSettings.SETTINGS_SHOW_HIDDEN, FileManagerSettings.SETTINGS_SHOW_SYSTEM, FileManagerSettings.SETTINGS_SHOW_SYMLINKS})); } break; //###################### //Selection Actions //###################### case R.id.ab_selection_done: //Show information of the filesystem getCurrentNavigationView().onDeselectAll(); break; //###################### //Action Bar buttons //###################### case R.id.ab_actions: openActionsDialog(getCurrentNavigationView().getCurrentDir(), true); break; case R.id.ab_search: openSearch(); break; default: break; } } /** * {@inheritDoc} */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == INTENT_REQUEST_SETTINGS) { // reset bookmarks list to default as the user could changed the // root mode which changes the system bookmarks initBookmarks(); return; } if (data != null) { switch (requestCode) { case INTENT_REQUEST_SEARCH: if (resultCode == RESULT_OK) { //Change directory? Bundle bundle = data.getExtras(); if (bundle != null) { FileSystemObject fso = (FileSystemObject) bundle.getSerializable( EXTRA_SEARCH_ENTRY_SELECTION); SearchInfoParcelable searchInfo = bundle.getParcelable(EXTRA_SEARCH_LAST_SEARCH_DATA); if (fso != null) { //Goto to new directory getCurrentNavigationView().open(fso, searchInfo); performHideEasyMode(); mDisplayingSearchResults = true; } } } else if (resultCode == RESULT_CANCELED) { SearchInfoParcelable searchInfo = data.getParcelableExtra(EXTRA_SEARCH_LAST_SEARCH_DATA); if (searchInfo != null && searchInfo.isSuccessNavigation()) { //Navigate to previous history back(); } else { // I don't know is the search view was changed, so try to do a refresh // of the navigation view getCurrentNavigationView().refresh(true); } } // reset bookmarks list to default as the user could have set a // new bookmark in the search activity initBookmarks(); break; default: break; } } } /** * {@inheritDoc} */ @Override public void onNewHistory(HistoryNavigable navigable) { addHistoryToDrawer(this.mHistory.size(), navigable); //Recollect information about current status History history = new History(this.mHistory.size(), navigable); this.mHistory.add(history); } /** * {@inheritDoc} */ @Override public void onCheckHistory() { } /** * {@inheritDoc} */ @Override public void onRequestRefresh(Object o, boolean clearSelection) { if (o instanceof FileSystemObject) { // Refresh only the item this.getCurrentNavigationView().refresh((FileSystemObject)o); } else if (o == null) { // Refresh all getCurrentNavigationView().refresh(); } if (clearSelection) { this.getCurrentNavigationView().onDeselectAll(); } } @Override public void onClearCache(Object o) { getCurrentNavigationView().onClearCache(o); } /** * {@inheritDoc} */ @Override public void onRequestBookmarksRefresh() { initBookmarks(); } /** * {@inheritDoc} */ @Override public void onRequestRemove(Object o, boolean clearSelection) { if (o instanceof FileSystemObject) { // Remove from view this.getCurrentNavigationView().removeItem((FileSystemObject)o); //Remove from history removeFromHistory((FileSystemObject)o); } else { onRequestRefresh(null, clearSelection); } if (clearSelection) { this.getCurrentNavigationView().onDeselectAll(); } } /** * {@inheritDoc} */ @Override public void onNavigateTo(Object o) { // Ignored } @Override public void onCancel(){ // nop } /** * {@inheritDoc} */ @Override public void onSelectionChanged(NavigationView navView, List selectedItems) { this.mSelectionBar.setSelection(selectedItems); } /** * {@inheritDoc} */ @Override public void onRequestMenu(NavigationView navView, FileSystemObject item) { // Show the actions dialog openActionsDialog(item, false); } /** * Method that shows a popup with a menu associated a {@link FileManagerSettings}. * * @param anchor The action button that was pressed * @param settings The array of settings associated with the action button */ private void showSettingsPopUp(View anchor, List settings) { //Create the adapter final MenuSettingsAdapter adapter = new MenuSettingsAdapter(this, settings); //Create a show the popup menu mPopupWindow = DialogHelper.createListPopupWindow(this, adapter, anchor); mPopupWindow.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View v, int position, long id) { FileManagerSettings setting = ((MenuSettingsAdapter)parent.getAdapter()).getSetting(position); final int value = ((MenuSettingsAdapter)parent.getAdapter()).getId(position); mPopupWindow.dismiss(); mPopupWindow = null; try { if (setting.compareTo(FileManagerSettings.SETTINGS_LAYOUT_MODE) == 0) { //Need to change the layout getCurrentNavigationView().changeViewMode( NavigationLayoutMode.fromId(value)); } else { //Save and refresh if (setting.getDefaultValue() instanceof Enum) { //Enumeration Preferences.savePreference(setting, new ObjectIdentifier() { @Override public int getId() { return value; } }, false); } else { //Boolean boolean newval = Preferences.getSharedPreferences(). getBoolean( setting.getId(), ((Boolean)setting.getDefaultValue()).booleanValue()); Preferences.savePreference(setting, Boolean.valueOf(!newval), false); } getCurrentNavigationView().refresh(); } } catch (Exception e) { Log.e(TAG, "Error applying navigation option", e); //$NON-NLS-1$ NavigationActivity.this.mHandler.post(new Runnable() { @Override public void run() { DialogHelper.showToast( NavigationActivity.this, R.string.msgs_settings_save_failure, Toast.LENGTH_SHORT); } }); } finally { adapter.dispose(); getCurrentNavigationView().getCustomTitle().restoreView(); } } }); mPopupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() { @Override public void onDismiss() { adapter.dispose(); } }); mPopupWindow.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED); mPopupWindow.show(); } /** * Method that show the information of a filesystem mount point. * * @param mp The mount point info * @param du The disk usage of the mount point */ private void showMountPointInfo(MountPoint mp, DiskUsage du) { //Has mount point info? if (mp == null) { //There is no information AlertDialog alert = DialogHelper.createWarningDialog( this, R.string.filesystem_info_warning_title, R.string.filesystem_info_warning_msg); DialogHelper.delegateDialogShow(this, alert); return; } //Show a the filesystem info dialog FilesystemInfoDialog dialog = new FilesystemInfoDialog(this, mp, du); dialog.setOnMountListener(new OnMountListener() { @Override public void onRemount(MountPoint mountPoint) { //Update the statistics of breadcrumb, only if mount point is the same Breadcrumb breadcrumb = getCurrentNavigationView().getBreadcrumb(); if (breadcrumb.getMountPointInfo().compareTo(mountPoint) == 0) { breadcrumb.updateMountPointInfo(); } if (mountPoint.isSecure()) { // Secure mountpoints only can be unmount, so we need to move the navigation // to a secure storage (do not add to history) Intent intent = new Intent(); intent.putExtra(EXTRA_ADD_TO_HISTORY, false); initNavigation(NavigationActivity.this.mCurrentNavigationView, false, intent); } } }); mOnConfigChangeListener = dialog.getOnConfigChangeListener(); dialog.setOnDismissListener(new DialogInterface.OnDismissListener() { @Override public void onDismiss(DialogInterface dialog) { mOnConfigChangeListener = null; } }); dialog.show(); } /** * Method that checks the action that must be realized when the * back button is pushed. * * @return boolean Indicates if the action must be intercepted */ private boolean checkBackAction() { // We need a basic structure to check this if (getCurrentNavigationView() == null) return false; if (mSearchView.getVisibility() == View.VISIBLE) { closeSearch(); } //Check if the configuration view is showing. In this case back //action must be "close configuration" if (getCurrentNavigationView().getCustomTitle().isConfigurationViewShowing()) { getCurrentNavigationView().getCustomTitle().restoreView(); return true; } //Do back operation over the navigation history boolean flag = this.mExitFlag; this.mExitFlag = !back(); // Retrieve if the exit status timeout has expired long now = System.currentTimeMillis(); boolean timeout = (this.mExitBackTimeout == -1 || (now - this.mExitBackTimeout) > RELEASE_EXIT_CHECK_TIMEOUT); //Check if there no history and if the user was advised in the last back action if (this.mExitFlag && (this.mExitFlag != flag || timeout)) { //Communicate the user that the next time the application will be closed this.mExitBackTimeout = System.currentTimeMillis(); DialogHelper.showToast(this, R.string.msgs_push_again_to_exit, Toast.LENGTH_SHORT); if (mNeedsEasyMode) { return isEasyModeVisible(); } else { return true; } } //Back action not applied return !this.mExitFlag; } @Override public void startActivity(Intent intent) { // check if search intent if (Intent.ACTION_SEARCH.equals(intent.getAction())) { intent.putExtra(SearchActivity.EXTRA_SEARCH_DIRECTORY, getCurrentNavigationView().getCurrentDir()); } super.startActivity(intent); } /** * Method that returns the history size. */ private void clearHistory() { this.mHistory.clear(); mDrawerHistory.removeAllViews(); mDrawerHistoryEmpty.setVisibility(View.VISIBLE); } /** * Method that navigates to the passed history reference. * * @param history The history reference * @return boolean A problem occurs while navigate */ public synchronized boolean navigateToHistory(History history) { try { //Gets the history History realHistory = this.mHistory.get(history.getPosition()); //Navigate to item. Check what kind of history is if (realHistory.getItem() instanceof NavigationViewInfoParcelable) { //Navigation NavigationViewInfoParcelable info = (NavigationViewInfoParcelable)realHistory.getItem(); int viewId = info.getId(); NavigationView view = getNavigationView(viewId); // Selected items must not be restored from on history navigation info.setSelectedFiles(view.getSelectedFiles()); if (!view.onRestoreState(info)) { return true; } } else if (realHistory.getItem() instanceof SearchInfoParcelable) { //Search (open search with the search results) SearchInfoParcelable info = (SearchInfoParcelable)realHistory.getItem(); Intent searchIntent = new Intent(this, SearchActivity.class); searchIntent.setAction(SearchActivity.ACTION_RESTORE); searchIntent.putExtra(SearchActivity.EXTRA_SEARCH_RESTORE, (Parcelable)info); startActivityForResult(searchIntent, INTENT_REQUEST_SEARCH); } else { //The type is unknown throw new IllegalArgumentException("Unknown history type"); //$NON-NLS-1$ } //Remove the old history int cc = realHistory.getPosition(); for (int i = this.mHistory.size() - 1; i >= cc; i--) { this.mHistory.remove(i); mDrawerHistory.removeViewAt(0); } if (mDrawerHistory.getChildCount() == 0) { mDrawerHistoryEmpty.setVisibility(View.VISIBLE); } //Navigate boolean clearHistory = mHistoryTab.isSelected() && mHistory.size() > 0; mClearHistory.setVisibility(clearHistory ? View.VISIBLE : View.GONE); return true; } catch (Throwable ex) { if (history != null) { Log.e(TAG, String.format("Failed to navigate to history %d: %s", //$NON-NLS-1$ Integer.valueOf(history.getPosition()), history.getItem().getTitle()), ex); } else { Log.e(TAG, String.format("Failed to navigate to history: null", ex)); //$NON-NLS-1$ } this.mHandler.post(new Runnable() { @Override public void run() { DialogHelper.showToast( NavigationActivity.this, R.string.msgs_history_unknown, Toast.LENGTH_LONG); } }); //Not change directory return false; } } /** * Method that request a back action over the navigation history. * * @return boolean If a back action was applied */ public boolean back() { // Check that has valid history while (this.mHistory.size() > 0) { History h = this.mHistory.get(this.mHistory.size() - 1); if (h.getItem() instanceof NavigationViewInfoParcelable) { // Verify that the path exists String path = ((NavigationViewInfoParcelable)h.getItem()).getCurrentDir(); try { FileSystemObject info = CommandHelper.getFileInfo(this, path, null); if (info != null) { break; } this.mHistory.remove(this.mHistory.size() - 1); } catch (Exception e) { ExceptionUtil.translateException(this, e, true, false); this.mHistory.remove(this.mHistory.size() - 1); } } else { break; } } //Navigate to history if (this.mHistory.size() > 0) { return navigateToHistory(this.mHistory.get(this.mHistory.size() - 1)); } //Nothing to apply mClearHistory.setVisibility(View.GONE); return false; } private void openActionsDialog(String path, boolean global) { FileSystemObject fso = null; try { fso = CommandHelper.getFileInfo(this, path, false, null); if (fso == null) { throw new NoSuchFileOrDirectory(path); } openActionsDialog(fso, global); } catch (Exception e) { // Notify the user ExceptionUtil.translateException(this, e); // Remove the object if (e instanceof FileNotFoundException || e instanceof NoSuchFileOrDirectory) { // If have a FileSystemObject reference then there is no need to search // the path (less resources used) getCurrentNavigationView().removeItem(path); } return; } } /** * Method that opens the actions dialog * * @param item The path or the {@link FileSystemObject} * @param global If the menu to display is the one with global actions */ private void openActionsDialog(FileSystemObject item, boolean global) { // We used to refresh the item reference here, but the access to the SecureConsole is synchronized, // which can/will cause on ANR in certain scenarios. We don't care if it doesn't exist anymore really // For this to work, SecureConsole NEEDS to be refactored. // Show the dialog ActionsDialog dialog = new ActionsDialog(this, this, item, global, false); dialog.setOnRequestRefreshListener(this); dialog.setOnSelectionListener(getCurrentNavigationView()); dialog.show(); } /** * Method that opens the search view. * * @hide */ void openSearch() { mSearchView.setVisibility(View.VISIBLE); mSearchView.onActionViewExpanded(); mCustomTitleView.setVisibility(View.GONE); } void closeSearch() { mSearchView.setVisibility(View.GONE); mSearchView.onActionViewCollapsed(); mCustomTitleView.setVisibility(View.VISIBLE); } /** * Method that opens the settings activity. * * @hide */ void openSettings() { Intent settingsIntent = new Intent(NavigationActivity.this, SettingsPreferences.class); startActivityForResult(settingsIntent, INTENT_REQUEST_SETTINGS); } /** * Method that remove the {@link FileSystemObject} from the history */ private void removeFromHistory(FileSystemObject fso) { if (this.mHistory != null) { int cc = this.mHistory.size() - 1; for (int i = cc; i >= 0 ; i--) { History history = this.mHistory.get(i); if (history.getItem() instanceof NavigationViewInfoParcelable) { String p0 = fso.getFullPath(); String p1 = ((NavigationViewInfoParcelable) history.getItem()).getCurrentDir(); if (p0.compareTo(p1) == 0) { this.mHistory.remove(i); mDrawerHistory.removeViewAt(mDrawerHistory.getChildCount() - i - 1); mDrawerHistoryEmpty.setVisibility( mDrawerHistory.getChildCount() == 0 ? View.VISIBLE : View.GONE); updateHistoryPositions(); } } } } } /** * Update the history positions after one of the history is removed from drawer */ private void updateHistoryPositions() { int cc = this.mHistory.size() - 1; for (int i = 0; i <= cc ; i++) { History history = this.mHistory.get(i); history.setPosition(i + 1); } } /** * Method that ask the user to change the access mode prior to crash. * @hide */ void askOrExit() { //Show a dialog asking the user AlertDialog dialog = DialogHelper.createYesNoDialog( this, R.string.msgs_change_to_prompt_access_mode_title, R.string.msgs_change_to_prompt_access_mode_msg, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface alertDialog, int which) { if (which == DialogInterface.BUTTON_NEGATIVE) { // We don't have any console // Show exception and exit DialogHelper.showToast( NavigationActivity.this, R.string.msgs_cant_create_console, Toast.LENGTH_LONG); exit(); return; } // Ok. Now try to change to prompt mode. Any crash // here is a fatal error. We won't have any console to operate. try { // Change console ConsoleBuilder.changeToNonPrivilegedConsole(NavigationActivity.this); // Save preferences Preferences.savePreference( FileManagerSettings.SETTINGS_ACCESS_MODE, AccessMode.PROMPT, true); } catch (Exception e) { // Displays an exception and exit Log.e(TAG, getString(R.string.msgs_cant_create_console), e); DialogHelper.showToast( NavigationActivity.this, R.string.msgs_cant_create_console, Toast.LENGTH_LONG); exit(); } } }); DialogHelper.delegateDialogShow(this, dialog); } /** * Method that creates a ChRooted environment, protecting the user to break anything in * the device * @hide */ void createChRooted() { // If we are in a ChRooted mode, then do nothing if (this.mChRooted) return; this.mChRooted = true; int cc = this.mNavigationViews.length; for (int i = 0; i < cc; i++) { this.mNavigationViews[i].createChRooted(); } // Remove the selection cc = this.mNavigationViews.length; for (int i = 0; i < cc; i++) { getCurrentNavigationView().onDeselectAll(); } // Remove the history (don't allow to access to previous data) clearHistory(); } /** * Method that exits from a ChRooted * @hide */ void exitChRooted() { // If we aren't in a ChRooted mode, then do nothing if (!this.mChRooted) return; this.mChRooted = false; int cc = this.mNavigationViews.length; for (int i = 0; i < cc; i++) { this.mNavigationViews[i].exitChRooted(); } } /** * Method called when a controlled exit is required * @hide */ void exit() { finish(); } private void recycle() { // Recycle the navigation views if (mNavigationViews != null) { int cc = this.mNavigationViews.length; for (int i = 0; i < cc; i++) { this.mNavigationViews[i].recycle(); } } try { FileManagerApplication.destroyBackgroundConsole(); } catch (Throwable ex) { /**NON BLOCK**/ } try { ConsoleBuilder.destroyConsole(); } catch (Throwable ex) { /**NON BLOCK**/ } } /** * Method that reconfigures the layout for better fit in portrait and landscape modes */ private void onLayoutChanged() { Theme theme = ThemeManager.getCurrentTheme(this); boolean drawerOpen = mDrawerLayout.isDrawerOpen(Gravity.START); // Apply only when the orientation was changed int orientation = getResources().getConfiguration().orientation; if (this.mOrientation == orientation) return; this.mOrientation = orientation; // imitate a closed drawer while layout is rebuilt to avoid NullPointerException if (drawerOpen) { mDrawerLayout.closeDrawer(Gravity.START); } if (this.mOrientation == Configuration.ORIENTATION_LANDSCAPE) { // Landscape mode ViewGroup statusBar = (ViewGroup)findViewById(R.id.navigation_statusbar); if (statusBar.getParent() != null) { ViewGroup parent = (ViewGroup) statusBar.getParent(); parent.removeView(statusBar); } // Calculate the action button size (all the buttons must fit in the title bar) int bw = (int)getResources().getDimension(R.dimen.default_buttom_width); int abw = this.mActionBar.getChildCount() * bw; int rbw = 0; int cc = statusBar.getChildCount(); for (int i = 0; i < cc; i++) { View child = statusBar.getChildAt(i); if (child instanceof ButtonItem) { rbw += bw; } } // Currently there isn't overflow menu int w = abw + rbw - bw; // Add to the new location ViewGroup newParent = (ViewGroup)findViewById(R.id.navigation_title_landscape_holder); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( w, ViewGroup.LayoutParams.MATCH_PARENT); statusBar.setLayoutParams(params); newParent.addView(statusBar); // Apply theme theme.setBackgroundDrawable(this, statusBar, "titlebar_drawable"); //$NON-NLS-1$ // Hide holder View holder = findViewById(R.id.navigation_statusbar_portrait_holder); holder.setVisibility(View.GONE); } else { // Portrait mode ViewGroup statusBar = (ViewGroup)findViewById(R.id.navigation_statusbar); if (statusBar.getParent() != null) { ViewGroup parent = (ViewGroup) statusBar.getParent(); parent.removeView(statusBar); } // Add to the new location ViewGroup newParent = (ViewGroup)findViewById( R.id.navigation_statusbar_portrait_holder); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); statusBar.setLayoutParams(params); newParent.addView(statusBar); // Apply theme theme.setBackgroundDrawable(this, statusBar, "statusbar_drawable"); //$NON-NLS-1$ // Show holder newParent.setVisibility(View.VISIBLE); } // if drawer was open, imitate reopening if (drawerOpen) { mDrawerToggle.onDrawerOpened(mDrawer); } } /** * Method that removes all the history items that refers to virtual unmounted filesystems */ private void removeUnmountedHistory() { int cc = mHistory.size() - 1; for (int i = cc; i >= 0; i--) { History history = mHistory.get(i); if (history.getItem() instanceof NavigationViewInfoParcelable) { NavigationViewInfoParcelable navigableInfo = ((NavigationViewInfoParcelable) history.getItem()); VirtualMountPointConsole vc = VirtualMountPointConsole.getVirtualConsoleForPath( navigableInfo.getCurrentDir()); if (vc != null && !vc.isMounted()) { mHistory.remove(i); mDrawerHistory.removeViewAt(mDrawerHistory.getChildCount() - i - 1); } } } mDrawerHistoryEmpty.setVisibility( mDrawerHistory.getChildCount() == 0 ? View.VISIBLE : View.GONE); updateHistoryPositions(); } /** * Method that removes all the selection items that refers to virtual unmounted filesystems */ private void removeUnmountedSelection() { for (NavigationView view : mNavigationViews) { view.removeUnmountedSelection(); } mSelectionBar.setSelection(getNavigationView(mCurrentNavigationView).getSelectedFiles()); } /** * Method that applies the current theme to the activity * @hide */ void applyTheme() { int orientation = getResources().getConfiguration().orientation; Theme theme = ThemeManager.getCurrentTheme(this); theme.setBaseThemeNoActionBar(this); applyTabTheme(); // imitate a closed drawer while layout is rebuilt to avoid NullPointerException boolean drawerOpen = mDrawerLayout.isDrawerOpen(Gravity.START); if (drawerOpen) { mDrawerLayout.closeDrawer(Gravity.START); } //- Layout View v = findViewById(R.id.navigation_layout); theme.setBackgroundDrawable(this, v, "background_drawable"); //$NON-NLS-1$ //- ActionBar theme.setTitlebarDrawable(this, getActionBar(), "titlebar_drawable"); //$NON-NLS-1$ // Hackery to theme search view mSearchView = (SearchView) findViewById(R.id.navigation_search_bar); int searchPlateId = mSearchView.getContext().getResources() .getIdentifier("android:id/search_plate", null, null); View searchPlate = mSearchView.findViewById(searchPlateId); if (searchPlate != null) { int searchTextId = searchPlate.getContext().getResources() .getIdentifier("android:id/search_src_text", null, null); TextView searchText = (TextView) searchPlate.findViewById(searchTextId); if (searchText != null) { searchText.setTextColor(Color.WHITE); searchText.setHintTextColor(Color.WHITE); } int magId = getResources().getIdentifier("android:id/search_mag_icon", null, null); ImageView magImage = (ImageView) mSearchView.findViewById(magId); if (magImage != null) { magImage.setLayoutParams(new LinearLayout.LayoutParams(0, 0)); } } SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); mSearchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName())); mSearchView.setIconifiedByDefault(false); mCustomTitleView = (NavigationCustomTitleView) findViewById(R.id.navigation_title_flipper); mCustomTitleView.setVisibility(View.VISIBLE); //- StatusBar v = findViewById(R.id.navigation_statusbar); if (orientation == Configuration.ORIENTATION_LANDSCAPE) { theme.setBackgroundDrawable(this, v, "titlebar_drawable"); //$NON-NLS-1$ } else { theme.setBackgroundDrawable(this, v, "statusbar_drawable"); //$NON-NLS-1$ } v = findViewById(R.id.ab_overflow); theme.setImageDrawable(this, (ImageView)v, "ab_overflow_drawable"); //$NON-NLS-1$ v = findViewById(R.id.ab_actions); theme.setImageDrawable(this, (ImageView)v, "ab_actions_drawable"); //$NON-NLS-1$ v = findViewById(R.id.ab_search); theme.setImageDrawable(this, (ImageView)v, "ab_search_drawable"); //$NON-NLS-1$ //- Expanders v = findViewById(R.id.ab_configuration); theme.setImageDrawable(this, (ImageView)v, "expander_open_drawable"); //$NON-NLS-1$ v = findViewById(R.id.ab_close); theme.setImageDrawable(this, (ImageView)v, "expander_close_drawable"); //$NON-NLS-1$ v = findViewById(R.id.ab_sort_mode); theme.setImageDrawable(this, (ImageView)v, "ab_sort_mode_drawable"); //$NON-NLS-1$ v = findViewById(R.id.ab_layout_mode); theme.setImageDrawable(this, (ImageView)v, "ab_layout_mode_drawable"); //$NON-NLS-1$ v = findViewById(R.id.ab_view_options); theme.setImageDrawable(this, (ImageView)v, "ab_view_options_drawable"); //$NON-NLS-1$ //- SelectionBar v = findViewById(R.id.navigation_selectionbar); theme.setBackgroundDrawable(this, v, "selectionbar_drawable"); //$NON-NLS-1$ v = findViewById(R.id.ab_selection_done); theme.setImageDrawable(this, (ImageView)v, "ab_selection_done_drawable"); //$NON-NLS-1$ v = findViewById(R.id.navigation_status_selection_label); theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$ // - Navigation drawer v = findViewById(R.id.history_empty); theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$ for (int i=0; i