2 * Copyright (C) 2012 The CyanogenMod Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.cyanogenmod.filemanager.activities;
19 import android.app.Activity;
20 import android.app.AlertDialog;
21 import android.app.Dialog;
22 import android.app.SearchManager;
23 import android.content.BroadcastReceiver;
24 import android.content.ContentResolver;
25 import android.content.Context;
26 import android.content.DialogInterface;
27 import android.content.Intent;
28 import android.content.IntentFilter;
29 import android.content.res.Configuration;
30 import android.content.res.XmlResourceParser;
31 import android.database.Cursor;
32 import android.graphics.Color;
33 import android.graphics.drawable.Drawable;
34 import android.net.Uri;
35 import android.nfc.NfcAdapter;
36 import android.nfc.NfcEvent;
37 import android.os.AsyncTask;
38 import android.os.Bundle;
39 import android.os.Environment;
40 import android.os.Handler;
41 import android.os.Parcelable;
42 import android.os.storage.StorageVolume;
43 import android.support.v4.app.ActionBarDrawerToggle;
44 import android.support.v4.widget.DrawerLayout;
45 import android.text.TextUtils;
46 import android.util.Log;
47 import android.view.Gravity;
48 import android.view.KeyEvent;
49 import android.view.MenuItem;
50 import android.view.View;
51 import android.view.View.OnClickListener;
52 import android.view.ViewGroup;
53 import android.view.inputmethod.InputMethodManager;
54 import android.widget.AdapterView;
55 import android.widget.AdapterView.OnItemClickListener;
56 import android.widget.ImageButton;
57 import android.widget.ImageView;
58 import android.widget.LinearLayout;
59 import android.widget.ListPopupWindow;
60 import android.widget.ListView;
61 import android.widget.PopupWindow;
62 import android.widget.SearchView;
63 import android.widget.TextView;
64 import android.widget.Toast;
65 import android.widget.Toolbar;
66 import android.widget.ArrayAdapter;
68 import com.android.internal.util.XmlUtils;
69 import com.cyanogenmod.filemanager.FileManagerApplication;
70 import com.cyanogenmod.filemanager.R;
71 import com.cyanogenmod.filemanager.activities.preferences.SettingsPreferences;
72 import com.cyanogenmod.filemanager.adapters.MenuSettingsAdapter;
73 import com.cyanogenmod.filemanager.console.Console;
74 import com.cyanogenmod.filemanager.console.ConsoleAllocException;
75 import com.cyanogenmod.filemanager.console.ConsoleBuilder;
76 import com.cyanogenmod.filemanager.console.InsufficientPermissionsException;
77 import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory;
78 import com.cyanogenmod.filemanager.console.VirtualConsole;
79 import com.cyanogenmod.filemanager.console.VirtualMountPointConsole;
80 import com.cyanogenmod.filemanager.console.secure.SecureConsole;
81 import com.cyanogenmod.filemanager.listeners.OnHistoryListener;
82 import com.cyanogenmod.filemanager.listeners.OnRequestRefreshListener;
83 import com.cyanogenmod.filemanager.model.Bookmark;
84 import com.cyanogenmod.filemanager.model.DiskUsage;
85 import com.cyanogenmod.filemanager.model.FileSystemObject;
86 import com.cyanogenmod.filemanager.model.History;
87 import com.cyanogenmod.filemanager.model.MountPoint;
88 import com.cyanogenmod.filemanager.model.Bookmark.BOOKMARK_TYPE;
89 import com.cyanogenmod.filemanager.parcelables.HistoryNavigable;
90 import com.cyanogenmod.filemanager.parcelables.NavigationViewInfoParcelable;
91 import com.cyanogenmod.filemanager.parcelables.SearchInfoParcelable;
92 import com.cyanogenmod.filemanager.preferences.AccessMode;
93 import com.cyanogenmod.filemanager.preferences.Bookmarks;
94 import com.cyanogenmod.filemanager.preferences.FileManagerSettings;
95 import com.cyanogenmod.filemanager.preferences.NavigationLayoutMode;
96 import com.cyanogenmod.filemanager.preferences.ObjectIdentifier;
97 import com.cyanogenmod.filemanager.preferences.Preferences;
98 import com.cyanogenmod.filemanager.ui.IconHolder;
99 import com.cyanogenmod.filemanager.ui.ThemeManager;
100 import com.cyanogenmod.filemanager.ui.ThemeManager.Theme;
101 import com.cyanogenmod.filemanager.ui.dialogs.ActionsDialog;
102 import com.cyanogenmod.filemanager.ui.dialogs.FilesystemInfoDialog;
103 import com.cyanogenmod.filemanager.ui.dialogs.InitialDirectoryDialog;
104 import com.cyanogenmod.filemanager.ui.dialogs.FilesystemInfoDialog.OnMountListener;
105 import com.cyanogenmod.filemanager.ui.widgets.Breadcrumb;
106 import com.cyanogenmod.filemanager.ui.widgets.ButtonItem;
107 import com.cyanogenmod.filemanager.ui.widgets.NavigationCustomTitleView;
108 import com.cyanogenmod.filemanager.ui.widgets.NavigationView;
109 import com.cyanogenmod.filemanager.ui.widgets.NavigationView.OnNavigationRequestMenuListener;
110 import com.cyanogenmod.filemanager.ui.widgets.NavigationView.OnNavigationSelectionChangedListener;
111 import com.cyanogenmod.filemanager.ui.widgets.SelectionView;
112 import com.cyanogenmod.filemanager.util.AndroidHelper;
113 import com.cyanogenmod.filemanager.util.BookmarksHelper;
114 import com.cyanogenmod.filemanager.util.CommandHelper;
115 import com.cyanogenmod.filemanager.util.DialogHelper;
116 import com.cyanogenmod.filemanager.util.ExceptionUtil;
117 import com.cyanogenmod.filemanager.util.ExceptionUtil.OnRelaunchCommandResult;
118 import com.cyanogenmod.filemanager.util.FileHelper;
119 import com.cyanogenmod.filemanager.util.MimeTypeHelper.MimeTypeCategory;
120 import com.cyanogenmod.filemanager.util.StorageHelper;
123 import java.io.FileNotFoundException;
124 import java.util.ArrayList;
125 import java.util.Arrays;
126 import java.util.HashMap;
127 import java.util.List;
128 import java.util.Locale;
129 import java.util.Map;
131 import static com.cyanogenmod.filemanager.util.MimeTypeHelper.MimeTypeCategory.*;
134 * The main navigation activity. This activity is the center of the application.
135 * From this the user can navigate, search, make actions.<br/>
136 * This activity is singleTop, so when it is displayed no other activities exists in
138 * This cause an issue with the saved instance of this class, because if another activity
139 * is displayed, and the process is killed, NavigationActivity is started and the saved
140 * instance gets corrupted.<br/>
141 * For this reason the methods {link {@link Activity#onSaveInstanceState(Bundle)} and
142 * {@link Activity#onRestoreInstanceState(Bundle)} are not implemented, and every time
143 * the app is killed, is restarted from his initial state.
145 public class NavigationActivity extends Activity
146 implements OnHistoryListener, OnRequestRefreshListener,
147 OnNavigationRequestMenuListener, OnNavigationSelectionChangedListener {
149 private static final String TAG = "NavigationActivity"; //$NON-NLS-1$
151 private static boolean DEBUG = false;
153 // Bookmark list XML tags
154 private static final String TAG_BOOKMARKS = "Bookmarks"; //$NON-NLS-1$
155 private static final String TAG_BOOKMARK = "bookmark"; //$NON-NLS-1$
157 private static final String STR_USB = "usb"; // $NON-NLS-1$
160 * Intent code for request a search.
162 public static final int INTENT_REQUEST_SEARCH = 10001;
165 * Intent code for request a search.
167 public static final int INTENT_REQUEST_SETTINGS = 20001;
170 * Constant for extra information about selected search entry.
172 public static final String EXTRA_SEARCH_ENTRY_SELECTION =
173 "extra_search_entry_selection"; //$NON-NLS-1$
176 * Constant for extra information about last search data.
178 public static final String EXTRA_SEARCH_LAST_SEARCH_DATA =
179 "extra_search_last_search_data"; //$NON-NLS-1$
182 * Constant for extra information for request a navigation to the passed path.
184 public static final String EXTRA_NAVIGATE_TO =
185 "extra_navigate_to"; //$NON-NLS-1$
188 * Constant for extra information for request to add navigation to the history
190 public static final String EXTRA_ADD_TO_HISTORY =
191 "extra_add_to_history"; //$NON-NLS-1$
193 // The timeout needed to reset the exit status for back button
194 // After this time user need to tap 2 times the back button to
195 // exit, and the toast is shown again after the first tap.
196 private static final int RELEASE_EXIT_CHECK_TIMEOUT = 3500;
199 private Toolbar mToolBar;
200 private SearchView mSearchView;
201 private NavigationCustomTitleView mCustomTitleView;
202 private InputMethodManager mImm;
204 private final BroadcastReceiver mNotificationReceiver = new BroadcastReceiver() {
206 public void onReceive(Context context, Intent intent) {
207 if (intent != null) {
208 if (intent.getAction().compareTo(FileManagerSettings.INTENT_SETTING_CHANGED) == 0) {
209 // The settings has changed
210 String key = intent.getStringExtra(FileManagerSettings.EXTRA_SETTING_CHANGED_KEY);
212 // Disk usage warning level
213 if (key.compareTo(FileManagerSettings.
214 SETTINGS_DISK_USAGE_WARNING_LEVEL.getId()) == 0) {
216 // Set the free disk space warning level of the breadcrumb widget
217 Breadcrumb breadcrumb = getCurrentNavigationView().getBreadcrumb();
218 String fds = Preferences.getSharedPreferences().getString(
219 FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getId(),
220 (String)FileManagerSettings.
221 SETTINGS_DISK_USAGE_WARNING_LEVEL.getDefaultValue());
222 breadcrumb.setFreeDiskSpaceWarningLevel(Integer.parseInt(fds));
223 breadcrumb.updateMountPointInfo();
227 // Case sensitive sort
228 if (key.compareTo(FileManagerSettings.
229 SETTINGS_CASE_SENSITIVE_SORT.getId()) == 0) {
230 getCurrentNavigationView().refresh();
235 if (key.compareTo(FileManagerSettings.
236 SETTINGS_DISPLAY_THUMBS.getId()) == 0) {
237 // Clean the icon cache applying the current theme
243 if (key.compareTo(FileManagerSettings.
244 SETTINGS_USE_FLINGER.getId()) == 0) {
246 Preferences.getSharedPreferences().getBoolean(
247 FileManagerSettings.SETTINGS_USE_FLINGER.getId(),
248 ((Boolean)FileManagerSettings.
249 SETTINGS_USE_FLINGER.
250 getDefaultValue()).booleanValue());
251 getCurrentNavigationView().setUseFlinger(useFlinger);
256 if (key.compareTo(FileManagerSettings.
257 SETTINGS_ACCESS_MODE.getId()) == 0) {
258 // Is it necessary to create or exit of the ChRooted?
260 FileManagerApplication.
261 getAccessMode().compareTo(AccessMode.SAFE) == 0;
262 if (chRooted != NavigationActivity.this.mChRooted) {
272 if (key.compareTo(FileManagerSettings.
273 SETTINGS_RESTRICT_SECONDARY_USERS_ACCESS.getId()) == 0) {
274 if (AndroidHelper.isSecondaryUser(context)) {
276 Preferences.savePreference(
277 FileManagerSettings.SETTINGS_ACCESS_MODE,
278 AccessMode.SAFE, true);
279 } catch (Throwable ex) {
280 Log.w(TAG, "can't save console preference", ex); //$NON-NLS-1$
282 ConsoleBuilder.changeToNonPrivilegedConsole(context);
287 // Filetime format mode
288 if (key.compareTo(FileManagerSettings.
289 SETTINGS_FILETIME_FORMAT_MODE.getId()) == 0) {
291 synchronized (FileHelper.DATETIME_SYNC) {
292 FileHelper.sReloadDateTimeFormats = true;
293 NavigationActivity.this.getCurrentNavigationView().refresh();
298 } else if (intent.getAction().compareTo(
299 FileManagerSettings.INTENT_FILE_CHANGED) == 0) {
300 // Retrieve the file that was changed
302 intent.getStringExtra(FileManagerSettings.EXTRA_FILE_CHANGED_KEY);
304 FileSystemObject fso = CommandHelper.getFileInfo(context, file, null);
306 getCurrentNavigationView().refresh(fso);
308 } catch (Exception e) {
309 ExceptionUtil.translateException(context, e, true, false);
312 } else if (intent.getAction().compareTo(
313 FileManagerSettings.INTENT_THEME_CHANGED) == 0) {
316 } else if (intent.getAction().compareTo(Intent.ACTION_TIME_CHANGED) == 0 ||
317 intent.getAction().compareTo(Intent.ACTION_DATE_CHANGED) == 0 ||
318 intent.getAction().compareTo(Intent.ACTION_TIMEZONE_CHANGED) == 0 ||
319 intent.getAction().compareTo(Intent.ACTION_LOCALE_CHANGED) == 0) {
321 synchronized (FileHelper.DATETIME_SYNC) {
322 FileHelper.sReloadDateTimeFormats = true;
323 NavigationActivity.this.getCurrentNavigationView().refresh();
325 } else if (intent.getAction().compareTo(
326 FileManagerSettings.INTENT_MOUNT_STATUS_CHANGED) == 0 ||
327 intent.getAction().equals(Intent.ACTION_MEDIA_MOUNTED) ||
328 intent.getAction().equals(Intent.ACTION_MEDIA_UNMOUNTED)) {
329 onRequestBookmarksRefresh();
330 removeUnmountedHistory();
331 removeUnmountedSelection();
337 private OnClickListener mOnClickDrawerTabListener = new OnClickListener() {
339 public void onClick(View v) {
341 case R.id.drawer_bookmarks_tab:
342 if (!mBookmarksTab.isSelected()) {
343 mBookmarksTab.setSelected(true);
344 mHistoryTab.setSelected(false);
345 mBookmarksTab.setTextAppearance(
346 NavigationActivity.this, R.style.primary_text_appearance);
347 mHistoryTab.setTextAppearance(
348 NavigationActivity.this, R.style.secondary_text_appearance);
349 mHistoryLayout.setVisibility(View.GONE);
350 mBookmarksLayout.setVisibility(View.VISIBLE);
354 Preferences.savePreference(FileManagerSettings.USER_PREF_LAST_DRAWER_TAB,
355 Integer.valueOf(0), true);
356 } catch (Exception ex) {
357 Log.e(TAG, "Can't save last drawer tab", ex); //$NON-NLS-1$
360 mClearHistory.setVisibility(View.GONE);
363 case R.id.drawer_history_tab:
364 if (!mHistoryTab.isSelected()) {
365 mHistoryTab.setSelected(true);
366 mBookmarksTab.setSelected(false);
367 mHistoryTab.setTextAppearance(
368 NavigationActivity.this, R.style.primary_text_appearance);
369 mBookmarksTab.setTextAppearance(
370 NavigationActivity.this, R.style.secondary_text_appearance);
371 mBookmarksLayout.setVisibility(View.GONE);
372 mHistoryLayout.setVisibility(View.VISIBLE);
376 Preferences.savePreference(FileManagerSettings.USER_PREF_LAST_DRAWER_TAB,
377 Integer.valueOf(1), true);
378 } catch (Exception ex) {
379 Log.e(TAG, "Can't save last drawer tab", ex); //$NON-NLS-1$
382 mClearHistory.setVisibility(mHistory.size() > 0 ? View.VISIBLE : View.GONE);
391 private OnClickListener mOnClickDrawerActionBarListener = new OnClickListener() {
393 public void onClick(View v) {
395 case R.id.ab_settings:
396 mDrawerLayout.closeDrawer(Gravity.START);
399 case R.id.ab_clear_history:
401 mClearHistory.setVisibility(View.GONE);
409 static String MIME_TYPE_LOCALIZED_NAMES[];
413 static Map<MimeTypeCategory, Drawable> EASY_MODE_ICONS = new
414 HashMap<MimeTypeCategory, Drawable>();
419 NavigationView[] mNavigationViews;
423 ListView mEasyModeListView;
424 private List<History> mHistory;
426 private static final List<MimeTypeCategory> EASY_MODE_LIST = new ArrayList<MimeTypeCategory>() {
437 private ArrayAdapter<MimeTypeCategory> mEasyModeAdapter;
438 private View.OnClickListener mEasyModeItemClickListener = new View.OnClickListener() {
440 public void onClick(View view) {
441 Integer position = (Integer) view.getTag();
446 private int mCurrentNavigationView;
448 private ViewGroup mActionBar;
449 private SelectionView mSelectionBar;
451 private DrawerLayout mDrawerLayout;
452 private ViewGroup mDrawer;
453 private ActionBarDrawerToggle mDrawerToggle;
454 private LinearLayout mDrawerHistory;
455 private TextView mDrawerHistoryEmpty;
457 private TextView mBookmarksTab;
458 private TextView mHistoryTab;
459 private View mBookmarksLayout;
460 private View mHistoryLayout;
462 private ButtonItem mSettings;
463 private ButtonItem mClearHistory;
465 private List<Bookmark> mBookmarks;
466 private List<Bookmark> mSdBookmarks;
467 private LinearLayout mDrawerBookmarks;
469 private boolean mExitFlag = false;
470 private long mExitBackTimeout = -1;
472 private Dialog mActiveDialog = null;
474 private int mOrientation;
476 private boolean mNeedsEasyMode = false;
488 private AsyncTask<Void, Void, Boolean> mBookmarksTask;
494 protected void onCreate(Bundle state) {
497 Log.d(TAG, "NavigationActivity.onCreate"); //$NON-NLS-1$
500 // Register the broadcast receiver
501 IntentFilter filter = new IntentFilter();
502 filter.addAction(FileManagerSettings.INTENT_SETTING_CHANGED);
503 filter.addAction(FileManagerSettings.INTENT_FILE_CHANGED);
504 filter.addAction(FileManagerSettings.INTENT_THEME_CHANGED);
505 filter.addAction(Intent.ACTION_DATE_CHANGED);
506 filter.addAction(Intent.ACTION_TIME_CHANGED);
507 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
508 filter.addAction(Intent.ACTION_LOCALE_CHANGED);
509 filter.addAction(FileManagerSettings.INTENT_MOUNT_STATUS_CHANGED);
510 registerReceiver(this.mNotificationReceiver, filter);
512 // This filter needs the file data scheme, so it must be defined separately.
513 IntentFilter newFilter = new IntentFilter();
514 newFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
515 newFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
516 newFilter.addDataScheme(ContentResolver.SCHEME_FILE);
517 registerReceiver(mNotificationReceiver, newFilter);
519 //the input manager service
520 mImm = (InputMethodManager) this.getSystemService(
521 Context.INPUT_METHOD_SERVICE);
523 // Set the theme before setContentView
524 Theme theme = ThemeManager.getCurrentTheme(this);
525 theme.setBaseThemeNoActionBar(this);
527 //Set the main layout of the activity
528 setContentView(R.layout.navigation);
530 //Initialize nfc adapter
531 NfcAdapter mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
532 if (mNfcAdapter != null) {
533 mNfcAdapter.setBeamPushUrisCallback(new NfcAdapter.CreateBeamUrisCallback() {
535 public Uri[] createBeamUris(NfcEvent event) {
536 List<FileSystemObject> selectedFiles =
537 getCurrentNavigationView().getSelectedFiles();
538 if (selectedFiles.size() > 0) {
539 List<Uri> fileUri = new ArrayList<Uri>();
540 for (FileSystemObject f : selectedFiles) {
541 //Beam ignores folders and system files
542 if (!FileHelper.isDirectory(f) && !FileHelper.isSystemFile(f)) {
543 fileUri.add(Uri.fromFile(new File(f.getFullPath())));
546 if (fileUri.size() > 0) {
547 return fileUri.toArray(new Uri[fileUri.size()]);
555 //Initialize activity
559 initNavigationViews();
561 // As we're using a Toolbar, we should retrieve it and set it
562 // to be our ActionBar
563 mToolBar = (Toolbar) findViewById(R.id.material_toolbar);
564 setActionBar(mToolBar);
566 //Initialize action bars
567 initTitleActionBar();
568 initStatusActionBar();
571 // Initialize navigation drawer
575 // Adjust layout (only when start on landscape mode)
576 int orientation = getResources().getConfiguration().orientation;
577 if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
580 this.mOrientation = orientation;
585 // Show welcome message
588 this.mHandler = new Handler();
589 this.mHandler.post(new Runnable() {
592 // Initialize console
595 //Initialize navigation
596 int cc = NavigationActivity.this.mNavigationViews.length;
597 for (int i = 0; i < cc; i++) {
598 initNavigation(i, false, getIntent());
601 //Check the intent action
602 checkIntent(getIntent());
606 MIME_TYPE_LOCALIZED_NAMES = MimeTypeCategory.getFriendlyLocalizedNames(NavigationActivity
609 EASY_MODE_ICONS.put(MimeTypeCategory.NONE, getResources().getDrawable(R.drawable
611 EASY_MODE_ICONS.put(MimeTypeCategory.IMAGE, getResources().getDrawable(R.drawable
613 EASY_MODE_ICONS.put(MimeTypeCategory.VIDEO, getResources().getDrawable(R.drawable
615 EASY_MODE_ICONS.put(MimeTypeCategory.AUDIO, getResources().getDrawable(R.drawable
617 EASY_MODE_ICONS.put(MimeTypeCategory.DOCUMENT, getResources().getDrawable(R.drawable
619 EASY_MODE_ICONS.put(MimeTypeCategory.APP, getResources().getDrawable(R.drawable
620 .ic_em_application));
623 super.onCreate(state);
627 protected void onResume() {
630 if (mSearchView.getVisibility() == View.VISIBLE) {
634 // Check restrictions
635 if (!FileManagerApplication.checkRestrictSecondaryUsersAccess(this, mChRooted)) {
639 // Check that the current dir is mounted (for virtual filesystems)
640 String curDir = mNavigationViews[mCurrentNavigationView].getCurrentDir();
641 if (curDir != null) {
642 VirtualMountPointConsole vc = VirtualMountPointConsole.getVirtualConsoleForPath(
643 mNavigationViews[mCurrentNavigationView].getCurrentDir());
644 if (vc != null && !vc.isMounted()) {
645 onRequestBookmarksRefresh();
646 removeUnmountedHistory();
647 removeUnmountedSelection();
649 Intent intent = new Intent();
650 intent.putExtra(EXTRA_ADD_TO_HISTORY, false);
651 initNavigation(NavigationActivity.this.mCurrentNavigationView, false, intent);
657 protected void onPostCreate(Bundle savedInstanceState) {
658 super.onPostCreate(savedInstanceState);
659 // Sync the toggle state after onRestoreInstanceState has occurred.
660 mDrawerToggle.syncState();
667 protected void onNewIntent(Intent intent) {
668 //Initialize navigation
669 initNavigation(this.mCurrentNavigationView, true, intent);
671 //Check the intent action
679 public void onConfigurationChanged(Configuration newConfig) {
680 super.onConfigurationChanged(newConfig);
682 mDrawerToggle.onConfigurationChanged(newConfig);
689 public boolean onOptionsItemSelected(MenuItem item) {
690 if (mDrawerToggle.onOptionsItemSelected(item)) {
694 if (mNeedsEasyMode) {
695 if (item.getItemId() == android.R.id.home) {
696 if (mHistory.size() == 0 && !isEasyModeVisible()) {
697 performShowEasyMode();
703 return super.onOptionsItemSelected(item);
710 protected void onDestroy() {
712 Log.d(TAG, "NavigationActivity.onDestroy"); //$NON-NLS-1$
715 if (mActiveDialog != null && mActiveDialog.isShowing()) {
716 mActiveDialog.dismiss();
719 // Unregister the receiver
721 unregisterReceiver(this.mNotificationReceiver);
722 } catch (Throwable ex) {
726 //All destroy. Continue
731 * Method that returns the current navigation view.
733 * @return NavigationView The current navigation view
735 public NavigationView getCurrentNavigationView() {
736 return getNavigationView(this.mCurrentNavigationView);
740 * Method that returns the current navigation view.
742 * @param viewId The view to return
743 * @return NavigationView The current navigation view
745 public NavigationView getNavigationView(int viewId) {
746 if (this.mNavigationViews == null) return null;
747 return this.mNavigationViews[viewId];
751 * Method that initializes the activity.
753 private void init() {
754 this.mHistory = new ArrayList<History>();
755 this.mChRooted = FileManagerApplication.getAccessMode().compareTo(AccessMode.SAFE) == 0;
759 * Method that displays a welcome message the first time the user
760 * access the application
762 private void showWelcomeMsg() {
763 boolean firstUse = Preferences.getSharedPreferences().getBoolean(
764 FileManagerSettings.SETTINGS_FIRST_USE.getId(),
765 ((Boolean)FileManagerSettings.SETTINGS_FIRST_USE.getDefaultValue()).booleanValue());
767 //Display the welcome message?
768 if (firstUse && FileManagerApplication.hasShellCommands()) {
769 // open navigation drawer to show user that it exists
770 mDrawerLayout.openDrawer(Gravity.START);
772 AlertDialog dialog = DialogHelper.createAlertDialog(this,
773 R.mipmap.ic_launcher_filemanager, R.string.welcome_title,
774 getString(R.string.welcome_msg), false);
775 DialogHelper.delegateDialogShow(this, dialog);
777 // Don't display again this dialog
779 Preferences.savePreference(
780 FileManagerSettings.SETTINGS_FIRST_USE, Boolean.FALSE, true);
781 } catch (Exception e) {/**NON BLOCK**/}
786 * Method that initializes the titlebar of the activity.
788 private void initTitleActionBar() {
789 //Inflate the view and associate breadcrumb
790 View titleLayout = getLayoutInflater().inflate(
791 R.layout.navigation_view_customtitle, null, false);
792 NavigationCustomTitleView title =
793 (NavigationCustomTitleView)titleLayout.findViewById(R.id.navigation_title_flipper);
794 title.setOnHistoryListener(this);
795 Breadcrumb breadcrumb = (Breadcrumb)title.findViewById(R.id.breadcrumb_view);
796 int cc = this.mNavigationViews.length;
797 for (int i = 0; i < cc; i++) {
798 this.mNavigationViews[i].setBreadcrumb(breadcrumb);
799 this.mNavigationViews[i].setOnHistoryListener(this);
800 this.mNavigationViews[i].setOnNavigationSelectionChangedListener(this);
801 this.mNavigationViews[i].setOnNavigationOnRequestMenuListener(this);
802 this.mNavigationViews[i].setCustomTitle(title);
805 // Set the free disk space warning level of the breadcrumb widget
806 String fds = Preferences.getSharedPreferences().getString(
807 FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getId(),
808 (String)FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getDefaultValue());
809 breadcrumb.setFreeDiskSpaceWarningLevel(Integer.parseInt(fds));
811 //Configure the action bar options
812 getActionBar().setBackgroundDrawable(
813 getResources().getDrawable(R.drawable.bg_material_titlebar));
814 mToolBar.addView(titleLayout);
818 * Method that initializes the statusbar of the activity.
820 private void initStatusActionBar() {
821 //Performs a width calculation of buttons. Buttons exceeds the width
822 //of the action bar should be hidden
823 //This application not use android ActionBar because the application
824 //make uses of the title and bottom areas, and wants to force to show
825 //the overflow button (without care of physical buttons)
826 this.mActionBar = (ViewGroup)findViewById(R.id.navigation_actionbar);
827 this.mActionBar.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
829 public void onLayoutChange(
830 View v, int left, int top, int right, int bottom, int oldLeft,
831 int oldTop, int oldRight, int oldBottom) {
832 //Get the width of the action bar
833 int w = v.getMeasuredWidth();
835 //Wake through children calculation his dimensions
836 int bw = (int)getResources().getDimension(R.dimen.default_buttom_width);
838 final ViewGroup abView = ((ViewGroup)v);
839 int cc = abView.getChildCount();
840 for (int i = 0; i < cc; i++) {
841 View child = abView.getChildAt(i);
842 child.setVisibility(cw + bw > w ? View.INVISIBLE : View.VISIBLE);
848 // Have overflow menu? Actually no. There is only a search action, so just hide
850 View overflow = findViewById(R.id.ab_overflow);
851 overflow.setVisibility(View.GONE);
853 // Show the status bar
854 View statusBar = findViewById(R.id.navigation_statusbar_portrait_holder);
855 statusBar.setVisibility(View.VISIBLE);
859 * Method that initializes the selectionbar of the activity.
861 private void initSelectionBar() {
862 this.mSelectionBar = (SelectionView)findViewById(R.id.navigation_selectionbar);
866 * Method that initializes the navigation drawer of the activity.
868 private void initDrawer() {
869 mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
870 //Set our status bar color
871 mDrawerLayout.setStatusBarBackgroundColor(R.color.material_palette_blue_primary_dark);
872 mDrawer = (ViewGroup) findViewById(R.id.drawer);
873 mDrawerBookmarks = (LinearLayout) findViewById(R.id.bookmarks_list);
874 mDrawerHistory = (LinearLayout) findViewById(R.id.history_list);
875 mDrawerHistoryEmpty = (TextView) findViewById(R.id.history_empty);
877 mBookmarksLayout = findViewById(R.id.drawer_bookmarks);
878 mHistoryLayout = findViewById(R.id.drawer_history);
879 mBookmarksTab = (TextView) findViewById(R.id.drawer_bookmarks_tab);
880 mHistoryTab = (TextView) findViewById(R.id.drawer_history_tab);
881 mBookmarksTab.setOnClickListener(mOnClickDrawerTabListener);
882 mHistoryTab.setOnClickListener(mOnClickDrawerTabListener);
884 mSettings = (ButtonItem) findViewById(R.id.ab_settings);
885 mSettings.setOnClickListener(mOnClickDrawerActionBarListener);
886 mClearHistory = (ButtonItem) findViewById(R.id.ab_clear_history);
887 mClearHistory.setOnClickListener(mOnClickDrawerActionBarListener);
889 // Restore the last tab pressed
890 Integer lastTab = Preferences.getSharedPreferences().getInt(
891 FileManagerSettings.USER_PREF_LAST_DRAWER_TAB.getId(),
892 (Integer) FileManagerSettings.USER_PREF_LAST_DRAWER_TAB
894 mOnClickDrawerTabListener.onClick(lastTab == 0 ? mBookmarksTab : mHistoryTab);
896 // Set the navigation drawer "hamburger" icon
897 mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
898 R.drawable.ic_material_light_navigation_drawer,
899 R.string.drawer_open, R.string.drawer_close) {
901 /** Called when a drawer has settled in a completely closed state. */
902 public void onDrawerClosed(View view) {
903 super.onDrawerClosed(view);
906 /** Called when a drawer has settled in a completely open state. */
907 public void onDrawerOpened(View drawerView) {
908 onDrawerLayoutOpened(drawerView);
909 super.onDrawerOpened(drawerView);
912 getActionBar().setDisplayHomeAsUpEnabled(true);
914 // Set the drawer toggle as the DrawerListener
915 mDrawerLayout.setDrawerListener(mDrawerToggle);
919 * Method that do something when the DrawerLayout opened.
921 private void onDrawerLayoutOpened(View drawerView){
922 if (mSearchView != null && mSearchView.getVisibility() == View.VISIBLE) {
924 hideSoftInput(drawerView);
929 * Method that hide the software when the software showing.
932 private void hideSoftInput(View view){
934 mImm.hideSoftInputFromWindow(view.getWindowToken(), 0);
939 * Method that adds a history entry to the history list in the drawer
941 private void addHistoryToDrawer(int index, HistoryNavigable navigable) {
942 // hide empty message
943 mDrawerHistoryEmpty.setVisibility(View.GONE);
945 Theme theme = ThemeManager.getCurrentTheme(this);
946 IconHolder iconholder = new IconHolder(this, false);
948 // inflate single bookmark layout item and fill it
949 LinearLayout view = (LinearLayout) getLayoutInflater().inflate(
950 R.layout.history_item, null);
952 ImageView iconView = (ImageView) view
953 .findViewById(R.id.history_item_icon);
954 TextView name = (TextView) view.findViewById(R.id.history_item_name);
955 TextView directory = (TextView) view
956 .findViewById(R.id.history_item_directory);
958 Drawable icon = iconholder.getDrawable("ic_fso_folder_drawable"); //$NON-NLS-1$
959 if (navigable instanceof SearchInfoParcelable) {
960 icon = iconholder.getDrawable("ic_history_search_drawable"); //$NON-NLS-1$
962 iconView.setImageDrawable(icon);
964 String title = navigable.getTitle();
965 if (title == null || title.trim().length() == 0) {
966 title = getString(R.string.root_directory_name);
970 directory.setText(navigable.getDescription());
972 theme.setTextColor(this, name, "text_color");
973 theme.setTextColor(this, directory, "text_color");
976 view.setOnClickListener(new OnClickListener() {
978 public void onClick(View v) {
979 final int index = mDrawerHistory.indexOfChild(v);
980 final int count = mDrawerHistory.getChildCount();
981 final History history = mHistory.get(count - index - 1);
983 navigateToHistory(history);
984 mDrawerLayout.closeDrawer(Gravity.START);
988 // add as first child
989 mDrawerHistory.addView(view, 0);
991 // Show clear button if history tab is selected
992 mClearHistory.setVisibility(mHistoryTab.isSelected() ? View.VISIBLE : View.GONE);
996 * Method takes a bookmark as argument and adds it to mBookmarks and the
999 public void addBookmark(Bookmark bookmark) {
1000 mBookmarks.add(bookmark);
1001 addBookmarkToDrawer(bookmark);
1005 * Show the easy mode view
1007 private void performShowEasyMode() {
1008 mEasyModeListView.setVisibility(View.VISIBLE);
1009 getCurrentNavigationView().setVisibility(View.GONE);
1010 performShowBackArrow(false);
1014 * Hide the easy mode view
1016 private void performHideEasyMode() {
1017 mEasyModeListView.setVisibility(View.GONE);
1018 getCurrentNavigationView().setVisibility(View.VISIBLE);
1021 private void performShowBackArrow(boolean showBackArrow) {
1022 if (mNeedsEasyMode) {
1023 mDrawerToggle.setDrawerIndicatorEnabled(!showBackArrow);
1027 private boolean isEasyModeVisible() {
1028 return mEasyModeListView.getVisibility() != View.GONE;
1032 * Method takes a bookmark as argument and adds it to the bookmark list in
1035 private void addBookmarkToDrawer(Bookmark bookmark) {
1036 Theme theme = ThemeManager.getCurrentTheme(this);
1037 IconHolder iconholder = new IconHolder(this, false);
1039 // inflate single bookmark layout item and fill it
1040 LinearLayout view = (LinearLayout) getLayoutInflater().inflate(
1041 R.layout.bookmarks_item, null);
1043 ImageView icon = (ImageView) view
1044 .findViewById(R.id.bookmarks_item_icon);
1045 TextView name = (TextView) view.findViewById(R.id.bookmarks_item_name);
1046 TextView path = (TextView) view.findViewById(R.id.bookmarks_item_path);
1047 ImageButton actionButton = (ImageButton) view
1048 .findViewById(R.id.bookmarks_item_action);
1050 name.setText(bookmark.mName);
1051 path.setText(bookmark.mPath);
1053 theme.setTextColor(this, name, "text_color");
1054 theme.setTextColor(this, path, "text_color");
1056 icon.setImageDrawable(iconholder.getDrawable(BookmarksHelper
1057 .getIcon(bookmark)));
1059 Drawable action = null;
1060 String actionCd = null;
1061 if (bookmark.mType.compareTo(BOOKMARK_TYPE.HOME) == 0) {
1062 action = iconholder.getDrawable("ic_edit_home_bookmark_drawable"); //$NON-NLS-1$
1063 actionCd = getApplicationContext().getString(
1064 R.string.bookmarks_button_config_cd);
1066 else if (bookmark.mType.compareTo(BOOKMARK_TYPE.USER_DEFINED) == 0) {
1067 action = iconholder.getDrawable("ic_close_drawable"); //$NON-NLS-1$
1068 actionCd = getApplicationContext().getString(
1069 R.string.bookmarks_button_remove_bookmark_cd);
1072 actionButton.setImageDrawable(action);
1073 actionButton.setVisibility(action != null ? View.VISIBLE : View.GONE);
1074 actionButton.setOnClickListener(new OnClickListener() {
1076 public void onClick(View view) {
1077 final View v = (View) view.getParent();
1078 final int index = mDrawerBookmarks.indexOfChild(v);
1079 final Bookmark bookmark = mBookmarks.get(index);
1082 if (bookmark.mType.compareTo(BOOKMARK_TYPE.HOME) == 0) {
1083 // Show a dialog for configure initial directory
1084 InitialDirectoryDialog dialog = new InitialDirectoryDialog(
1085 NavigationActivity.this);
1086 dialog.setOnValueChangedListener(new InitialDirectoryDialog.OnValueChangedListener() {
1088 public void onValueChanged(String newInitialDir) {
1089 bookmark.mPath = newInitialDir;
1091 // reset drawer bookmarks list
1100 if (bookmark.mType.compareTo(BOOKMARK_TYPE.USER_DEFINED) == 0) {
1101 boolean result = Bookmarks.removeBookmark(
1102 getApplicationContext(), bookmark);
1103 if (!result) { // Show warning
1104 DialogHelper.showToast(getApplicationContext(),
1105 R.string.msgs_operation_failure,
1106 Toast.LENGTH_SHORT);
1109 mBookmarks.remove(bookmark);
1110 mDrawerBookmarks.removeView(v);
1115 actionButton.setContentDescription(actionCd);
1117 // handle item click
1118 view.setOnClickListener(new OnClickListener() {
1120 public void onClick(View v) {
1121 final int index = mDrawerBookmarks.indexOfChild(v);
1122 final Bookmark bookmark = mBookmarks.get(index);
1124 boolean showEasyMode = (mSdBookmarks.contains(bookmark)) &&
1125 getResources().getBoolean(R.bool.cmcc_show_easy_mode);
1127 // try to navigate to the bookmark path
1129 FileSystemObject fso = CommandHelper.getFileInfo(
1130 getApplicationContext(), bookmark.mPath, null);
1133 performShowEasyMode();
1135 performHideEasyMode();
1137 performShowBackArrow(!mDrawerToggle.isDrawerIndicatorEnabled());
1138 getCurrentNavigationView().open(fso);
1139 mDrawerLayout.closeDrawer(Gravity.START);
1142 // The bookmark does not exist, delete the user-defined
1145 Bookmarks.removeBookmark(getApplicationContext(),
1148 // reset bookmarks list to default
1151 catch (Exception ex) {
1155 catch (Exception e) { // Capture the exception
1157 .translateException(NavigationActivity.this, e);
1158 if (e instanceof NoSuchFileOrDirectory
1159 || e instanceof FileNotFoundException) {
1160 // The bookmark does not exist, delete the user-defined
1163 Bookmarks.removeBookmark(getApplicationContext(),
1166 // reset bookmarks list to default
1169 catch (Exception ex) {
1177 mDrawerBookmarks.addView(view);
1181 * Method that initializes the bookmarks.
1183 private synchronized void initBookmarks() {
1184 if (mBookmarksTask != null &&
1185 !mBookmarksTask.getStatus().equals(AsyncTask.Status.FINISHED)) {
1189 // Retrieve the loading view
1190 final View waiting = findViewById(R.id.bookmarks_loading);
1192 // Load bookmarks in background
1193 mBookmarksTask = new AsyncTask<Void, Void, Boolean>() {
1197 protected Boolean doInBackground(Void... params) {
1199 mBookmarks = loadBookmarks();
1200 return Boolean.TRUE;
1203 catch (Exception e) {
1205 return Boolean.FALSE;
1210 protected void onPreExecute() {
1211 waiting.setVisibility(View.VISIBLE);
1212 mDrawerBookmarks.removeAllViews();
1216 protected void onPostExecute(Boolean result) {
1217 waiting.setVisibility(View.GONE);
1218 if (result.booleanValue()) {
1219 for (Bookmark bookmark : mBookmarks) {
1220 addBookmarkToDrawer(bookmark);
1224 if (this.mCause != null) {
1225 ExceptionUtil.translateException(
1226 NavigationActivity.this, this.mCause);
1229 mBookmarksTask = null;
1233 protected void onCancelled() {
1234 waiting.setVisibility(View.GONE);
1235 mBookmarksTask = null;
1238 mBookmarksTask.execute();
1242 * Method that loads all kind of bookmarks and join in an array to be used
1243 * in the listview adapter.
1245 * @return List<Bookmark>
1248 List<Bookmark> loadBookmarks() {
1249 // Bookmarks = HOME + FILESYSTEM + SD STORAGES + USER DEFINED
1250 // In ChRooted mode = SD STORAGES + USER DEFINED (from SD STORAGES)
1251 List<Bookmark> bookmarks = new ArrayList<Bookmark>();
1252 if (!this.mChRooted) {
1253 bookmarks.add(loadHomeBookmarks());
1254 bookmarks.addAll(loadFilesystemBookmarks());
1256 mSdBookmarks = loadSdStorageBookmarks();
1257 bookmarks.addAll(mSdBookmarks);
1258 bookmarks.addAll(loadVirtualBookmarks());
1259 bookmarks.addAll(loadUserBookmarks());
1264 * Method that loads the home bookmark from the user preference.
1266 * @return Bookmark The bookmark loaded
1268 private Bookmark loadHomeBookmarks() {
1269 String initialDir = Preferences.getSharedPreferences().getString(
1270 FileManagerSettings.SETTINGS_INITIAL_DIR.getId(),
1271 (String) FileManagerSettings.SETTINGS_INITIAL_DIR
1272 .getDefaultValue());
1273 return new Bookmark(BOOKMARK_TYPE.HOME,
1274 getString(R.string.bookmarks_home), initialDir);
1278 * Method that loads the filesystem bookmarks from the internal xml file.
1279 * (defined by this application)
1281 * @return List<Bookmark> The bookmarks loaded
1283 private List<Bookmark> loadFilesystemBookmarks() {
1285 // Initialize the bookmarks
1286 List<Bookmark> bookmarks = new ArrayList<Bookmark>();
1288 // Read the command list xml file
1289 XmlResourceParser parser = getResources().getXml(
1290 R.xml.filesystem_bookmarks);
1293 // Find the root element
1294 XmlUtils.beginDocument(parser, TAG_BOOKMARKS);
1296 XmlUtils.nextElement(parser);
1297 String element = parser.getName();
1298 if (element == null) {
1302 if (TAG_BOOKMARK.equals(element)) {
1303 CharSequence name = null;
1304 CharSequence directory = null;
1307 name = getString(parser.getAttributeResourceValue(
1308 R.styleable.Bookmark_name, 0));
1310 catch (Exception e) {
1314 directory = getString(parser
1315 .getAttributeResourceValue(
1316 R.styleable.Bookmark_directory, 0));
1318 catch (Exception e) {
1321 if (directory == null) {
1323 .getAttributeValue(R.styleable.Bookmark_directory);
1325 if (name != null && directory != null) {
1326 bookmarks.add(new Bookmark(
1327 BOOKMARK_TYPE.FILESYSTEM, name.toString(),
1328 directory.toString()));
1333 // Return the bookmarks
1341 catch (Throwable ex) {
1342 Log.e(TAG, "Load filesystem bookmarks failed", ex); //$NON-NLS-1$
1346 return new ArrayList<Bookmark>();
1350 * Method that loads the secure digital card storage bookmarks from the
1353 * @return List<Bookmark> The bookmarks loaded
1355 private List<Bookmark> loadSdStorageBookmarks() {
1356 // Initialize the bookmarks
1357 List<Bookmark> bookmarks = new ArrayList<Bookmark>();
1360 // Recovery sdcards from storage manager
1361 StorageVolume[] volumes = StorageHelper
1362 .getStorageVolumes(getApplication(), true);
1363 for (StorageVolume volume: volumes) {
1364 if (volume != null) {
1365 String mountedState = volume.getState();
1366 String path = volume.getPath();
1367 if (!Environment.MEDIA_MOUNTED.equalsIgnoreCase(mountedState) &&
1368 !Environment.MEDIA_MOUNTED_READ_ONLY.equalsIgnoreCase(mountedState)) {
1369 Log.w(TAG, "Ignoring '" + path + "' with state of '"+ mountedState + "'");
1372 if (!TextUtils.isEmpty(path)) {
1373 String lowerPath = path.toLowerCase(Locale.ROOT);
1375 if (lowerPath.contains(STR_USB)) {
1376 bookmark = new Bookmark(BOOKMARK_TYPE.USB, StorageHelper
1377 .getStorageVolumeDescription(getApplication(), volume), path);
1379 bookmark = new Bookmark(BOOKMARK_TYPE.SDCARD, StorageHelper
1380 .getStorageVolumeDescription(getApplication(), volume), path);
1382 bookmarks.add(bookmark);
1387 // Return the bookmarks
1390 catch (Throwable ex) {
1391 Log.e(TAG, "Load filesystem bookmarks failed", ex); //$NON-NLS-1$
1395 return new ArrayList<Bookmark>();
1399 * Method that loads all virtual mount points.
1401 * @return List<Bookmark> The bookmarks loaded
1403 private List<Bookmark> loadVirtualBookmarks() {
1404 // Initialize the bookmarks
1405 List<Bookmark> bookmarks = new ArrayList<Bookmark>();
1406 List<MountPoint> mps = VirtualMountPointConsole.getVirtualMountPoints();
1407 for (MountPoint mp : mps) {
1408 BOOKMARK_TYPE type = null;
1410 if (mp.isSecure()) {
1411 type = BOOKMARK_TYPE.SECURE;
1412 name = getString(R.string.bookmarks_secure);
1413 } else if (mp.isRemote()) {
1414 type = BOOKMARK_TYPE.REMOTE;
1415 name = getString(R.string.bookmarks_remote);
1419 bookmarks.add(new Bookmark(type, name, mp.getMountPoint()));
1425 * Method that loads the user bookmarks (added by the user).
1427 * @return List<Bookmark> The bookmarks loaded
1429 private List<Bookmark> loadUserBookmarks() {
1430 List<Bookmark> bookmarks = new ArrayList<Bookmark>();
1431 Cursor cursor = Bookmarks.getAllBookmarks(this.getContentResolver());
1433 if (cursor != null && cursor.moveToFirst()) {
1435 Bookmark bm = new Bookmark(cursor);
1437 && !StorageHelper.isPathInStorageVolume(bm.mPath)) {
1442 while (cursor.moveToNext());
1447 if (cursor != null) {
1451 catch (Exception e) {
1456 // Remove bookmarks from virtual storage if the filesystem is not mount
1457 int c = bookmarks.size() - 1;
1458 for (int i = c; i >= 0; i--) {
1459 VirtualMountPointConsole vc =
1460 VirtualMountPointConsole.getVirtualConsoleForPath(bookmarks.get(i).mPath);
1461 if (vc != null && !vc.isMounted()) {
1462 bookmarks.remove(i);
1470 * Method that initializes the navigation views of the activity
1472 private void initNavigationViews() {
1473 //Get the navigation views (wishlist: multiple view; for now only one view)
1474 this.mNavigationViews = new NavigationView[1];
1475 this.mCurrentNavigationView = 0;
1477 this.mNavigationViews[0] = (NavigationView)findViewById(R.id.navigation_view);
1478 this.mNavigationViews[0].setId(0);
1479 this.mEasyModeListView = (ListView) findViewById(R.id.lv_easy_mode);
1480 mEasyModeAdapter = new ArrayAdapter<MimeTypeCategory>(this, R.layout
1481 .navigation_view_simple_item) {
1483 public View getView(int position, View convertView, ViewGroup parent) {
1484 convertView = (convertView == null) ?getLayoutInflater().inflate(R.layout
1485 .navigation_view_simple_item, parent, false) : convertView;
1486 MimeTypeCategory item = getItem(position);
1487 String typeTitle = MIME_TYPE_LOCALIZED_NAMES[item.ordinal()];
1488 TextView typeTitleTV = (TextView) convertView
1489 .findViewById(R.id.navigation_view_item_name);
1490 ImageView typeIconIV = (ImageView) convertView
1491 .findViewById(R.id.navigation_view_item_icon);
1492 View checkBoxView = convertView.findViewById(R.id.navigation_view_item_check);
1493 checkBoxView.setVisibility(View.GONE);
1494 typeTitleTV.setText(typeTitle);
1495 typeIconIV.setImageDrawable(EASY_MODE_ICONS.get(item));
1496 convertView.setOnClickListener(mEasyModeItemClickListener);
1497 convertView.setTag(position);
1501 mEasyModeAdapter.addAll(EASY_MODE_LIST);
1502 mEasyModeListView.setAdapter(mEasyModeAdapter);
1505 private void onClicked(int position) {
1506 Intent intent = new Intent(this, SearchActivity.class);
1507 intent.setAction(Intent.ACTION_SEARCH);
1508 intent.putExtra(SearchActivity.EXTRA_SEARCH_DIRECTORY,
1509 getCurrentNavigationView().getCurrentDir());
1510 intent.putExtra(SearchManager.QUERY, "*"); // Use wild-card '*'
1512 if (position == 0) {
1513 // the user has selected all items, they want to see their folders so let's do that.
1514 performHideEasyMode();
1515 performShowBackArrow(true);
1519 ArrayList<MimeTypeCategory> searchCategories = new ArrayList<MimeTypeCategory>();
1520 MimeTypeCategory selectedCategory = EASY_MODE_LIST.get(position);
1521 searchCategories.add(selectedCategory);
1522 // a one off case where we implicitly want to also search for TEXT mimetypes when the
1523 // DOCUMENTS category is selected
1524 if (selectedCategory == MimeTypeCategory.DOCUMENT) {
1525 searchCategories.add(MimeTypeCategory.TEXT);
1527 intent.putExtra(SearchActivity.EXTRA_SEARCH_MIMETYPE, searchCategories);
1530 startActivity(intent);
1534 * Method that initialize the console
1537 void initConsole() {
1538 //Create the default console (from the preferences)
1540 Console console = ConsoleBuilder.getConsole(NavigationActivity.this);
1541 if (console == null) {
1542 throw new ConsoleAllocException("console == null"); //$NON-NLS-1$
1544 } catch (Throwable ex) {
1545 if (!NavigationActivity.this.mChRooted) {
1546 //Show exception and exit
1547 Log.e(TAG, getString(R.string.msgs_cant_create_console), ex);
1548 // We don't have any console
1549 // Show exception and exit
1550 DialogHelper.showToast(
1551 NavigationActivity.this,
1552 R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
1557 // We are in a trouble (something is not allowing creating the console)
1558 // Ask the user to return to prompt or root access mode mode with a
1559 // non-privileged console, prior to make crash the application
1566 * Method that initializes the navigation.
1568 * @param viewId The navigation view identifier where apply the navigation
1569 * @param restore Initialize from a restore info
1570 * @param intent The current intent
1573 void initNavigation(final int viewId, final boolean restore, final Intent intent) {
1574 final NavigationView navigationView = getNavigationView(viewId);
1575 this.mHandler.post(new Runnable() {
1578 //Is necessary navigate?
1580 applyInitialDir(navigationView, intent);
1587 * Method that applies the user-defined initial directory
1589 * @param navigationView The navigation view
1590 * @param intent The current intent
1593 void applyInitialDir(final NavigationView navigationView, final Intent intent) {
1594 //Load the user-defined initial directory
1596 Preferences.getSharedPreferences().getString(
1597 FileManagerSettings.SETTINGS_INITIAL_DIR.getId(),
1598 (String)FileManagerSettings.
1599 SETTINGS_INITIAL_DIR.getDefaultValue());
1601 // Check if request navigation to directory (use as default), and
1602 // ensure chrooted and absolute path
1603 String navigateTo = intent.getStringExtra(EXTRA_NAVIGATE_TO);
1604 String intentAction = intent.getAction();
1605 if (navigateTo != null && navigateTo.length() > 0) {
1606 initialDir = navigateTo;
1607 } else if (intentAction != null && intentAction.equals(Intent.ACTION_VIEW)) {
1608 Uri data = intent.getData();
1609 if (data != null && (FileHelper.FILE_URI_SCHEME.equals(data.getScheme())
1610 || FileHelper.FOLDER_URI_SCHEME.equals(data.getScheme())
1611 || FileHelper.DIRECTORY_URI_SCHEME.equals(data.getScheme()))) {
1612 File path = new File(data.getPath());
1613 if (path.isDirectory()) {
1614 initialDir = path.getAbsolutePath();
1620 final boolean addToHistory = intent.getBooleanExtra(EXTRA_ADD_TO_HISTORY, true);
1622 // We cannot navigate to a secure console if it is unmounted. So go to root in that case
1623 VirtualConsole vc = VirtualMountPointConsole.getVirtualConsoleForPath(initialDir);
1624 if (vc != null && vc instanceof SecureConsole && !((SecureConsole) vc).isMounted()) {
1625 initialDir = FileHelper.ROOT_DIRECTORY;
1628 if (this.mChRooted) {
1629 // Initial directory is the first external sdcard (sdcard, emmc, usb, ...)
1630 if (!StorageHelper.isPathInStorageVolume(initialDir)) {
1631 StorageVolume[] volumes =
1632 StorageHelper.getStorageVolumes(this, false);
1633 if (volumes != null && volumes.length > 0) {
1634 initialDir = volumes[0].getPath();
1635 int count = volumes.length;
1636 for (int i = 0; i < count; i++) {
1637 StorageVolume volume = volumes[i];
1638 if (Environment.MEDIA_MOUNTED.equalsIgnoreCase(volume.getState())) {
1639 initialDir = volume.getPath();
1643 //Ensure that initial directory is an absolute directory
1644 initialDir = FileHelper.getAbsPath(initialDir);
1646 // Show exception and exit
1647 DialogHelper.showToast(
1649 R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
1655 //Ensure that initial directory is an absolute directory
1656 final String userInitialDir = initialDir;
1657 initialDir = FileHelper.getAbsPath(initialDir);
1658 final String absInitialDir = initialDir;
1659 File f = new File(initialDir);
1660 boolean exists = f.exists();
1662 // Fix for /data/media/0. Libcore doesn't detect it correctly.
1664 exists = CommandHelper.getFileInfo(this, initialDir, false, null) != null;
1665 } catch (InsufficientPermissionsException ipex) {
1666 ExceptionUtil.translateException(
1667 this, ipex, false, true, new OnRelaunchCommandResult() {
1669 public void onSuccess() {
1670 navigationView.changeCurrentDir(absInitialDir, addToHistory);
1673 public void onFailed(Throwable cause) {
1674 showInitialInvalidDirectoryMsg(userInitialDir);
1675 navigationView.changeCurrentDir(FileHelper.ROOT_DIRECTORY,
1679 public void onCancelled() {
1680 showInitialInvalidDirectoryMsg(userInitialDir);
1681 navigationView.changeCurrentDir(FileHelper.ROOT_DIRECTORY,
1686 // Asynchronous mode
1688 } catch (Exception ex) {
1689 // We are not interested in other exceptions
1690 ExceptionUtil.translateException(this, ex, true, false);
1693 // Check again the initial directory
1695 showInitialInvalidDirectoryMsg(userInitialDir);
1696 initialDir = FileHelper.ROOT_DIRECTORY;
1699 // Weird, but we have a valid initial directory
1703 boolean needsEasyMode = false;
1704 if (mSdBookmarks != null ) {
1705 for (Bookmark bookmark :mSdBookmarks) {
1706 if (bookmark.mPath.equalsIgnoreCase(initialDir)) {
1707 needsEasyMode = true;
1713 mNeedsEasyMode = getResources().getBoolean(R.bool.cmcc_show_easy_mode);
1715 needsEasyMode = needsEasyMode && mNeedsEasyMode;
1716 if (needsEasyMode) {
1717 performShowEasyMode();
1719 performHideEasyMode();
1721 // Change the current directory to the user-defined initial directory
1722 navigationView.changeCurrentDir(initialDir, addToHistory);
1726 * Displays a message reporting invalid directory
1728 * @param initialDir The initial directory
1731 void showInitialInvalidDirectoryMsg(String initialDir) {
1732 // Change to root directory
1733 DialogHelper.showToast(
1736 R.string.msgs_settings_invalid_initial_directory,
1738 Toast.LENGTH_SHORT);
1742 * Method that verifies the intent passed to the activity, and checks
1743 * if a request is made like Search.
1745 * @param intent The intent to check
1748 void checkIntent(Intent intent) {
1750 if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
1751 Intent searchIntent = new Intent(this, SearchActivity.class);
1752 searchIntent.setAction(Intent.ACTION_SEARCH);
1753 //- SearchActivity.EXTRA_SEARCH_DIRECTORY
1754 searchIntent.putExtra(
1755 SearchActivity.EXTRA_SEARCH_DIRECTORY,
1756 getCurrentNavigationView().getCurrentDir());
1757 //- SearchManager.APP_DATA
1758 if (intent.getBundleExtra(SearchManager.APP_DATA) != null) {
1759 Bundle bundle = new Bundle();
1760 bundle.putAll(intent.getBundleExtra(SearchManager.APP_DATA));
1761 searchIntent.putExtra(SearchManager.APP_DATA, bundle);
1763 //-- SearchManager.QUERY
1764 String query = intent.getStringExtra(SearchManager.QUERY);
1765 if (query != null) {
1766 searchIntent.putExtra(SearchManager.QUERY, query);
1768 //- android.speech.RecognizerIntent.EXTRA_RESULTS
1769 ArrayList<String> extraResults =
1770 intent.getStringArrayListExtra(android.speech.RecognizerIntent.EXTRA_RESULTS);
1771 if (extraResults != null) {
1772 searchIntent.putStringArrayListExtra(
1773 android.speech.RecognizerIntent.EXTRA_RESULTS, extraResults);
1775 startActivityForResult(searchIntent, INTENT_REQUEST_SEARCH);
1784 public boolean onKeyUp(int keyCode, KeyEvent event) {
1785 if (keyCode == KeyEvent.KEYCODE_MENU) {
1786 if (mDrawerLayout.isDrawerOpen(mDrawer)) {
1787 mDrawerLayout.closeDrawer(Gravity.START);
1789 mDrawerLayout.openDrawer(Gravity.START);
1793 return super.onKeyUp(keyCode, event);
1797 public void onBackPressed() {
1798 if (mDrawerLayout.isDrawerOpen(Gravity.START)) {
1799 mDrawerLayout.closeDrawer(Gravity.START);
1802 if (checkBackAction()) {
1803 performHideEasyMode();
1806 if (mNeedsEasyMode && !isEasyModeVisible()) {
1807 performShowEasyMode();
1812 // An exit event has occurred, force the destroy the consoles
1817 * Method invoked when an action item is clicked.
1819 * @param view The button pushed
1821 public void onActionBarItemClick(View view) {
1822 switch (view.getId()) {
1823 //######################
1824 //Navigation Custom Title
1825 //######################
1826 case R.id.ab_configuration:
1827 //Show navigation view configuration toolbar
1828 getCurrentNavigationView().getCustomTitle().showConfigurationView();
1831 //Hide navigation view configuration toolbar
1832 getCurrentNavigationView().getCustomTitle().hideConfigurationView();
1835 //######################
1836 //Breadcrumb Actions
1837 //######################
1838 case R.id.ab_filesystem_info:
1839 //Show information of the filesystem
1840 MountPoint mp = getCurrentNavigationView().getBreadcrumb().getMountPointInfo();
1841 DiskUsage du = getCurrentNavigationView().getBreadcrumb().getDiskUsageInfo();
1842 showMountPointInfo(mp, du);
1845 //######################
1846 //Navigation view options
1847 //######################
1848 case R.id.ab_sort_mode:
1849 showSettingsPopUp(view,
1851 new FileManagerSettings[]{
1852 FileManagerSettings.SETTINGS_SORT_MODE}));
1854 case R.id.ab_layout_mode:
1855 showSettingsPopUp(view,
1857 new FileManagerSettings[]{
1858 FileManagerSettings.SETTINGS_LAYOUT_MODE}));
1860 case R.id.ab_view_options:
1861 // If we are in ChRooted mode, then don't show non-secure items
1862 if (this.mChRooted) {
1863 showSettingsPopUp(view,
1864 Arrays.asList(new FileManagerSettings[]{
1865 FileManagerSettings.SETTINGS_SHOW_DIRS_FIRST}));
1867 showSettingsPopUp(view,
1868 Arrays.asList(new FileManagerSettings[]{
1869 FileManagerSettings.SETTINGS_SHOW_DIRS_FIRST,
1870 FileManagerSettings.SETTINGS_SHOW_HIDDEN,
1871 FileManagerSettings.SETTINGS_SHOW_SYSTEM,
1872 FileManagerSettings.SETTINGS_SHOW_SYMLINKS}));
1877 //######################
1879 //######################
1880 case R.id.ab_selection_done:
1881 //Show information of the filesystem
1882 getCurrentNavigationView().onDeselectAll();
1885 //######################
1886 //Action Bar buttons
1887 //######################
1888 case R.id.ab_actions:
1889 openActionsDialog(getCurrentNavigationView().getCurrentDir(),
1893 case R.id.ab_search:
1907 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
1908 if (requestCode == INTENT_REQUEST_SETTINGS) {
1909 // reset bookmarks list to default as the user could changed the
1910 // root mode which changes the system bookmarks
1916 switch (requestCode) {
1917 case INTENT_REQUEST_SEARCH:
1918 if (resultCode == RESULT_OK) {
1920 Bundle bundle = data.getExtras();
1921 if (bundle != null) {
1922 FileSystemObject fso = (FileSystemObject) bundle.getSerializable(
1923 EXTRA_SEARCH_ENTRY_SELECTION);
1924 SearchInfoParcelable searchInfo =
1925 bundle.getParcelable(EXTRA_SEARCH_LAST_SEARCH_DATA);
1927 //Goto to new directory
1928 getCurrentNavigationView().open(fso, searchInfo);
1929 performHideEasyMode();
1932 } else if (resultCode == RESULT_CANCELED) {
1933 SearchInfoParcelable searchInfo =
1934 data.getParcelableExtra(EXTRA_SEARCH_LAST_SEARCH_DATA);
1935 if (searchInfo != null && searchInfo.isSuccessNavigation()) {
1936 //Navigate to previous history
1939 // I don't know is the search view was changed, so try to do a refresh
1940 // of the navigation view
1941 getCurrentNavigationView().refresh(true);
1944 // reset bookmarks list to default as the user could have set a
1945 // new bookmark in the search activity
1959 public void onNewHistory(HistoryNavigable navigable) {
1960 addHistoryToDrawer(this.mHistory.size(), navigable);
1961 //Recollect information about current status
1962 History history = new History(this.mHistory.size(), navigable);
1963 this.mHistory.add(history);
1970 public void onCheckHistory() {
1977 public void onRequestRefresh(Object o, boolean clearSelection) {
1978 if (o instanceof FileSystemObject) {
1979 // Refresh only the item
1980 this.getCurrentNavigationView().refresh((FileSystemObject)o);
1981 } else if (o == null) {
1983 getCurrentNavigationView().refresh();
1985 if (clearSelection) {
1986 this.getCurrentNavigationView().onDeselectAll();
1994 public void onRequestBookmarksRefresh() {
2002 public void onRequestRemove(Object o, boolean clearSelection) {
2003 if (o instanceof FileSystemObject) {
2005 this.getCurrentNavigationView().removeItem((FileSystemObject)o);
2007 //Remove from history
2008 removeFromHistory((FileSystemObject)o);
2010 onRequestRefresh(null, clearSelection);
2012 if (clearSelection) {
2013 this.getCurrentNavigationView().onDeselectAll();
2021 public void onNavigateTo(Object o) {
2026 public void onCancel(){
2034 public void onSelectionChanged(NavigationView navView, List<FileSystemObject> selectedItems) {
2035 this.mSelectionBar.setSelection(selectedItems);
2042 public void onRequestMenu(NavigationView navView, FileSystemObject item) {
2043 // Show the actions dialog
2044 openActionsDialog(item, false);
2048 * Method that shows a popup with a menu associated a {@link FileManagerSettings}.
2050 * @param anchor The action button that was pressed
2051 * @param settings The array of settings associated with the action button
2053 private void showSettingsPopUp(View anchor, List<FileManagerSettings> settings) {
2054 //Create the adapter
2055 final MenuSettingsAdapter adapter = new MenuSettingsAdapter(this, settings);
2057 //Create a show the popup menu
2058 final ListPopupWindow popup = DialogHelper.createListPopupWindow(this, adapter, anchor);
2059 popup.setOnItemClickListener(new OnItemClickListener() {
2061 public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
2062 FileManagerSettings setting =
2063 ((MenuSettingsAdapter)parent.getAdapter()).getSetting(position);
2064 final int value = ((MenuSettingsAdapter)parent.getAdapter()).getId(position);
2067 if (setting.compareTo(FileManagerSettings.SETTINGS_LAYOUT_MODE) == 0) {
2068 //Need to change the layout
2069 getCurrentNavigationView().changeViewMode(
2070 NavigationLayoutMode.fromId(value));
2073 if (setting.getDefaultValue() instanceof Enum<?>) {
2075 Preferences.savePreference(setting, new ObjectIdentifier() {
2077 public int getId() {
2084 Preferences.getSharedPreferences().
2087 ((Boolean)setting.getDefaultValue()).booleanValue());
2088 Preferences.savePreference(setting, Boolean.valueOf(!newval), false);
2090 getCurrentNavigationView().refresh();
2092 } catch (Exception e) {
2093 Log.e(TAG, "Error applying navigation option", e); //$NON-NLS-1$
2094 NavigationActivity.this.mHandler.post(new Runnable() {
2097 DialogHelper.showToast(
2098 NavigationActivity.this,
2099 R.string.msgs_settings_save_failure, Toast.LENGTH_SHORT);
2105 getCurrentNavigationView().getCustomTitle().restoreView();
2110 popup.setOnDismissListener(new PopupWindow.OnDismissListener() {
2112 public void onDismiss() {
2120 * Method that show the information of a filesystem mount point.
2122 * @param mp The mount point info
2123 * @param du The disk usage of the mount point
2125 private void showMountPointInfo(MountPoint mp, DiskUsage du) {
2126 //Has mount point info?
2128 //There is no information
2130 DialogHelper.createWarningDialog(
2132 R.string.filesystem_info_warning_title,
2133 R.string.filesystem_info_warning_msg);
2134 DialogHelper.delegateDialogShow(this, alert);
2138 //Show a the filesystem info dialog
2139 FilesystemInfoDialog dialog = new FilesystemInfoDialog(this, mp, du);
2140 dialog.setOnMountListener(new OnMountListener() {
2142 public void onRemount(MountPoint mountPoint) {
2143 //Update the statistics of breadcrumb, only if mount point is the same
2144 Breadcrumb breadcrumb = getCurrentNavigationView().getBreadcrumb();
2145 if (breadcrumb.getMountPointInfo().compareTo(mountPoint) == 0) {
2146 breadcrumb.updateMountPointInfo();
2148 if (mountPoint.isSecure()) {
2149 // Secure mountpoints only can be unmount, so we need to move the navigation
2150 // to a secure storage (do not add to history)
2151 Intent intent = new Intent();
2152 intent.putExtra(EXTRA_ADD_TO_HISTORY, false);
2153 initNavigation(NavigationActivity.this.mCurrentNavigationView, false, intent);
2161 * Method that checks the action that must be realized when the
2162 * back button is pushed.
2164 * @return boolean Indicates if the action must be intercepted
2166 private boolean checkBackAction() {
2167 // We need a basic structure to check this
2168 if (getCurrentNavigationView() == null) return false;
2170 if (mSearchView.getVisibility() == View.VISIBLE) {
2174 //Check if the configuration view is showing. In this case back
2175 //action must be "close configuration"
2176 if (getCurrentNavigationView().getCustomTitle().isConfigurationViewShowing()) {
2177 getCurrentNavigationView().getCustomTitle().restoreView();
2181 //Do back operation over the navigation history
2182 boolean flag = this.mExitFlag;
2184 this.mExitFlag = !back();
2186 // Retrieve if the exit status timeout has expired
2187 long now = System.currentTimeMillis();
2188 boolean timeout = (this.mExitBackTimeout == -1 ||
2189 (now - this.mExitBackTimeout) > RELEASE_EXIT_CHECK_TIMEOUT);
2191 //Check if there no history and if the user was advised in the last back action
2192 if (this.mExitFlag && (this.mExitFlag != flag || timeout)) {
2193 //Communicate the user that the next time the application will be closed
2194 this.mExitBackTimeout = System.currentTimeMillis();
2195 DialogHelper.showToast(this, R.string.msgs_push_again_to_exit, Toast.LENGTH_SHORT);
2196 if (mNeedsEasyMode) {
2197 return isEasyModeVisible();
2203 //Back action not applied
2204 return !this.mExitFlag;
2208 public void startActivity(Intent intent) {
2209 // check if search intent
2210 if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
2211 intent.putExtra(SearchActivity.EXTRA_SEARCH_DIRECTORY,
2212 getCurrentNavigationView().getCurrentDir());
2215 super.startActivity(intent);
2219 * Method that returns the history size.
2221 private void clearHistory() {
2222 this.mHistory.clear();
2223 mDrawerHistory.removeAllViews();
2224 mDrawerHistoryEmpty.setVisibility(View.VISIBLE);
2228 * Method that navigates to the passed history reference.
2230 * @param history The history reference
2231 * @return boolean A problem occurs while navigate
2233 public synchronized boolean navigateToHistory(History history) {
2236 History realHistory = this.mHistory.get(history.getPosition());
2238 //Navigate to item. Check what kind of history is
2239 if (realHistory.getItem() instanceof NavigationViewInfoParcelable) {
2241 NavigationViewInfoParcelable info =
2242 (NavigationViewInfoParcelable)realHistory.getItem();
2243 int viewId = info.getId();
2244 NavigationView view = getNavigationView(viewId);
2245 // Selected items must not be restored from on history navigation
2246 info.setSelectedFiles(view.getSelectedFiles());
2247 if (!view.onRestoreState(info)) {
2251 } else if (realHistory.getItem() instanceof SearchInfoParcelable) {
2252 //Search (open search with the search results)
2253 SearchInfoParcelable info = (SearchInfoParcelable)realHistory.getItem();
2254 Intent searchIntent = new Intent(this, SearchActivity.class);
2255 searchIntent.setAction(SearchActivity.ACTION_RESTORE);
2256 searchIntent.putExtra(SearchActivity.EXTRA_SEARCH_RESTORE, (Parcelable)info);
2257 startActivityForResult(searchIntent, INTENT_REQUEST_SEARCH);
2259 //The type is unknown
2260 throw new IllegalArgumentException("Unknown history type"); //$NON-NLS-1$
2263 //Remove the old history
2264 int cc = realHistory.getPosition();
2265 for (int i = this.mHistory.size() - 1; i >= cc; i--) {
2266 this.mHistory.remove(i);
2267 mDrawerHistory.removeViewAt(0);
2270 if (mDrawerHistory.getChildCount() == 0) {
2271 mDrawerHistoryEmpty.setVisibility(View.VISIBLE);
2275 boolean clearHistory = mHistoryTab.isSelected() && mHistory.size() > 0;
2276 mClearHistory.setVisibility(clearHistory ? View.VISIBLE : View.GONE);
2279 } catch (Throwable ex) {
2280 if (history != null) {
2282 String.format("Failed to navigate to history %d: %s", //$NON-NLS-1$
2283 Integer.valueOf(history.getPosition()),
2284 history.getItem().getTitle()), ex);
2287 String.format("Failed to navigate to history: null", ex)); //$NON-NLS-1$
2289 this.mHandler.post(new Runnable() {
2292 DialogHelper.showToast(
2293 NavigationActivity.this,
2294 R.string.msgs_history_unknown, Toast.LENGTH_LONG);
2298 //Not change directory
2304 * Method that request a back action over the navigation history.
2306 * @return boolean If a back action was applied
2308 public boolean back() {
2309 // Check that has valid history
2310 while (this.mHistory.size() > 0) {
2311 History h = this.mHistory.get(this.mHistory.size() - 1);
2312 if (h.getItem() instanceof NavigationViewInfoParcelable) {
2313 // Verify that the path exists
2314 String path = ((NavigationViewInfoParcelable)h.getItem()).getCurrentDir();
2317 FileSystemObject info = CommandHelper.getFileInfo(this, path, null);
2321 this.mHistory.remove(this.mHistory.size() - 1);
2322 } catch (Exception e) {
2323 ExceptionUtil.translateException(this, e, true, false);
2324 this.mHistory.remove(this.mHistory.size() - 1);
2331 //Navigate to history
2332 if (this.mHistory.size() > 0) {
2333 return navigateToHistory(this.mHistory.get(this.mHistory.size() - 1));
2337 mClearHistory.setVisibility(View.GONE);
2342 * Method that opens the actions dialog
2344 * @param item The path or the {@link FileSystemObject}
2345 * @param global If the menu to display is the one with global actions
2347 private void openActionsDialog(Object item, boolean global) {
2348 // Resolve the full path
2349 String path = String.valueOf(item);
2350 if (item instanceof FileSystemObject) {
2351 path = ((FileSystemObject)item).getFullPath();
2354 // Prior to show the dialog, refresh the item reference
2355 FileSystemObject fso = null;
2357 fso = CommandHelper.getFileInfo(this, path, false, null);
2359 throw new NoSuchFileOrDirectory(path);
2362 } catch (Exception e) {
2364 ExceptionUtil.translateException(this, e);
2366 // Remove the object
2367 if (e instanceof FileNotFoundException || e instanceof NoSuchFileOrDirectory) {
2368 // If have a FileSystemObject reference then there is no need to search
2369 // the path (less resources used)
2370 if (item instanceof FileSystemObject) {
2371 getCurrentNavigationView().removeItem((FileSystemObject)item);
2373 getCurrentNavigationView().removeItem((String)item);
2380 ActionsDialog dialog = new ActionsDialog(this, this, fso, global, false);
2381 dialog.setOnRequestRefreshListener(this);
2382 dialog.setOnSelectionListener(getCurrentNavigationView());
2387 * Method that opens the search view.
2392 mSearchView.setVisibility(View.VISIBLE);
2393 mSearchView.onActionViewExpanded();
2394 mCustomTitleView.setVisibility(View.GONE);
2397 void closeSearch() {
2398 mSearchView.setVisibility(View.GONE);
2399 mSearchView.onActionViewCollapsed();
2400 mCustomTitleView.setVisibility(View.VISIBLE);
2404 * Method that opens the settings activity.
2408 void openSettings() {
2409 Intent settingsIntent = new Intent(NavigationActivity.this,
2410 SettingsPreferences.class);
2411 startActivityForResult(settingsIntent, INTENT_REQUEST_SETTINGS);
2415 * Method that remove the {@link FileSystemObject} from the history
2417 private void removeFromHistory(FileSystemObject fso) {
2418 if (this.mHistory != null) {
2419 int cc = this.mHistory.size() - 1;
2420 for (int i = cc; i >= 0 ; i--) {
2421 History history = this.mHistory.get(i);
2422 if (history.getItem() instanceof NavigationViewInfoParcelable) {
2423 String p0 = fso.getFullPath();
2424 String p1 = ((NavigationViewInfoParcelable) history.getItem()).getCurrentDir();
2425 if (p0.compareTo(p1) == 0) {
2426 this.mHistory.remove(i);
2427 mDrawerHistory.removeViewAt(mDrawerHistory.getChildCount() - i - 1);
2428 mDrawerHistoryEmpty.setVisibility(
2429 mDrawerHistory.getChildCount() == 0 ? View.VISIBLE : View.GONE);
2430 updateHistoryPositions();
2438 * Update the history positions after one of the history is removed from drawer
2440 private void updateHistoryPositions() {
2441 int cc = this.mHistory.size() - 1;
2442 for (int i = 0; i <= cc ; i++) {
2443 History history = this.mHistory.get(i);
2444 history.setPosition(i + 1);
2449 * Method that ask the user to change the access mode prior to crash.
2453 //Show a dialog asking the user
2454 AlertDialog dialog =
2455 DialogHelper.createYesNoDialog(
2457 R.string.msgs_change_to_prompt_access_mode_title,
2458 R.string.msgs_change_to_prompt_access_mode_msg,
2459 new DialogInterface.OnClickListener() {
2461 public void onClick(DialogInterface alertDialog, int which) {
2462 if (which == DialogInterface.BUTTON_NEGATIVE) {
2463 // We don't have any console
2464 // Show exception and exit
2465 DialogHelper.showToast(
2466 NavigationActivity.this,
2467 R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
2472 // Ok. Now try to change to prompt mode. Any crash
2473 // here is a fatal error. We won't have any console to operate.
2476 ConsoleBuilder.changeToNonPrivilegedConsole(NavigationActivity.this);
2479 Preferences.savePreference(
2480 FileManagerSettings.SETTINGS_ACCESS_MODE,
2481 AccessMode.PROMPT, true);
2483 } catch (Exception e) {
2484 // Displays an exception and exit
2485 Log.e(TAG, getString(R.string.msgs_cant_create_console), e);
2486 DialogHelper.showToast(
2487 NavigationActivity.this,
2488 R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
2493 DialogHelper.delegateDialogShow(this, dialog);
2497 * Method that creates a ChRooted environment, protecting the user to break anything in
2501 void createChRooted() {
2502 // If we are in a ChRooted mode, then do nothing
2503 if (this.mChRooted) return;
2504 this.mChRooted = true;
2506 int cc = this.mNavigationViews.length;
2507 for (int i = 0; i < cc; i++) {
2508 this.mNavigationViews[i].createChRooted();
2511 // Remove the selection
2512 cc = this.mNavigationViews.length;
2513 for (int i = 0; i < cc; i++) {
2514 getCurrentNavigationView().onDeselectAll();
2517 // Remove the history (don't allow to access to previous data)
2522 * Method that exits from a ChRooted
2525 void exitChRooted() {
2526 // If we aren't in a ChRooted mode, then do nothing
2527 if (!this.mChRooted) return;
2528 this.mChRooted = false;
2530 int cc = this.mNavigationViews.length;
2531 for (int i = 0; i < cc; i++) {
2532 this.mNavigationViews[i].exitChRooted();
2537 * Method called when a controlled exit is required
2541 // Recycle the navigation views
2542 int cc = this.mNavigationViews.length;
2543 for (int i = 0; i < cc; i++) {
2544 this.mNavigationViews[i].recycle();
2547 FileManagerApplication.destroyBackgroundConsole();
2548 } catch (Throwable ex) {
2552 ConsoleBuilder.destroyConsole();
2553 } catch (Throwable ex) {
2560 * Method that reconfigures the layout for better fit in portrait and landscape modes
2562 private void onLayoutChanged() {
2563 Theme theme = ThemeManager.getCurrentTheme(this);
2564 boolean drawerOpen = mDrawerLayout.isDrawerOpen(Gravity.START);
2566 // Apply only when the orientation was changed
2567 int orientation = getResources().getConfiguration().orientation;
2568 if (this.mOrientation == orientation) return;
2569 this.mOrientation = orientation;
2571 // imitate a closed drawer while layout is rebuilt to avoid NullPointerException
2573 mDrawerLayout.closeDrawer(Gravity.START);
2576 if (this.mOrientation == Configuration.ORIENTATION_LANDSCAPE) {
2578 ViewGroup statusBar = (ViewGroup)findViewById(R.id.navigation_statusbar);
2579 if (statusBar.getParent() != null) {
2580 ViewGroup parent = (ViewGroup) statusBar.getParent();
2581 parent.removeView(statusBar);
2584 // Calculate the action button size (all the buttons must fit in the title bar)
2585 int bw = (int)getResources().getDimension(R.dimen.default_buttom_width);
2586 int abw = this.mActionBar.getChildCount() * bw;
2588 int cc = statusBar.getChildCount();
2589 for (int i = 0; i < cc; i++) {
2590 View child = statusBar.getChildAt(i);
2591 if (child instanceof ButtonItem) {
2595 // Currently there isn't overflow menu
2596 int w = abw + rbw - bw;
2598 // Add to the new location
2599 ViewGroup newParent = (ViewGroup)findViewById(R.id.navigation_title_landscape_holder);
2600 LinearLayout.LayoutParams params =
2601 new LinearLayout.LayoutParams(
2603 ViewGroup.LayoutParams.MATCH_PARENT);
2604 statusBar.setLayoutParams(params);
2605 newParent.addView(statusBar);
2608 theme.setBackgroundDrawable(this, statusBar, "titlebar_drawable"); //$NON-NLS-1$
2611 View holder = findViewById(R.id.navigation_statusbar_portrait_holder);
2612 holder.setVisibility(View.GONE);
2616 ViewGroup statusBar = (ViewGroup)findViewById(R.id.navigation_statusbar);
2617 if (statusBar.getParent() != null) {
2618 ViewGroup parent = (ViewGroup) statusBar.getParent();
2619 parent.removeView(statusBar);
2622 // Add to the new location
2623 ViewGroup newParent = (ViewGroup)findViewById(
2624 R.id.navigation_statusbar_portrait_holder);
2625 LinearLayout.LayoutParams params =
2626 new LinearLayout.LayoutParams(
2627 ViewGroup.LayoutParams.MATCH_PARENT,
2628 ViewGroup.LayoutParams.MATCH_PARENT);
2629 statusBar.setLayoutParams(params);
2630 newParent.addView(statusBar);
2633 theme.setBackgroundDrawable(this, statusBar, "statusbar_drawable"); //$NON-NLS-1$
2636 newParent.setVisibility(View.VISIBLE);
2639 // if drawer was open, imitate reopening
2641 mDrawerToggle.onDrawerOpened(mDrawer);
2646 * Method that removes all the history items that refers to virtual unmounted filesystems
2648 private void removeUnmountedHistory() {
2649 int cc = mHistory.size() - 1;
2650 for (int i = cc; i >= 0; i--) {
2651 History history = mHistory.get(i);
2652 if (history.getItem() instanceof NavigationViewInfoParcelable) {
2653 NavigationViewInfoParcelable navigableInfo =
2654 ((NavigationViewInfoParcelable) history.getItem());
2655 VirtualMountPointConsole vc =
2656 VirtualMountPointConsole.getVirtualConsoleForPath(
2657 navigableInfo.getCurrentDir());
2658 if (vc != null && !vc.isMounted()) {
2660 mDrawerHistory.removeViewAt(mDrawerHistory.getChildCount() - i - 1);
2664 mDrawerHistoryEmpty.setVisibility(
2665 mDrawerHistory.getChildCount() == 0 ? View.VISIBLE : View.GONE);
2666 updateHistoryPositions();
2670 * Method that removes all the selection items that refers to virtual unmounted filesystems
2672 private void removeUnmountedSelection() {
2673 for (NavigationView view : mNavigationViews) {
2674 view.removeUnmountedSelection();
2676 mSelectionBar.setSelection(getNavigationView(mCurrentNavigationView).getSelectedFiles());
2680 * Method that applies the current theme to the activity
2684 int orientation = getResources().getConfiguration().orientation;
2685 Theme theme = ThemeManager.getCurrentTheme(this);
2686 theme.setBaseThemeNoActionBar(this);
2689 // imitate a closed drawer while layout is rebuilt to avoid NullPointerException
2690 boolean drawerOpen = mDrawerLayout.isDrawerOpen(Gravity.START);
2692 mDrawerLayout.closeDrawer(Gravity.START);
2696 View v = findViewById(R.id.navigation_layout);
2697 theme.setBackgroundDrawable(this, v, "background_drawable"); //$NON-NLS-1$
2700 theme.setTitlebarDrawable(this, getActionBar(), "titlebar_drawable"); //$NON-NLS-1$
2702 // Hackery to theme search view
2703 mSearchView = (SearchView) findViewById(R.id.navigation_search_bar);
2704 int searchPlateId = mSearchView.getContext().getResources()
2705 .getIdentifier("android:id/search_plate", null, null);
2706 View searchPlate = mSearchView.findViewById(searchPlateId);
2707 if (searchPlate != null) {
2708 int searchTextId = searchPlate.getContext().getResources()
2709 .getIdentifier("android:id/search_src_text", null, null);
2710 TextView searchText = (TextView) searchPlate.findViewById(searchTextId);
2711 if (searchText != null) {
2712 searchText.setTextColor(Color.WHITE);
2713 searchText.setHintTextColor(Color.WHITE);
2716 int magId = getResources().getIdentifier("android:id/search_mag_icon", null, null);
2717 ImageView magImage = (ImageView) mSearchView.findViewById(magId);
2718 if (magImage != null) {
2719 magImage.setLayoutParams(new LinearLayout.LayoutParams(0, 0));
2723 SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
2724 mSearchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
2725 mSearchView.setIconifiedByDefault(false);
2727 mCustomTitleView = (NavigationCustomTitleView) findViewById(R.id.navigation_title_flipper);
2728 mCustomTitleView.setVisibility(View.VISIBLE);
2731 v = findViewById(R.id.navigation_statusbar);
2732 if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
2733 theme.setBackgroundDrawable(this, v, "titlebar_drawable"); //$NON-NLS-1$
2735 theme.setBackgroundDrawable(this, v, "statusbar_drawable"); //$NON-NLS-1$
2737 v = findViewById(R.id.ab_overflow);
2738 theme.setImageDrawable(this, (ImageView)v, "ab_overflow_drawable"); //$NON-NLS-1$
2739 v = findViewById(R.id.ab_actions);
2740 theme.setImageDrawable(this, (ImageView)v, "ab_actions_drawable"); //$NON-NLS-1$
2741 v = findViewById(R.id.ab_search);
2742 theme.setImageDrawable(this, (ImageView)v, "ab_search_drawable"); //$NON-NLS-1$
2745 v = findViewById(R.id.ab_configuration);
2746 theme.setImageDrawable(this, (ImageView)v, "expander_open_drawable"); //$NON-NLS-1$
2747 v = findViewById(R.id.ab_close);
2748 theme.setImageDrawable(this, (ImageView)v, "expander_close_drawable"); //$NON-NLS-1$
2749 v = findViewById(R.id.ab_sort_mode);
2750 theme.setImageDrawable(this, (ImageView)v, "ab_sort_mode_drawable"); //$NON-NLS-1$
2751 v = findViewById(R.id.ab_layout_mode);
2752 theme.setImageDrawable(this, (ImageView)v, "ab_layout_mode_drawable"); //$NON-NLS-1$
2753 v = findViewById(R.id.ab_view_options);
2754 theme.setImageDrawable(this, (ImageView)v, "ab_view_options_drawable"); //$NON-NLS-1$
2757 v = findViewById(R.id.navigation_selectionbar);
2758 theme.setBackgroundDrawable(this, v, "selectionbar_drawable"); //$NON-NLS-1$
2759 v = findViewById(R.id.ab_selection_done);
2760 theme.setImageDrawable(this, (ImageView)v, "ab_selection_done_drawable"); //$NON-NLS-1$
2761 v = findViewById(R.id.navigation_status_selection_label);
2762 theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2764 // - Navigation drawer
2765 v = findViewById(R.id.history_empty);
2766 theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2768 for (int i=0; i<mDrawerHistory.getChildCount(); i++) {
2769 View item = mDrawerHistory.getChildAt(i);
2771 v = item.findViewById(R.id.history_item_name);
2772 theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2773 v = item.findViewById(R.id.history_item_directory);
2774 theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2778 int cc = this.mNavigationViews.length;
2779 for (int i = 0; i < cc; i++) {
2780 getNavigationView(i).applyTheme();
2783 // if drawer was open, imitate reopening
2785 mDrawerToggle.onDrawerOpened(mDrawer);
2790 * Method that applies the current theme to the tab host
2792 private void applyTabTheme() {
2794 Theme theme = ThemeManager.getCurrentTheme(this);
2796 View v = findViewById(R.id.drawer);
2797 theme.setBackgroundDrawable(this, v, "background_drawable"); //$NON-NLS-1$
2799 v = findViewById(R.id.drawer_bookmarks_tab);
2800 theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2801 v = findViewById(R.id.drawer_history_tab);
2802 theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2804 v = findViewById(R.id.ab_settings);
2805 theme.setImageDrawable(this, (ButtonItem) v, "ab_settings_drawable"); //$NON-NLS-1$
2806 v = findViewById(R.id.ab_clear_history);
2807 theme.setImageDrawable(this, (ButtonItem) v, "ab_delete_drawable"); //$NON-NLS-1$
2810 public void updateActiveDialog(Dialog dialog) {
2811 mActiveDialog = dialog;