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.widget.AdapterView;
54 import android.widget.AdapterView.OnItemClickListener;
55 import android.widget.ImageButton;
56 import android.widget.ImageView;
57 import android.widget.LinearLayout;
58 import android.widget.ListPopupWindow;
59 import android.widget.ListView;
60 import android.widget.PopupWindow;
61 import android.widget.SearchView;
62 import android.widget.TextView;
63 import android.widget.Toast;
64 import android.widget.Toolbar;
65 import android.widget.ArrayAdapter;
67 import com.android.internal.util.XmlUtils;
68 import com.cyanogenmod.filemanager.FileManagerApplication;
69 import com.cyanogenmod.filemanager.R;
70 import com.cyanogenmod.filemanager.activities.preferences.SettingsPreferences;
71 import com.cyanogenmod.filemanager.adapters.MenuSettingsAdapter;
72 import com.cyanogenmod.filemanager.console.Console;
73 import com.cyanogenmod.filemanager.console.ConsoleAllocException;
74 import com.cyanogenmod.filemanager.console.ConsoleBuilder;
75 import com.cyanogenmod.filemanager.console.InsufficientPermissionsException;
76 import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory;
77 import com.cyanogenmod.filemanager.console.VirtualConsole;
78 import com.cyanogenmod.filemanager.console.VirtualMountPointConsole;
79 import com.cyanogenmod.filemanager.console.secure.SecureConsole;
80 import com.cyanogenmod.filemanager.listeners.OnHistoryListener;
81 import com.cyanogenmod.filemanager.listeners.OnRequestRefreshListener;
82 import com.cyanogenmod.filemanager.model.Bookmark;
83 import com.cyanogenmod.filemanager.model.DiskUsage;
84 import com.cyanogenmod.filemanager.model.FileSystemObject;
85 import com.cyanogenmod.filemanager.model.History;
86 import com.cyanogenmod.filemanager.model.MountPoint;
87 import com.cyanogenmod.filemanager.model.Bookmark.BOOKMARK_TYPE;
88 import com.cyanogenmod.filemanager.parcelables.HistoryNavigable;
89 import com.cyanogenmod.filemanager.parcelables.NavigationViewInfoParcelable;
90 import com.cyanogenmod.filemanager.parcelables.SearchInfoParcelable;
91 import com.cyanogenmod.filemanager.preferences.AccessMode;
92 import com.cyanogenmod.filemanager.preferences.Bookmarks;
93 import com.cyanogenmod.filemanager.preferences.FileManagerSettings;
94 import com.cyanogenmod.filemanager.preferences.NavigationLayoutMode;
95 import com.cyanogenmod.filemanager.preferences.ObjectIdentifier;
96 import com.cyanogenmod.filemanager.preferences.Preferences;
97 import com.cyanogenmod.filemanager.ui.IconHolder;
98 import com.cyanogenmod.filemanager.ui.ThemeManager;
99 import com.cyanogenmod.filemanager.ui.ThemeManager.Theme;
100 import com.cyanogenmod.filemanager.ui.dialogs.ActionsDialog;
101 import com.cyanogenmod.filemanager.ui.dialogs.FilesystemInfoDialog;
102 import com.cyanogenmod.filemanager.ui.dialogs.InitialDirectoryDialog;
103 import com.cyanogenmod.filemanager.ui.dialogs.FilesystemInfoDialog.OnMountListener;
104 import com.cyanogenmod.filemanager.ui.widgets.Breadcrumb;
105 import com.cyanogenmod.filemanager.ui.widgets.ButtonItem;
106 import com.cyanogenmod.filemanager.ui.widgets.NavigationCustomTitleView;
107 import com.cyanogenmod.filemanager.ui.widgets.NavigationView;
108 import com.cyanogenmod.filemanager.ui.widgets.NavigationView.OnNavigationRequestMenuListener;
109 import com.cyanogenmod.filemanager.ui.widgets.NavigationView.OnNavigationSelectionChangedListener;
110 import com.cyanogenmod.filemanager.ui.widgets.SelectionView;
111 import com.cyanogenmod.filemanager.util.AndroidHelper;
112 import com.cyanogenmod.filemanager.util.BookmarksHelper;
113 import com.cyanogenmod.filemanager.util.CommandHelper;
114 import com.cyanogenmod.filemanager.util.DialogHelper;
115 import com.cyanogenmod.filemanager.util.ExceptionUtil;
116 import com.cyanogenmod.filemanager.util.ExceptionUtil.OnRelaunchCommandResult;
117 import com.cyanogenmod.filemanager.util.FileHelper;
118 import com.cyanogenmod.filemanager.util.MimeTypeHelper.MimeTypeCategory;
119 import com.cyanogenmod.filemanager.util.StorageHelper;
122 import java.io.FileNotFoundException;
123 import java.util.ArrayList;
124 import java.util.Arrays;
125 import java.util.HashMap;
126 import java.util.List;
127 import java.util.Locale;
128 import java.util.Map;
130 import static com.cyanogenmod.filemanager.util.MimeTypeHelper.MimeTypeCategory.*;
133 * The main navigation activity. This activity is the center of the application.
134 * From this the user can navigate, search, make actions.<br/>
135 * This activity is singleTop, so when it is displayed no other activities exists in
137 * This cause an issue with the saved instance of this class, because if another activity
138 * is displayed, and the process is killed, NavigationActivity is started and the saved
139 * instance gets corrupted.<br/>
140 * For this reason the methods {link {@link Activity#onSaveInstanceState(Bundle)} and
141 * {@link Activity#onRestoreInstanceState(Bundle)} are not implemented, and every time
142 * the app is killed, is restarted from his initial state.
144 public class NavigationActivity extends Activity
145 implements OnHistoryListener, OnRequestRefreshListener,
146 OnNavigationRequestMenuListener, OnNavigationSelectionChangedListener {
148 private static final String TAG = "NavigationActivity"; //$NON-NLS-1$
150 private static boolean DEBUG = false;
152 // Bookmark list XML tags
153 private static final String TAG_BOOKMARKS = "Bookmarks"; //$NON-NLS-1$
154 private static final String TAG_BOOKMARK = "bookmark"; //$NON-NLS-1$
156 private static final String STR_USB = "usb"; // $NON-NLS-1$
159 * Intent code for request a search.
161 public static final int INTENT_REQUEST_SEARCH = 10001;
164 * Intent code for request a search.
166 public static final int INTENT_REQUEST_SETTINGS = 20001;
169 * Constant for extra information about selected search entry.
171 public static final String EXTRA_SEARCH_ENTRY_SELECTION =
172 "extra_search_entry_selection"; //$NON-NLS-1$
175 * Constant for extra information about last search data.
177 public static final String EXTRA_SEARCH_LAST_SEARCH_DATA =
178 "extra_search_last_search_data"; //$NON-NLS-1$
181 * Constant for extra information for request a navigation to the passed path.
183 public static final String EXTRA_NAVIGATE_TO =
184 "extra_navigate_to"; //$NON-NLS-1$
187 * Constant for extra information for request to add navigation to the history
189 public static final String EXTRA_ADD_TO_HISTORY =
190 "extra_add_to_history"; //$NON-NLS-1$
192 // The timeout needed to reset the exit status for back button
193 // After this time user need to tap 2 times the back button to
194 // exit, and the toast is shown again after the first tap.
195 private static final int RELEASE_EXIT_CHECK_TIMEOUT = 3500;
198 private Toolbar mToolBar;
199 private SearchView mSearchView;
200 private NavigationCustomTitleView mCustomTitleView;
202 private final BroadcastReceiver mNotificationReceiver = new BroadcastReceiver() {
204 public void onReceive(Context context, Intent intent) {
205 if (intent != null) {
206 if (intent.getAction().compareTo(FileManagerSettings.INTENT_SETTING_CHANGED) == 0) {
207 // The settings has changed
208 String key = intent.getStringExtra(FileManagerSettings.EXTRA_SETTING_CHANGED_KEY);
210 // Disk usage warning level
211 if (key.compareTo(FileManagerSettings.
212 SETTINGS_DISK_USAGE_WARNING_LEVEL.getId()) == 0) {
214 // Set the free disk space warning level of the breadcrumb widget
215 Breadcrumb breadcrumb = getCurrentNavigationView().getBreadcrumb();
216 String fds = Preferences.getSharedPreferences().getString(
217 FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getId(),
218 (String)FileManagerSettings.
219 SETTINGS_DISK_USAGE_WARNING_LEVEL.getDefaultValue());
220 breadcrumb.setFreeDiskSpaceWarningLevel(Integer.parseInt(fds));
221 breadcrumb.updateMountPointInfo();
225 // Case sensitive sort
226 if (key.compareTo(FileManagerSettings.
227 SETTINGS_CASE_SENSITIVE_SORT.getId()) == 0) {
228 getCurrentNavigationView().refresh();
233 if (key.compareTo(FileManagerSettings.
234 SETTINGS_DISPLAY_THUMBS.getId()) == 0) {
235 // Clean the icon cache applying the current theme
241 if (key.compareTo(FileManagerSettings.
242 SETTINGS_USE_FLINGER.getId()) == 0) {
244 Preferences.getSharedPreferences().getBoolean(
245 FileManagerSettings.SETTINGS_USE_FLINGER.getId(),
246 ((Boolean)FileManagerSettings.
247 SETTINGS_USE_FLINGER.
248 getDefaultValue()).booleanValue());
249 getCurrentNavigationView().setUseFlinger(useFlinger);
254 if (key.compareTo(FileManagerSettings.
255 SETTINGS_ACCESS_MODE.getId()) == 0) {
256 // Is it necessary to create or exit of the ChRooted?
258 FileManagerApplication.
259 getAccessMode().compareTo(AccessMode.SAFE) == 0;
260 if (chRooted != NavigationActivity.this.mChRooted) {
270 if (key.compareTo(FileManagerSettings.
271 SETTINGS_RESTRICT_SECONDARY_USERS_ACCESS.getId()) == 0) {
272 if (AndroidHelper.isSecondaryUser(context)) {
274 Preferences.savePreference(
275 FileManagerSettings.SETTINGS_ACCESS_MODE,
276 AccessMode.SAFE, true);
277 } catch (Throwable ex) {
278 Log.w(TAG, "can't save console preference", ex); //$NON-NLS-1$
280 ConsoleBuilder.changeToNonPrivilegedConsole(context);
285 // Filetime format mode
286 if (key.compareTo(FileManagerSettings.
287 SETTINGS_FILETIME_FORMAT_MODE.getId()) == 0) {
289 synchronized (FileHelper.DATETIME_SYNC) {
290 FileHelper.sReloadDateTimeFormats = true;
291 NavigationActivity.this.getCurrentNavigationView().refresh();
296 } else if (intent.getAction().compareTo(
297 FileManagerSettings.INTENT_FILE_CHANGED) == 0) {
298 // Retrieve the file that was changed
300 intent.getStringExtra(FileManagerSettings.EXTRA_FILE_CHANGED_KEY);
302 FileSystemObject fso = CommandHelper.getFileInfo(context, file, null);
304 getCurrentNavigationView().refresh(fso);
306 } catch (Exception e) {
307 ExceptionUtil.translateException(context, e, true, false);
310 } else if (intent.getAction().compareTo(
311 FileManagerSettings.INTENT_THEME_CHANGED) == 0) {
314 } else if (intent.getAction().compareTo(Intent.ACTION_TIME_CHANGED) == 0 ||
315 intent.getAction().compareTo(Intent.ACTION_DATE_CHANGED) == 0 ||
316 intent.getAction().compareTo(Intent.ACTION_TIMEZONE_CHANGED) == 0 ||
317 intent.getAction().compareTo(Intent.ACTION_LOCALE_CHANGED) == 0) {
319 synchronized (FileHelper.DATETIME_SYNC) {
320 FileHelper.sReloadDateTimeFormats = true;
321 NavigationActivity.this.getCurrentNavigationView().refresh();
323 } else if (intent.getAction().compareTo(
324 FileManagerSettings.INTENT_MOUNT_STATUS_CHANGED) == 0 ||
325 intent.getAction().equals(Intent.ACTION_MEDIA_MOUNTED) ||
326 intent.getAction().equals(Intent.ACTION_MEDIA_UNMOUNTED)) {
327 onRequestBookmarksRefresh();
328 removeUnmountedHistory();
329 removeUnmountedSelection();
335 private OnClickListener mOnClickDrawerTabListener = new OnClickListener() {
337 public void onClick(View v) {
339 case R.id.drawer_bookmarks_tab:
340 if (!mBookmarksTab.isSelected()) {
341 mBookmarksTab.setSelected(true);
342 mHistoryTab.setSelected(false);
343 mBookmarksTab.setTextAppearance(
344 NavigationActivity.this, R.style.primary_text_appearance);
345 mHistoryTab.setTextAppearance(
346 NavigationActivity.this, R.style.secondary_text_appearance);
347 mHistoryLayout.setVisibility(View.GONE);
348 mBookmarksLayout.setVisibility(View.VISIBLE);
352 Preferences.savePreference(FileManagerSettings.USER_PREF_LAST_DRAWER_TAB,
353 Integer.valueOf(0), true);
354 } catch (Exception ex) {
355 Log.e(TAG, "Can't save last drawer tab", ex); //$NON-NLS-1$
358 mClearHistory.setVisibility(View.GONE);
361 case R.id.drawer_history_tab:
362 if (!mHistoryTab.isSelected()) {
363 mHistoryTab.setSelected(true);
364 mBookmarksTab.setSelected(false);
365 mHistoryTab.setTextAppearance(
366 NavigationActivity.this, R.style.primary_text_appearance);
367 mBookmarksTab.setTextAppearance(
368 NavigationActivity.this, R.style.secondary_text_appearance);
369 mBookmarksLayout.setVisibility(View.GONE);
370 mHistoryLayout.setVisibility(View.VISIBLE);
374 Preferences.savePreference(FileManagerSettings.USER_PREF_LAST_DRAWER_TAB,
375 Integer.valueOf(1), true);
376 } catch (Exception ex) {
377 Log.e(TAG, "Can't save last drawer tab", ex); //$NON-NLS-1$
380 mClearHistory.setVisibility(mHistory.size() > 0 ? View.VISIBLE : View.GONE);
389 private OnClickListener mOnClickDrawerActionBarListener = new OnClickListener() {
391 public void onClick(View v) {
393 case R.id.ab_settings:
394 mDrawerLayout.closeDrawer(Gravity.START);
397 case R.id.ab_clear_history:
399 mClearHistory.setVisibility(View.GONE);
407 static String MIME_TYPE_LOCALIZED_NAMES[];
411 static Map<MimeTypeCategory, Drawable> EASY_MODE_ICONS = new
412 HashMap<MimeTypeCategory, Drawable>();
417 NavigationView[] mNavigationViews;
421 ListView mEasyModeListView;
422 private List<History> mHistory;
424 private static final List<MimeTypeCategory> EASY_MODE_LIST = new ArrayList<MimeTypeCategory>() {
435 private ArrayAdapter<MimeTypeCategory> mEasyModeAdapter;
436 private View.OnClickListener mEasyModeItemClickListener = new View.OnClickListener() {
438 public void onClick(View view) {
439 Integer position = (Integer) view.getTag();
444 private int mCurrentNavigationView;
446 private ViewGroup mActionBar;
447 private SelectionView mSelectionBar;
449 private DrawerLayout mDrawerLayout;
450 private ViewGroup mDrawer;
451 private ActionBarDrawerToggle mDrawerToggle;
452 private LinearLayout mDrawerHistory;
453 private TextView mDrawerHistoryEmpty;
455 private TextView mBookmarksTab;
456 private TextView mHistoryTab;
457 private View mBookmarksLayout;
458 private View mHistoryLayout;
460 private ButtonItem mSettings;
461 private ButtonItem mClearHistory;
463 private List<Bookmark> mBookmarks;
464 private List<Bookmark> mSdBookmarks;
465 private LinearLayout mDrawerBookmarks;
467 private boolean mExitFlag = false;
468 private long mExitBackTimeout = -1;
470 private Dialog mActiveDialog = null;
472 private int mOrientation;
484 private AsyncTask<Void, Void, Boolean> mBookmarksTask;
490 protected void onCreate(Bundle state) {
493 Log.d(TAG, "NavigationActivity.onCreate"); //$NON-NLS-1$
496 // Register the broadcast receiver
497 IntentFilter filter = new IntentFilter();
498 filter.addAction(FileManagerSettings.INTENT_SETTING_CHANGED);
499 filter.addAction(FileManagerSettings.INTENT_FILE_CHANGED);
500 filter.addAction(FileManagerSettings.INTENT_THEME_CHANGED);
501 filter.addAction(Intent.ACTION_DATE_CHANGED);
502 filter.addAction(Intent.ACTION_TIME_CHANGED);
503 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
504 filter.addAction(Intent.ACTION_LOCALE_CHANGED);
505 filter.addAction(FileManagerSettings.INTENT_MOUNT_STATUS_CHANGED);
506 registerReceiver(this.mNotificationReceiver, filter);
508 // This filter needs the file data scheme, so it must be defined separately.
509 IntentFilter newFilter = new IntentFilter();
510 newFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
511 newFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
512 newFilter.addDataScheme(ContentResolver.SCHEME_FILE);
513 registerReceiver(mNotificationReceiver, newFilter);
515 // Set the theme before setContentView
516 Theme theme = ThemeManager.getCurrentTheme(this);
517 theme.setBaseThemeNoActionBar(this);
519 //Set the main layout of the activity
520 setContentView(R.layout.navigation);
522 //Initialize nfc adapter
523 NfcAdapter mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
524 if (mNfcAdapter != null) {
525 mNfcAdapter.setBeamPushUrisCallback(new NfcAdapter.CreateBeamUrisCallback() {
527 public Uri[] createBeamUris(NfcEvent event) {
528 List<FileSystemObject> selectedFiles =
529 getCurrentNavigationView().getSelectedFiles();
530 if (selectedFiles.size() > 0) {
531 List<Uri> fileUri = new ArrayList<Uri>();
532 for (FileSystemObject f : selectedFiles) {
533 //Beam ignores folders and system files
534 if (!FileHelper.isDirectory(f) && !FileHelper.isSystemFile(f)) {
535 fileUri.add(Uri.fromFile(new File(f.getFullPath())));
538 if (fileUri.size() > 0) {
539 return fileUri.toArray(new Uri[fileUri.size()]);
547 //Initialize activity
551 initNavigationViews();
553 // As we're using a Toolbar, we should retrieve it and set it
554 // to be our ActionBar
555 mToolBar = (Toolbar) findViewById(R.id.material_toolbar);
556 setActionBar(mToolBar);
558 //Initialize action bars
559 initTitleActionBar();
560 initStatusActionBar();
563 // Initialize navigation drawer
567 // Adjust layout (only when start on landscape mode)
568 int orientation = getResources().getConfiguration().orientation;
569 if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
572 this.mOrientation = orientation;
577 // Show welcome message
580 this.mHandler = new Handler();
581 this.mHandler.post(new Runnable() {
584 // Initialize console
587 //Initialize navigation
588 int cc = NavigationActivity.this.mNavigationViews.length;
589 for (int i = 0; i < cc; i++) {
590 initNavigation(i, false, getIntent());
593 //Check the intent action
594 checkIntent(getIntent());
598 MIME_TYPE_LOCALIZED_NAMES = MimeTypeCategory.getFriendlyLocalizedNames(NavigationActivity
601 EASY_MODE_ICONS.put(MimeTypeCategory.NONE, getResources().getDrawable(R.drawable
603 EASY_MODE_ICONS.put(MimeTypeCategory.IMAGE, getResources().getDrawable(R.drawable
605 EASY_MODE_ICONS.put(MimeTypeCategory.VIDEO, getResources().getDrawable(R.drawable
607 EASY_MODE_ICONS.put(MimeTypeCategory.AUDIO, getResources().getDrawable(R.drawable
609 EASY_MODE_ICONS.put(MimeTypeCategory.DOCUMENT, getResources().getDrawable(R.drawable
611 EASY_MODE_ICONS.put(MimeTypeCategory.APP, getResources().getDrawable(R.drawable
612 .ic_em_application));
615 super.onCreate(state);
619 protected void onResume() {
622 if (mSearchView.getVisibility() == View.VISIBLE) {
626 // Check restrictions
627 if (!FileManagerApplication.checkRestrictSecondaryUsersAccess(this, mChRooted)) {
631 // Check that the current dir is mounted (for virtual filesystems)
632 String curDir = mNavigationViews[mCurrentNavigationView].getCurrentDir();
633 if (curDir != null) {
634 VirtualMountPointConsole vc = VirtualMountPointConsole.getVirtualConsoleForPath(
635 mNavigationViews[mCurrentNavigationView].getCurrentDir());
636 if (vc != null && !vc.isMounted()) {
637 onRequestBookmarksRefresh();
638 removeUnmountedHistory();
639 removeUnmountedSelection();
641 Intent intent = new Intent();
642 intent.putExtra(EXTRA_ADD_TO_HISTORY, false);
643 initNavigation(NavigationActivity.this.mCurrentNavigationView, false, intent);
649 protected void onPostCreate(Bundle savedInstanceState) {
650 super.onPostCreate(savedInstanceState);
651 // Sync the toggle state after onRestoreInstanceState has occurred.
652 mDrawerToggle.syncState();
659 protected void onNewIntent(Intent intent) {
660 //Initialize navigation
661 initNavigation(this.mCurrentNavigationView, true, intent);
663 //Check the intent action
671 public void onConfigurationChanged(Configuration newConfig) {
672 super.onConfigurationChanged(newConfig);
674 mDrawerToggle.onConfigurationChanged(newConfig);
681 public boolean onOptionsItemSelected(MenuItem item) {
682 if (mDrawerToggle.onOptionsItemSelected(item)) {
685 return super.onOptionsItemSelected(item);
692 protected void onDestroy() {
694 Log.d(TAG, "NavigationActivity.onDestroy"); //$NON-NLS-1$
697 if (mActiveDialog != null && mActiveDialog.isShowing()) {
698 mActiveDialog.dismiss();
701 // Unregister the receiver
703 unregisterReceiver(this.mNotificationReceiver);
704 } catch (Throwable ex) {
708 //All destroy. Continue
713 * Method that returns the current navigation view.
715 * @return NavigationView The current navigation view
717 public NavigationView getCurrentNavigationView() {
718 return getNavigationView(this.mCurrentNavigationView);
722 * Method that returns the current navigation view.
724 * @param viewId The view to return
725 * @return NavigationView The current navigation view
727 public NavigationView getNavigationView(int viewId) {
728 if (this.mNavigationViews == null) return null;
729 return this.mNavigationViews[viewId];
733 * Method that initializes the activity.
735 private void init() {
736 this.mHistory = new ArrayList<History>();
737 this.mChRooted = FileManagerApplication.getAccessMode().compareTo(AccessMode.SAFE) == 0;
741 * Method that displays a welcome message the first time the user
742 * access the application
744 private void showWelcomeMsg() {
745 boolean firstUse = Preferences.getSharedPreferences().getBoolean(
746 FileManagerSettings.SETTINGS_FIRST_USE.getId(),
747 ((Boolean)FileManagerSettings.SETTINGS_FIRST_USE.getDefaultValue()).booleanValue());
749 //Display the welcome message?
750 if (firstUse && FileManagerApplication.hasShellCommands()) {
751 // open navigation drawer to show user that it exists
752 mDrawerLayout.openDrawer(Gravity.START);
754 AlertDialog dialog = DialogHelper.createAlertDialog(this,
755 R.mipmap.ic_launcher_filemanager, R.string.welcome_title,
756 getString(R.string.welcome_msg), false);
757 DialogHelper.delegateDialogShow(this, dialog);
759 // Don't display again this dialog
761 Preferences.savePreference(
762 FileManagerSettings.SETTINGS_FIRST_USE, Boolean.FALSE, true);
763 } catch (Exception e) {/**NON BLOCK**/}
768 * Method that initializes the titlebar of the activity.
770 private void initTitleActionBar() {
771 //Inflate the view and associate breadcrumb
772 View titleLayout = getLayoutInflater().inflate(
773 R.layout.navigation_view_customtitle, null, false);
774 NavigationCustomTitleView title =
775 (NavigationCustomTitleView)titleLayout.findViewById(R.id.navigation_title_flipper);
776 title.setOnHistoryListener(this);
777 Breadcrumb breadcrumb = (Breadcrumb)title.findViewById(R.id.breadcrumb_view);
778 int cc = this.mNavigationViews.length;
779 for (int i = 0; i < cc; i++) {
780 this.mNavigationViews[i].setBreadcrumb(breadcrumb);
781 this.mNavigationViews[i].setOnHistoryListener(this);
782 this.mNavigationViews[i].setOnNavigationSelectionChangedListener(this);
783 this.mNavigationViews[i].setOnNavigationOnRequestMenuListener(this);
784 this.mNavigationViews[i].setCustomTitle(title);
787 // Set the free disk space warning level of the breadcrumb widget
788 String fds = Preferences.getSharedPreferences().getString(
789 FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getId(),
790 (String)FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getDefaultValue());
791 breadcrumb.setFreeDiskSpaceWarningLevel(Integer.parseInt(fds));
793 //Configure the action bar options
794 getActionBar().setBackgroundDrawable(
795 getResources().getDrawable(R.drawable.bg_material_titlebar));
796 mToolBar.addView(titleLayout);
800 * Method that initializes the statusbar of the activity.
802 private void initStatusActionBar() {
803 //Performs a width calculation of buttons. Buttons exceeds the width
804 //of the action bar should be hidden
805 //This application not use android ActionBar because the application
806 //make uses of the title and bottom areas, and wants to force to show
807 //the overflow button (without care of physical buttons)
808 this.mActionBar = (ViewGroup)findViewById(R.id.navigation_actionbar);
809 this.mActionBar.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
811 public void onLayoutChange(
812 View v, int left, int top, int right, int bottom, int oldLeft,
813 int oldTop, int oldRight, int oldBottom) {
814 //Get the width of the action bar
815 int w = v.getMeasuredWidth();
817 //Wake through children calculation his dimensions
818 int bw = (int)getResources().getDimension(R.dimen.default_buttom_width);
820 final ViewGroup abView = ((ViewGroup)v);
821 int cc = abView.getChildCount();
822 for (int i = 0; i < cc; i++) {
823 View child = abView.getChildAt(i);
824 child.setVisibility(cw + bw > w ? View.INVISIBLE : View.VISIBLE);
830 // Have overflow menu? Actually no. There is only a search action, so just hide
832 View overflow = findViewById(R.id.ab_overflow);
833 overflow.setVisibility(View.GONE);
835 // Show the status bar
836 View statusBar = findViewById(R.id.navigation_statusbar_portrait_holder);
837 statusBar.setVisibility(View.VISIBLE);
841 * Method that initializes the selectionbar of the activity.
843 private void initSelectionBar() {
844 this.mSelectionBar = (SelectionView)findViewById(R.id.navigation_selectionbar);
848 * Method that initializes the navigation drawer of the activity.
850 private void initDrawer() {
851 mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
852 //Set our status bar color
853 mDrawerLayout.setStatusBarBackgroundColor(R.color.material_palette_blue_primary_dark);
854 mDrawer = (ViewGroup) findViewById(R.id.drawer);
855 mDrawerBookmarks = (LinearLayout) findViewById(R.id.bookmarks_list);
856 mDrawerHistory = (LinearLayout) findViewById(R.id.history_list);
857 mDrawerHistoryEmpty = (TextView) findViewById(R.id.history_empty);
859 mBookmarksLayout = findViewById(R.id.drawer_bookmarks);
860 mHistoryLayout = findViewById(R.id.drawer_history);
861 mBookmarksTab = (TextView) findViewById(R.id.drawer_bookmarks_tab);
862 mHistoryTab = (TextView) findViewById(R.id.drawer_history_tab);
863 mBookmarksTab.setOnClickListener(mOnClickDrawerTabListener);
864 mHistoryTab.setOnClickListener(mOnClickDrawerTabListener);
866 mSettings = (ButtonItem) findViewById(R.id.ab_settings);
867 mSettings.setOnClickListener(mOnClickDrawerActionBarListener);
868 mClearHistory = (ButtonItem) findViewById(R.id.ab_clear_history);
869 mClearHistory.setOnClickListener(mOnClickDrawerActionBarListener);
871 // Restore the last tab pressed
872 Integer lastTab = Preferences.getSharedPreferences().getInt(
873 FileManagerSettings.USER_PREF_LAST_DRAWER_TAB.getId(),
874 (Integer) FileManagerSettings.USER_PREF_LAST_DRAWER_TAB
876 mOnClickDrawerTabListener.onClick(lastTab == 0 ? mBookmarksTab : mHistoryTab);
878 // Set the navigation drawer "hamburger" icon
879 mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
880 R.drawable.ic_material_light_navigation_drawer,
881 R.string.drawer_open, R.string.drawer_close) {
883 /** Called when a drawer has settled in a completely closed state. */
884 public void onDrawerClosed(View view) {
885 super.onDrawerClosed(view);
888 /** Called when a drawer has settled in a completely open state. */
889 public void onDrawerOpened(View drawerView) {
890 super.onDrawerOpened(drawerView);
893 getActionBar().setDisplayHomeAsUpEnabled(true);
895 // Set the drawer toggle as the DrawerListener
896 mDrawerLayout.setDrawerListener(mDrawerToggle);
900 * Method that adds a history entry to the history list in the drawer
902 private void addHistoryToDrawer(int index, HistoryNavigable navigable) {
903 // hide empty message
904 mDrawerHistoryEmpty.setVisibility(View.GONE);
906 Theme theme = ThemeManager.getCurrentTheme(this);
907 IconHolder iconholder = new IconHolder(this, false);
909 // inflate single bookmark layout item and fill it
910 LinearLayout view = (LinearLayout) getLayoutInflater().inflate(
911 R.layout.history_item, null);
913 ImageView iconView = (ImageView) view
914 .findViewById(R.id.history_item_icon);
915 TextView name = (TextView) view.findViewById(R.id.history_item_name);
916 TextView directory = (TextView) view
917 .findViewById(R.id.history_item_directory);
919 Drawable icon = iconholder.getDrawable("ic_fso_folder_drawable"); //$NON-NLS-1$
920 if (navigable instanceof SearchInfoParcelable) {
921 icon = iconholder.getDrawable("ic_history_search_drawable"); //$NON-NLS-1$
923 iconView.setImageDrawable(icon);
925 String title = navigable.getTitle();
926 if (title == null || title.trim().length() == 0) {
927 title = getString(R.string.root_directory_name);
931 directory.setText(navigable.getDescription());
933 theme.setTextColor(this, name, "text_color");
934 theme.setTextColor(this, directory, "text_color");
937 view.setOnClickListener(new OnClickListener() {
939 public void onClick(View v) {
940 final int index = mDrawerHistory.indexOfChild(v);
941 final int count = mDrawerHistory.getChildCount();
942 final History history = mHistory.get(count - index - 1);
944 navigateToHistory(history);
945 mDrawerLayout.closeDrawer(Gravity.START);
949 // add as first child
950 mDrawerHistory.addView(view, 0);
952 // Show clear button if history tab is selected
953 mClearHistory.setVisibility(mHistoryTab.isSelected() ? View.VISIBLE : View.GONE);
957 * Method takes a bookmark as argument and adds it to mBookmarks and the
960 public void addBookmark(Bookmark bookmark) {
961 mBookmarks.add(bookmark);
962 addBookmarkToDrawer(bookmark);
966 * Show the easy mode view
968 private void performShowEasyMode() {
969 mEasyModeListView.setVisibility(View.VISIBLE);
970 getCurrentNavigationView().setVisibility(View.GONE);
974 * Hide the easy mode view
976 private void performHideEasyMode() {
977 mEasyModeListView.setVisibility(View.GONE);
978 getCurrentNavigationView().setVisibility(View.VISIBLE);
982 * Method takes a bookmark as argument and adds it to the bookmark list in
985 private void addBookmarkToDrawer(Bookmark bookmark) {
986 Theme theme = ThemeManager.getCurrentTheme(this);
987 IconHolder iconholder = new IconHolder(this, false);
989 // inflate single bookmark layout item and fill it
990 LinearLayout view = (LinearLayout) getLayoutInflater().inflate(
991 R.layout.bookmarks_item, null);
993 ImageView icon = (ImageView) view
994 .findViewById(R.id.bookmarks_item_icon);
995 TextView name = (TextView) view.findViewById(R.id.bookmarks_item_name);
996 TextView path = (TextView) view.findViewById(R.id.bookmarks_item_path);
997 ImageButton actionButton = (ImageButton) view
998 .findViewById(R.id.bookmarks_item_action);
1000 name.setText(bookmark.mName);
1001 path.setText(bookmark.mPath);
1003 theme.setTextColor(this, name, "text_color");
1004 theme.setTextColor(this, path, "text_color");
1006 icon.setImageDrawable(iconholder.getDrawable(BookmarksHelper
1007 .getIcon(bookmark)));
1009 Drawable action = null;
1010 String actionCd = null;
1011 if (bookmark.mType.compareTo(BOOKMARK_TYPE.HOME) == 0) {
1012 action = iconholder.getDrawable("ic_edit_home_bookmark_drawable"); //$NON-NLS-1$
1013 actionCd = getApplicationContext().getString(
1014 R.string.bookmarks_button_config_cd);
1016 else if (bookmark.mType.compareTo(BOOKMARK_TYPE.USER_DEFINED) == 0) {
1017 action = iconholder.getDrawable("ic_close_drawable"); //$NON-NLS-1$
1018 actionCd = getApplicationContext().getString(
1019 R.string.bookmarks_button_remove_bookmark_cd);
1022 actionButton.setImageDrawable(action);
1023 actionButton.setVisibility(action != null ? View.VISIBLE : View.GONE);
1024 actionButton.setOnClickListener(new OnClickListener() {
1026 public void onClick(View view) {
1027 final View v = (View) view.getParent();
1028 final int index = mDrawerBookmarks.indexOfChild(v);
1029 final Bookmark bookmark = mBookmarks.get(index);
1032 if (bookmark.mType.compareTo(BOOKMARK_TYPE.HOME) == 0) {
1033 // Show a dialog for configure initial directory
1034 InitialDirectoryDialog dialog = new InitialDirectoryDialog(
1035 NavigationActivity.this);
1036 dialog.setOnValueChangedListener(new InitialDirectoryDialog.OnValueChangedListener() {
1038 public void onValueChanged(String newInitialDir) {
1039 bookmark.mPath = newInitialDir;
1041 // reset drawer bookmarks list
1050 if (bookmark.mType.compareTo(BOOKMARK_TYPE.USER_DEFINED) == 0) {
1051 boolean result = Bookmarks.removeBookmark(
1052 getApplicationContext(), bookmark);
1053 if (!result) { // Show warning
1054 DialogHelper.showToast(getApplicationContext(),
1055 R.string.msgs_operation_failure,
1056 Toast.LENGTH_SHORT);
1059 mBookmarks.remove(bookmark);
1060 mDrawerBookmarks.removeView(v);
1065 actionButton.setContentDescription(actionCd);
1067 // handle item click
1068 view.setOnClickListener(new OnClickListener() {
1070 public void onClick(View v) {
1071 final int index = mDrawerBookmarks.indexOfChild(v);
1072 final Bookmark bookmark = mBookmarks.get(index);
1074 boolean showEasyMode = (mSdBookmarks.contains(bookmark)) &&
1075 getResources().getBoolean(R.bool.cmcc_show_easy_mode);
1077 // try to navigate to the bookmark path
1079 FileSystemObject fso = CommandHelper.getFileInfo(
1080 getApplicationContext(), bookmark.mPath, null);
1083 performShowEasyMode();
1085 performHideEasyMode();
1087 getCurrentNavigationView().open(fso);
1088 mDrawerLayout.closeDrawer(Gravity.START);
1091 // The bookmark does not exist, delete the user-defined
1094 Bookmarks.removeBookmark(getApplicationContext(),
1097 // reset bookmarks list to default
1100 catch (Exception ex) {
1104 catch (Exception e) { // Capture the exception
1106 .translateException(NavigationActivity.this, e);
1107 if (e instanceof NoSuchFileOrDirectory
1108 || e instanceof FileNotFoundException) {
1109 // The bookmark does not exist, delete the user-defined
1112 Bookmarks.removeBookmark(getApplicationContext(),
1115 // reset bookmarks list to default
1118 catch (Exception ex) {
1126 mDrawerBookmarks.addView(view);
1130 * Method that initializes the bookmarks.
1132 private synchronized void initBookmarks() {
1133 if (mBookmarksTask != null &&
1134 !mBookmarksTask.getStatus().equals(AsyncTask.Status.FINISHED)) {
1138 // Retrieve the loading view
1139 final View waiting = findViewById(R.id.bookmarks_loading);
1141 // Load bookmarks in background
1142 mBookmarksTask = new AsyncTask<Void, Void, Boolean>() {
1146 protected Boolean doInBackground(Void... params) {
1148 mBookmarks = loadBookmarks();
1149 return Boolean.TRUE;
1152 catch (Exception e) {
1154 return Boolean.FALSE;
1159 protected void onPreExecute() {
1160 waiting.setVisibility(View.VISIBLE);
1161 mDrawerBookmarks.removeAllViews();
1165 protected void onPostExecute(Boolean result) {
1166 waiting.setVisibility(View.GONE);
1167 if (result.booleanValue()) {
1168 for (Bookmark bookmark : mBookmarks) {
1169 addBookmarkToDrawer(bookmark);
1173 if (this.mCause != null) {
1174 ExceptionUtil.translateException(
1175 NavigationActivity.this, this.mCause);
1178 mBookmarksTask = null;
1182 protected void onCancelled() {
1183 waiting.setVisibility(View.GONE);
1184 mBookmarksTask = null;
1187 mBookmarksTask.execute();
1191 * Method that loads all kind of bookmarks and join in an array to be used
1192 * in the listview adapter.
1194 * @return List<Bookmark>
1197 List<Bookmark> loadBookmarks() {
1198 // Bookmarks = HOME + FILESYSTEM + SD STORAGES + USER DEFINED
1199 // In ChRooted mode = SD STORAGES + USER DEFINED (from SD STORAGES)
1200 List<Bookmark> bookmarks = new ArrayList<Bookmark>();
1201 if (!this.mChRooted) {
1202 bookmarks.add(loadHomeBookmarks());
1203 bookmarks.addAll(loadFilesystemBookmarks());
1205 mSdBookmarks = loadSdStorageBookmarks();
1206 bookmarks.addAll(mSdBookmarks);
1207 bookmarks.addAll(loadVirtualBookmarks());
1208 bookmarks.addAll(loadUserBookmarks());
1213 * Method that loads the home bookmark from the user preference.
1215 * @return Bookmark The bookmark loaded
1217 private Bookmark loadHomeBookmarks() {
1218 String initialDir = Preferences.getSharedPreferences().getString(
1219 FileManagerSettings.SETTINGS_INITIAL_DIR.getId(),
1220 (String) FileManagerSettings.SETTINGS_INITIAL_DIR
1221 .getDefaultValue());
1222 return new Bookmark(BOOKMARK_TYPE.HOME,
1223 getString(R.string.bookmarks_home), initialDir);
1227 * Method that loads the filesystem bookmarks from the internal xml file.
1228 * (defined by this application)
1230 * @return List<Bookmark> The bookmarks loaded
1232 private List<Bookmark> loadFilesystemBookmarks() {
1234 // Initialize the bookmarks
1235 List<Bookmark> bookmarks = new ArrayList<Bookmark>();
1237 // Read the command list xml file
1238 XmlResourceParser parser = getResources().getXml(
1239 R.xml.filesystem_bookmarks);
1242 // Find the root element
1243 XmlUtils.beginDocument(parser, TAG_BOOKMARKS);
1245 XmlUtils.nextElement(parser);
1246 String element = parser.getName();
1247 if (element == null) {
1251 if (TAG_BOOKMARK.equals(element)) {
1252 CharSequence name = null;
1253 CharSequence directory = null;
1256 name = getString(parser.getAttributeResourceValue(
1257 R.styleable.Bookmark_name, 0));
1259 catch (Exception e) {
1263 directory = getString(parser
1264 .getAttributeResourceValue(
1265 R.styleable.Bookmark_directory, 0));
1267 catch (Exception e) {
1270 if (directory == null) {
1272 .getAttributeValue(R.styleable.Bookmark_directory);
1274 if (name != null && directory != null) {
1275 bookmarks.add(new Bookmark(
1276 BOOKMARK_TYPE.FILESYSTEM, name.toString(),
1277 directory.toString()));
1282 // Return the bookmarks
1290 catch (Throwable ex) {
1291 Log.e(TAG, "Load filesystem bookmarks failed", ex); //$NON-NLS-1$
1295 return new ArrayList<Bookmark>();
1299 * Method that loads the secure digital card storage bookmarks from the
1302 * @return List<Bookmark> The bookmarks loaded
1304 private List<Bookmark> loadSdStorageBookmarks() {
1305 // Initialize the bookmarks
1306 List<Bookmark> bookmarks = new ArrayList<Bookmark>();
1309 // Recovery sdcards from storage manager
1310 StorageVolume[] volumes = StorageHelper
1311 .getStorageVolumes(getApplication(), true);
1312 for (StorageVolume volume: volumes) {
1313 if (volume != null) {
1314 String mountedState = volume.getState();
1315 String path = volume.getPath();
1316 if (!Environment.MEDIA_MOUNTED.equalsIgnoreCase(mountedState) &&
1317 !Environment.MEDIA_MOUNTED_READ_ONLY.equalsIgnoreCase(mountedState)) {
1318 Log.w(TAG, "Ignoring '" + path + "' with state of '"+ mountedState + "'");
1321 if (!TextUtils.isEmpty(path)) {
1322 String lowerPath = path.toLowerCase(Locale.ROOT);
1324 if (lowerPath.contains(STR_USB)) {
1325 bookmark = new Bookmark(BOOKMARK_TYPE.USB, StorageHelper
1326 .getStorageVolumeDescription(getApplication(), volume), path);
1328 bookmark = new Bookmark(BOOKMARK_TYPE.SDCARD, StorageHelper
1329 .getStorageVolumeDescription(getApplication(), volume), path);
1331 bookmarks.add(bookmark);
1336 // Return the bookmarks
1339 catch (Throwable ex) {
1340 Log.e(TAG, "Load filesystem bookmarks failed", ex); //$NON-NLS-1$
1344 return new ArrayList<Bookmark>();
1348 * Method that loads all virtual mount points.
1350 * @return List<Bookmark> The bookmarks loaded
1352 private List<Bookmark> loadVirtualBookmarks() {
1353 // Initialize the bookmarks
1354 List<Bookmark> bookmarks = new ArrayList<Bookmark>();
1355 List<MountPoint> mps = VirtualMountPointConsole.getVirtualMountPoints();
1356 for (MountPoint mp : mps) {
1357 BOOKMARK_TYPE type = null;
1359 if (mp.isSecure()) {
1360 type = BOOKMARK_TYPE.SECURE;
1361 name = getString(R.string.bookmarks_secure);
1362 } else if (mp.isRemote()) {
1363 type = BOOKMARK_TYPE.REMOTE;
1364 name = getString(R.string.bookmarks_remote);
1368 bookmarks.add(new Bookmark(type, name, mp.getMountPoint()));
1374 * Method that loads the user bookmarks (added by the user).
1376 * @return List<Bookmark> The bookmarks loaded
1378 private List<Bookmark> loadUserBookmarks() {
1379 List<Bookmark> bookmarks = new ArrayList<Bookmark>();
1380 Cursor cursor = Bookmarks.getAllBookmarks(this.getContentResolver());
1382 if (cursor != null && cursor.moveToFirst()) {
1384 Bookmark bm = new Bookmark(cursor);
1386 && !StorageHelper.isPathInStorageVolume(bm.mPath)) {
1391 while (cursor.moveToNext());
1396 if (cursor != null) {
1400 catch (Exception e) {
1405 // Remove bookmarks from virtual storage if the filesystem is not mount
1406 int c = bookmarks.size() - 1;
1407 for (int i = c; i >= 0; i--) {
1408 VirtualMountPointConsole vc =
1409 VirtualMountPointConsole.getVirtualConsoleForPath(bookmarks.get(i).mPath);
1410 if (vc != null && !vc.isMounted()) {
1411 bookmarks.remove(i);
1419 * Method that initializes the navigation views of the activity
1421 private void initNavigationViews() {
1422 //Get the navigation views (wishlist: multiple view; for now only one view)
1423 this.mNavigationViews = new NavigationView[1];
1424 this.mCurrentNavigationView = 0;
1426 this.mNavigationViews[0] = (NavigationView)findViewById(R.id.navigation_view);
1427 this.mNavigationViews[0].setId(0);
1428 this.mEasyModeListView = (ListView) findViewById(R.id.lv_easy_mode);
1429 mEasyModeAdapter = new ArrayAdapter<MimeTypeCategory>(this, R.layout
1430 .navigation_view_simple_item) {
1432 public View getView(int position, View convertView, ViewGroup parent) {
1433 convertView = (convertView == null) ?getLayoutInflater().inflate(R.layout
1434 .navigation_view_simple_item, parent, false) : convertView;
1435 MimeTypeCategory item = getItem(position);
1436 String typeTitle = MIME_TYPE_LOCALIZED_NAMES[item.ordinal()];
1437 TextView typeTitleTV = (TextView) convertView
1438 .findViewById(R.id.navigation_view_item_name);
1439 ImageView typeIconIV = (ImageView) convertView
1440 .findViewById(R.id.navigation_view_item_icon);
1441 View checkBoxView = convertView.findViewById(R.id.navigation_view_item_check);
1442 checkBoxView.setVisibility(View.GONE);
1443 typeTitleTV.setText(typeTitle);
1444 typeIconIV.setImageDrawable(EASY_MODE_ICONS.get(item));
1445 convertView.setOnClickListener(mEasyModeItemClickListener);
1446 convertView.setTag(position);
1450 mEasyModeAdapter.addAll(EASY_MODE_LIST);
1451 mEasyModeListView.setAdapter(mEasyModeAdapter);
1454 private void onClicked(int position) {
1455 Intent intent = new Intent(this, SearchActivity.class);
1456 intent.setAction(Intent.ACTION_SEARCH);
1457 intent.putExtra(SearchActivity.EXTRA_SEARCH_DIRECTORY,
1458 getCurrentNavigationView().getCurrentDir());
1459 intent.putExtra(SearchManager.QUERY, "*"); // Use wild-card '*'
1461 if (position == 0) {
1462 performHideEasyMode();
1466 ArrayList<MimeTypeCategory> searchCategories = new ArrayList<MimeTypeCategory>();
1467 MimeTypeCategory selectedCategory = EASY_MODE_LIST.get(position);
1468 searchCategories.add(selectedCategory);
1469 // a one off case where we implicitly want to also search for TEXT mimetypes when the
1470 // DOCUMENTS category is selected
1471 if (selectedCategory == MimeTypeCategory.DOCUMENT) {
1472 searchCategories.add(MimeTypeCategory.TEXT);
1474 intent.putExtra(SearchActivity.EXTRA_SEARCH_MIMETYPE, searchCategories);
1477 startActivity(intent);
1481 * Method that initialize the console
1484 void initConsole() {
1485 //Create the default console (from the preferences)
1487 Console console = ConsoleBuilder.getConsole(NavigationActivity.this);
1488 if (console == null) {
1489 throw new ConsoleAllocException("console == null"); //$NON-NLS-1$
1491 } catch (Throwable ex) {
1492 if (!NavigationActivity.this.mChRooted) {
1493 //Show exception and exit
1494 Log.e(TAG, getString(R.string.msgs_cant_create_console), ex);
1495 // We don't have any console
1496 // Show exception and exit
1497 DialogHelper.showToast(
1498 NavigationActivity.this,
1499 R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
1504 // We are in a trouble (something is not allowing creating the console)
1505 // Ask the user to return to prompt or root access mode mode with a
1506 // non-privileged console, prior to make crash the application
1513 * Method that initializes the navigation.
1515 * @param viewId The navigation view identifier where apply the navigation
1516 * @param restore Initialize from a restore info
1517 * @param intent The current intent
1520 void initNavigation(final int viewId, final boolean restore, final Intent intent) {
1521 final NavigationView navigationView = getNavigationView(viewId);
1522 this.mHandler.post(new Runnable() {
1525 //Is necessary navigate?
1527 applyInitialDir(navigationView, intent);
1534 * Method that applies the user-defined initial directory
1536 * @param navigationView The navigation view
1537 * @param intent The current intent
1540 void applyInitialDir(final NavigationView navigationView, final Intent intent) {
1541 //Load the user-defined initial directory
1543 Preferences.getSharedPreferences().getString(
1544 FileManagerSettings.SETTINGS_INITIAL_DIR.getId(),
1545 (String)FileManagerSettings.
1546 SETTINGS_INITIAL_DIR.getDefaultValue());
1548 // Check if request navigation to directory (use as default), and
1549 // ensure chrooted and absolute path
1550 String navigateTo = intent.getStringExtra(EXTRA_NAVIGATE_TO);
1551 String intentAction = intent.getAction();
1552 if (navigateTo != null && navigateTo.length() > 0) {
1553 initialDir = navigateTo;
1554 } else if (intentAction != null && intentAction.equals(Intent.ACTION_VIEW)) {
1555 Uri data = intent.getData();
1556 if (data != null && (FileHelper.FILE_URI_SCHEME.equals(data.getScheme())
1557 || FileHelper.FOLDER_URI_SCHEME.equals(data.getScheme())
1558 || FileHelper.DIRECTORY_URI_SCHEME.equals(data.getScheme()))) {
1559 File path = new File(data.getPath());
1560 if (path.isDirectory()) {
1561 initialDir = path.getAbsolutePath();
1567 final boolean addToHistory = intent.getBooleanExtra(EXTRA_ADD_TO_HISTORY, true);
1569 // We cannot navigate to a secure console if it is unmounted. So go to root in that case
1570 VirtualConsole vc = VirtualMountPointConsole.getVirtualConsoleForPath(initialDir);
1571 if (vc != null && vc instanceof SecureConsole && !((SecureConsole) vc).isMounted()) {
1572 initialDir = FileHelper.ROOT_DIRECTORY;
1575 if (this.mChRooted) {
1576 // Initial directory is the first external sdcard (sdcard, emmc, usb, ...)
1577 if (!StorageHelper.isPathInStorageVolume(initialDir)) {
1578 StorageVolume[] volumes =
1579 StorageHelper.getStorageVolumes(this, false);
1580 if (volumes != null && volumes.length > 0) {
1581 initialDir = volumes[0].getPath();
1582 int count = volumes.length;
1583 for (int i = 0; i < count; i++) {
1584 StorageVolume volume = volumes[i];
1585 if (Environment.MEDIA_MOUNTED.equalsIgnoreCase(volume.getState())) {
1586 initialDir = volume.getPath();
1590 //Ensure that initial directory is an absolute directory
1591 initialDir = FileHelper.getAbsPath(initialDir);
1593 // Show exception and exit
1594 DialogHelper.showToast(
1596 R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
1602 //Ensure that initial directory is an absolute directory
1603 final String userInitialDir = initialDir;
1604 initialDir = FileHelper.getAbsPath(initialDir);
1605 final String absInitialDir = initialDir;
1606 File f = new File(initialDir);
1607 boolean exists = f.exists();
1609 // Fix for /data/media/0. Libcore doesn't detect it correctly.
1611 exists = CommandHelper.getFileInfo(this, initialDir, false, null) != null;
1612 } catch (InsufficientPermissionsException ipex) {
1613 ExceptionUtil.translateException(
1614 this, ipex, false, true, new OnRelaunchCommandResult() {
1616 public void onSuccess() {
1617 navigationView.changeCurrentDir(absInitialDir, addToHistory);
1620 public void onFailed(Throwable cause) {
1621 showInitialInvalidDirectoryMsg(userInitialDir);
1622 navigationView.changeCurrentDir(FileHelper.ROOT_DIRECTORY,
1626 public void onCancelled() {
1627 showInitialInvalidDirectoryMsg(userInitialDir);
1628 navigationView.changeCurrentDir(FileHelper.ROOT_DIRECTORY,
1633 // Asynchronous mode
1635 } catch (Exception ex) {
1636 // We are not interested in other exceptions
1637 ExceptionUtil.translateException(this, ex, true, false);
1640 // Check again the initial directory
1642 showInitialInvalidDirectoryMsg(userInitialDir);
1643 initialDir = FileHelper.ROOT_DIRECTORY;
1646 // Weird, but we have a valid initial directory
1650 boolean needsEasyMode = false;
1651 if (mSdBookmarks != null ) {
1652 for (Bookmark bookmark :mSdBookmarks) {
1653 if (bookmark.mPath.equalsIgnoreCase(initialDir)) {
1654 needsEasyMode = true;
1660 needsEasyMode = needsEasyMode
1661 && getResources().getBoolean(R.bool.cmcc_show_easy_mode);
1662 if (needsEasyMode) {
1663 performShowEasyMode();
1665 performHideEasyMode();
1667 // Change the current directory to the user-defined initial directory
1668 navigationView.changeCurrentDir(initialDir, addToHistory);
1672 * Displays a message reporting invalid directory
1674 * @param initialDir The initial directory
1677 void showInitialInvalidDirectoryMsg(String initialDir) {
1678 // Change to root directory
1679 DialogHelper.showToast(
1682 R.string.msgs_settings_invalid_initial_directory,
1684 Toast.LENGTH_SHORT);
1688 * Method that verifies the intent passed to the activity, and checks
1689 * if a request is made like Search.
1691 * @param intent The intent to check
1694 void checkIntent(Intent intent) {
1696 if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
1697 Intent searchIntent = new Intent(this, SearchActivity.class);
1698 searchIntent.setAction(Intent.ACTION_SEARCH);
1699 //- SearchActivity.EXTRA_SEARCH_DIRECTORY
1700 searchIntent.putExtra(
1701 SearchActivity.EXTRA_SEARCH_DIRECTORY,
1702 getCurrentNavigationView().getCurrentDir());
1703 //- SearchManager.APP_DATA
1704 if (intent.getBundleExtra(SearchManager.APP_DATA) != null) {
1705 Bundle bundle = new Bundle();
1706 bundle.putAll(intent.getBundleExtra(SearchManager.APP_DATA));
1707 searchIntent.putExtra(SearchManager.APP_DATA, bundle);
1709 //-- SearchManager.QUERY
1710 String query = intent.getStringExtra(SearchManager.QUERY);
1711 if (query != null) {
1712 searchIntent.putExtra(SearchManager.QUERY, query);
1714 //- android.speech.RecognizerIntent.EXTRA_RESULTS
1715 ArrayList<String> extraResults =
1716 intent.getStringArrayListExtra(android.speech.RecognizerIntent.EXTRA_RESULTS);
1717 if (extraResults != null) {
1718 searchIntent.putStringArrayListExtra(
1719 android.speech.RecognizerIntent.EXTRA_RESULTS, extraResults);
1721 startActivityForResult(searchIntent, INTENT_REQUEST_SEARCH);
1730 public boolean onKeyUp(int keyCode, KeyEvent event) {
1731 if (keyCode == KeyEvent.KEYCODE_MENU) {
1732 if (mDrawerLayout.isDrawerOpen(mDrawer)) {
1733 mDrawerLayout.closeDrawer(Gravity.START);
1735 mDrawerLayout.openDrawer(Gravity.START);
1739 return super.onKeyUp(keyCode, event);
1743 public void onBackPressed() {
1744 if (mDrawerLayout.isDrawerOpen(Gravity.START)) {
1745 mDrawerLayout.closeDrawer(Gravity.START);
1748 if (checkBackAction()) {
1749 performHideEasyMode();
1753 // An exit event has occurred, force the destroy the consoles
1758 * Method invoked when an action item is clicked.
1760 * @param view The button pushed
1762 public void onActionBarItemClick(View view) {
1763 switch (view.getId()) {
1764 //######################
1765 //Navigation Custom Title
1766 //######################
1767 case R.id.ab_configuration:
1768 //Show navigation view configuration toolbar
1769 getCurrentNavigationView().getCustomTitle().showConfigurationView();
1772 //Hide navigation view configuration toolbar
1773 getCurrentNavigationView().getCustomTitle().hideConfigurationView();
1776 //######################
1777 //Breadcrumb Actions
1778 //######################
1779 case R.id.ab_filesystem_info:
1780 //Show information of the filesystem
1781 MountPoint mp = getCurrentNavigationView().getBreadcrumb().getMountPointInfo();
1782 DiskUsage du = getCurrentNavigationView().getBreadcrumb().getDiskUsageInfo();
1783 showMountPointInfo(mp, du);
1786 //######################
1787 //Navigation view options
1788 //######################
1789 case R.id.ab_sort_mode:
1790 showSettingsPopUp(view,
1792 new FileManagerSettings[]{
1793 FileManagerSettings.SETTINGS_SORT_MODE}));
1795 case R.id.ab_layout_mode:
1796 showSettingsPopUp(view,
1798 new FileManagerSettings[]{
1799 FileManagerSettings.SETTINGS_LAYOUT_MODE}));
1801 case R.id.ab_view_options:
1802 // If we are in ChRooted mode, then don't show non-secure items
1803 if (this.mChRooted) {
1804 showSettingsPopUp(view,
1805 Arrays.asList(new FileManagerSettings[]{
1806 FileManagerSettings.SETTINGS_SHOW_DIRS_FIRST}));
1808 showSettingsPopUp(view,
1809 Arrays.asList(new FileManagerSettings[]{
1810 FileManagerSettings.SETTINGS_SHOW_DIRS_FIRST,
1811 FileManagerSettings.SETTINGS_SHOW_HIDDEN,
1812 FileManagerSettings.SETTINGS_SHOW_SYSTEM,
1813 FileManagerSettings.SETTINGS_SHOW_SYMLINKS}));
1818 //######################
1820 //######################
1821 case R.id.ab_selection_done:
1822 //Show information of the filesystem
1823 getCurrentNavigationView().onDeselectAll();
1826 //######################
1827 //Action Bar buttons
1828 //######################
1829 case R.id.ab_actions:
1830 openActionsDialog(getCurrentNavigationView().getCurrentDir(),
1834 case R.id.ab_search:
1848 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
1849 if (requestCode == INTENT_REQUEST_SETTINGS) {
1850 // reset bookmarks list to default as the user could changed the
1851 // root mode which changes the system bookmarks
1857 switch (requestCode) {
1858 case INTENT_REQUEST_SEARCH:
1859 if (resultCode == RESULT_OK) {
1861 Bundle bundle = data.getExtras();
1862 if (bundle != null) {
1863 FileSystemObject fso = (FileSystemObject) bundle.getSerializable(
1864 EXTRA_SEARCH_ENTRY_SELECTION);
1865 SearchInfoParcelable searchInfo =
1866 bundle.getParcelable(EXTRA_SEARCH_LAST_SEARCH_DATA);
1868 //Goto to new directory
1869 getCurrentNavigationView().open(fso, searchInfo);
1870 performHideEasyMode();
1873 } else if (resultCode == RESULT_CANCELED) {
1874 SearchInfoParcelable searchInfo =
1875 data.getParcelableExtra(EXTRA_SEARCH_LAST_SEARCH_DATA);
1876 if (searchInfo != null && searchInfo.isSuccessNavigation()) {
1877 //Navigate to previous history
1880 // I don't know is the search view was changed, so try to do a refresh
1881 // of the navigation view
1882 getCurrentNavigationView().refresh(true);
1885 // reset bookmarks list to default as the user could have set a
1886 // new bookmark in the search activity
1900 public void onNewHistory(HistoryNavigable navigable) {
1901 addHistoryToDrawer(this.mHistory.size(), navigable);
1902 //Recollect information about current status
1903 History history = new History(this.mHistory.size(), navigable);
1904 this.mHistory.add(history);
1911 public void onCheckHistory() {
1918 public void onRequestRefresh(Object o, boolean clearSelection) {
1919 if (o instanceof FileSystemObject) {
1920 // Refresh only the item
1921 this.getCurrentNavigationView().refresh((FileSystemObject)o);
1922 } else if (o == null) {
1924 getCurrentNavigationView().refresh();
1926 if (clearSelection) {
1927 this.getCurrentNavigationView().onDeselectAll();
1935 public void onRequestBookmarksRefresh() {
1943 public void onRequestRemove(Object o, boolean clearSelection) {
1944 if (o instanceof FileSystemObject) {
1946 this.getCurrentNavigationView().removeItem((FileSystemObject)o);
1948 //Remove from history
1949 removeFromHistory((FileSystemObject)o);
1951 onRequestRefresh(null, clearSelection);
1953 if (clearSelection) {
1954 this.getCurrentNavigationView().onDeselectAll();
1962 public void onNavigateTo(Object o) {
1967 public void onCancel(){
1975 public void onSelectionChanged(NavigationView navView, List<FileSystemObject> selectedItems) {
1976 this.mSelectionBar.setSelection(selectedItems);
1983 public void onRequestMenu(NavigationView navView, FileSystemObject item) {
1984 // Show the actions dialog
1985 openActionsDialog(item, false);
1989 * Method that shows a popup with a menu associated a {@link FileManagerSettings}.
1991 * @param anchor The action button that was pressed
1992 * @param settings The array of settings associated with the action button
1994 private void showSettingsPopUp(View anchor, List<FileManagerSettings> settings) {
1995 //Create the adapter
1996 final MenuSettingsAdapter adapter = new MenuSettingsAdapter(this, settings);
1998 //Create a show the popup menu
1999 final ListPopupWindow popup = DialogHelper.createListPopupWindow(this, adapter, anchor);
2000 popup.setOnItemClickListener(new OnItemClickListener() {
2002 public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
2003 FileManagerSettings setting =
2004 ((MenuSettingsAdapter)parent.getAdapter()).getSetting(position);
2005 final int value = ((MenuSettingsAdapter)parent.getAdapter()).getId(position);
2008 if (setting.compareTo(FileManagerSettings.SETTINGS_LAYOUT_MODE) == 0) {
2009 //Need to change the layout
2010 getCurrentNavigationView().changeViewMode(
2011 NavigationLayoutMode.fromId(value));
2014 if (setting.getDefaultValue() instanceof Enum<?>) {
2016 Preferences.savePreference(setting, new ObjectIdentifier() {
2018 public int getId() {
2025 Preferences.getSharedPreferences().
2028 ((Boolean)setting.getDefaultValue()).booleanValue());
2029 Preferences.savePreference(setting, Boolean.valueOf(!newval), false);
2031 getCurrentNavigationView().refresh();
2033 } catch (Exception e) {
2034 Log.e(TAG, "Error applying navigation option", e); //$NON-NLS-1$
2035 NavigationActivity.this.mHandler.post(new Runnable() {
2038 DialogHelper.showToast(
2039 NavigationActivity.this,
2040 R.string.msgs_settings_save_failure, Toast.LENGTH_SHORT);
2046 getCurrentNavigationView().getCustomTitle().restoreView();
2051 popup.setOnDismissListener(new PopupWindow.OnDismissListener() {
2053 public void onDismiss() {
2061 * Method that show the information of a filesystem mount point.
2063 * @param mp The mount point info
2064 * @param du The disk usage of the mount point
2066 private void showMountPointInfo(MountPoint mp, DiskUsage du) {
2067 //Has mount point info?
2069 //There is no information
2071 DialogHelper.createWarningDialog(
2073 R.string.filesystem_info_warning_title,
2074 R.string.filesystem_info_warning_msg);
2075 DialogHelper.delegateDialogShow(this, alert);
2079 //Show a the filesystem info dialog
2080 FilesystemInfoDialog dialog = new FilesystemInfoDialog(this, mp, du);
2081 dialog.setOnMountListener(new OnMountListener() {
2083 public void onRemount(MountPoint mountPoint) {
2084 //Update the statistics of breadcrumb, only if mount point is the same
2085 Breadcrumb breadcrumb = getCurrentNavigationView().getBreadcrumb();
2086 if (breadcrumb.getMountPointInfo().compareTo(mountPoint) == 0) {
2087 breadcrumb.updateMountPointInfo();
2089 if (mountPoint.isSecure()) {
2090 // Secure mountpoints only can be unmount, so we need to move the navigation
2091 // to a secure storage (do not add to history)
2092 Intent intent = new Intent();
2093 intent.putExtra(EXTRA_ADD_TO_HISTORY, false);
2094 initNavigation(NavigationActivity.this.mCurrentNavigationView, false, intent);
2102 * Method that checks the action that must be realized when the
2103 * back button is pushed.
2105 * @return boolean Indicates if the action must be intercepted
2107 private boolean checkBackAction() {
2108 // We need a basic structure to check this
2109 if (getCurrentNavigationView() == null) return false;
2111 if (mSearchView.getVisibility() == View.VISIBLE) {
2115 //Check if the configuration view is showing. In this case back
2116 //action must be "close configuration"
2117 if (getCurrentNavigationView().getCustomTitle().isConfigurationViewShowing()) {
2118 getCurrentNavigationView().getCustomTitle().restoreView();
2122 //Do back operation over the navigation history
2123 boolean flag = this.mExitFlag;
2125 this.mExitFlag = !back();
2127 // Retrieve if the exit status timeout has expired
2128 long now = System.currentTimeMillis();
2129 boolean timeout = (this.mExitBackTimeout == -1 ||
2130 (now - this.mExitBackTimeout) > RELEASE_EXIT_CHECK_TIMEOUT);
2132 //Check if there no history and if the user was advised in the last back action
2133 if (this.mExitFlag && (this.mExitFlag != flag || timeout)) {
2134 //Communicate the user that the next time the application will be closed
2135 this.mExitBackTimeout = System.currentTimeMillis();
2136 DialogHelper.showToast(this, R.string.msgs_push_again_to_exit, Toast.LENGTH_SHORT);
2140 //Back action not applied
2141 return !this.mExitFlag;
2145 public void startActivity(Intent intent) {
2146 // check if search intent
2147 if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
2148 intent.putExtra(SearchActivity.EXTRA_SEARCH_DIRECTORY,
2149 getCurrentNavigationView().getCurrentDir());
2152 super.startActivity(intent);
2156 * Method that returns the history size.
2158 private void clearHistory() {
2159 this.mHistory.clear();
2160 mDrawerHistory.removeAllViews();
2161 mDrawerHistoryEmpty.setVisibility(View.VISIBLE);
2165 * Method that navigates to the passed history reference.
2167 * @param history The history reference
2168 * @return boolean A problem occurs while navigate
2170 public synchronized boolean navigateToHistory(History history) {
2173 History realHistory = this.mHistory.get(history.getPosition());
2175 //Navigate to item. Check what kind of history is
2176 if (realHistory.getItem() instanceof NavigationViewInfoParcelable) {
2178 NavigationViewInfoParcelable info =
2179 (NavigationViewInfoParcelable)realHistory.getItem();
2180 int viewId = info.getId();
2181 NavigationView view = getNavigationView(viewId);
2182 // Selected items must not be restored from on history navigation
2183 info.setSelectedFiles(view.getSelectedFiles());
2184 if (!view.onRestoreState(info)) {
2188 } else if (realHistory.getItem() instanceof SearchInfoParcelable) {
2189 //Search (open search with the search results)
2190 SearchInfoParcelable info = (SearchInfoParcelable)realHistory.getItem();
2191 Intent searchIntent = new Intent(this, SearchActivity.class);
2192 searchIntent.setAction(SearchActivity.ACTION_RESTORE);
2193 searchIntent.putExtra(SearchActivity.EXTRA_SEARCH_RESTORE, (Parcelable)info);
2194 startActivityForResult(searchIntent, INTENT_REQUEST_SEARCH);
2196 //The type is unknown
2197 throw new IllegalArgumentException("Unknown history type"); //$NON-NLS-1$
2200 //Remove the old history
2201 int cc = realHistory.getPosition();
2202 for (int i = this.mHistory.size() - 1; i >= cc; i--) {
2203 this.mHistory.remove(i);
2204 mDrawerHistory.removeViewAt(0);
2207 if (mDrawerHistory.getChildCount() == 0) {
2208 mDrawerHistoryEmpty.setVisibility(View.VISIBLE);
2212 boolean clearHistory = mHistoryTab.isSelected() && mHistory.size() > 0;
2213 mClearHistory.setVisibility(clearHistory ? View.VISIBLE : View.GONE);
2216 } catch (Throwable ex) {
2217 if (history != null) {
2219 String.format("Failed to navigate to history %d: %s", //$NON-NLS-1$
2220 Integer.valueOf(history.getPosition()),
2221 history.getItem().getTitle()), ex);
2224 String.format("Failed to navigate to history: null", ex)); //$NON-NLS-1$
2226 this.mHandler.post(new Runnable() {
2229 DialogHelper.showToast(
2230 NavigationActivity.this,
2231 R.string.msgs_history_unknown, Toast.LENGTH_LONG);
2235 //Not change directory
2241 * Method that request a back action over the navigation history.
2243 * @return boolean If a back action was applied
2245 public boolean back() {
2246 // Check that has valid history
2247 while (this.mHistory.size() > 0) {
2248 History h = this.mHistory.get(this.mHistory.size() - 1);
2249 if (h.getItem() instanceof NavigationViewInfoParcelable) {
2250 // Verify that the path exists
2251 String path = ((NavigationViewInfoParcelable)h.getItem()).getCurrentDir();
2254 FileSystemObject info = CommandHelper.getFileInfo(this, path, null);
2258 this.mHistory.remove(this.mHistory.size() - 1);
2259 } catch (Exception e) {
2260 ExceptionUtil.translateException(this, e, true, false);
2261 this.mHistory.remove(this.mHistory.size() - 1);
2268 //Navigate to history
2269 if (this.mHistory.size() > 0) {
2270 return navigateToHistory(this.mHistory.get(this.mHistory.size() - 1));
2274 mClearHistory.setVisibility(View.GONE);
2279 * Method that opens the actions dialog
2281 * @param item The path or the {@link FileSystemObject}
2282 * @param global If the menu to display is the one with global actions
2284 private void openActionsDialog(Object item, boolean global) {
2285 // Resolve the full path
2286 String path = String.valueOf(item);
2287 if (item instanceof FileSystemObject) {
2288 path = ((FileSystemObject)item).getFullPath();
2291 // Prior to show the dialog, refresh the item reference
2292 FileSystemObject fso = null;
2294 fso = CommandHelper.getFileInfo(this, path, false, null);
2296 throw new NoSuchFileOrDirectory(path);
2299 } catch (Exception e) {
2301 ExceptionUtil.translateException(this, e);
2303 // Remove the object
2304 if (e instanceof FileNotFoundException || e instanceof NoSuchFileOrDirectory) {
2305 // If have a FileSystemObject reference then there is no need to search
2306 // the path (less resources used)
2307 if (item instanceof FileSystemObject) {
2308 getCurrentNavigationView().removeItem((FileSystemObject)item);
2310 getCurrentNavigationView().removeItem((String)item);
2317 ActionsDialog dialog = new ActionsDialog(this, this, fso, global, false);
2318 dialog.setOnRequestRefreshListener(this);
2319 dialog.setOnSelectionListener(getCurrentNavigationView());
2324 * Method that opens the search view.
2329 mSearchView.setVisibility(View.VISIBLE);
2330 mSearchView.onActionViewExpanded();
2331 mCustomTitleView.setVisibility(View.GONE);
2334 void closeSearch() {
2335 mSearchView.setVisibility(View.GONE);
2336 mSearchView.onActionViewCollapsed();
2337 mCustomTitleView.setVisibility(View.VISIBLE);
2341 * Method that opens the settings activity.
2345 void openSettings() {
2346 Intent settingsIntent = new Intent(NavigationActivity.this,
2347 SettingsPreferences.class);
2348 startActivityForResult(settingsIntent, INTENT_REQUEST_SETTINGS);
2352 * Method that remove the {@link FileSystemObject} from the history
2354 private void removeFromHistory(FileSystemObject fso) {
2355 if (this.mHistory != null) {
2356 int cc = this.mHistory.size() - 1;
2357 for (int i = cc; i >= 0 ; i--) {
2358 History history = this.mHistory.get(i);
2359 if (history.getItem() instanceof NavigationViewInfoParcelable) {
2360 String p0 = fso.getFullPath();
2361 String p1 = ((NavigationViewInfoParcelable) history.getItem()).getCurrentDir();
2362 if (p0.compareTo(p1) == 0) {
2363 this.mHistory.remove(i);
2364 mDrawerHistory.removeViewAt(mDrawerHistory.getChildCount() - i - 1);
2365 mDrawerHistoryEmpty.setVisibility(
2366 mDrawerHistory.getChildCount() == 0 ? View.VISIBLE : View.GONE);
2367 updateHistoryPositions();
2375 * Update the history positions after one of the history is removed from drawer
2377 private void updateHistoryPositions() {
2378 int cc = this.mHistory.size() - 1;
2379 for (int i = 0; i <= cc ; i++) {
2380 History history = this.mHistory.get(i);
2381 history.setPosition(i + 1);
2386 * Method that ask the user to change the access mode prior to crash.
2390 //Show a dialog asking the user
2391 AlertDialog dialog =
2392 DialogHelper.createYesNoDialog(
2394 R.string.msgs_change_to_prompt_access_mode_title,
2395 R.string.msgs_change_to_prompt_access_mode_msg,
2396 new DialogInterface.OnClickListener() {
2398 public void onClick(DialogInterface alertDialog, int which) {
2399 if (which == DialogInterface.BUTTON_NEGATIVE) {
2400 // We don't have any console
2401 // Show exception and exit
2402 DialogHelper.showToast(
2403 NavigationActivity.this,
2404 R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
2409 // Ok. Now try to change to prompt mode. Any crash
2410 // here is a fatal error. We won't have any console to operate.
2413 ConsoleBuilder.changeToNonPrivilegedConsole(NavigationActivity.this);
2416 Preferences.savePreference(
2417 FileManagerSettings.SETTINGS_ACCESS_MODE,
2418 AccessMode.PROMPT, true);
2420 } catch (Exception e) {
2421 // Displays an exception and exit
2422 Log.e(TAG, getString(R.string.msgs_cant_create_console), e);
2423 DialogHelper.showToast(
2424 NavigationActivity.this,
2425 R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
2430 DialogHelper.delegateDialogShow(this, dialog);
2434 * Method that creates a ChRooted environment, protecting the user to break anything in
2438 void createChRooted() {
2439 // If we are in a ChRooted mode, then do nothing
2440 if (this.mChRooted) return;
2441 this.mChRooted = true;
2443 int cc = this.mNavigationViews.length;
2444 for (int i = 0; i < cc; i++) {
2445 this.mNavigationViews[i].createChRooted();
2448 // Remove the selection
2449 cc = this.mNavigationViews.length;
2450 for (int i = 0; i < cc; i++) {
2451 getCurrentNavigationView().onDeselectAll();
2454 // Remove the history (don't allow to access to previous data)
2459 * Method that exits from a ChRooted
2462 void exitChRooted() {
2463 // If we aren't in a ChRooted mode, then do nothing
2464 if (!this.mChRooted) return;
2465 this.mChRooted = false;
2467 int cc = this.mNavigationViews.length;
2468 for (int i = 0; i < cc; i++) {
2469 this.mNavigationViews[i].exitChRooted();
2474 * Method called when a controlled exit is required
2478 // Recycle the navigation views
2479 int cc = this.mNavigationViews.length;
2480 for (int i = 0; i < cc; i++) {
2481 this.mNavigationViews[i].recycle();
2484 FileManagerApplication.destroyBackgroundConsole();
2485 } catch (Throwable ex) {
2489 ConsoleBuilder.destroyConsole();
2490 } catch (Throwable ex) {
2497 * Method that reconfigures the layout for better fit in portrait and landscape modes
2499 private void onLayoutChanged() {
2500 Theme theme = ThemeManager.getCurrentTheme(this);
2501 boolean drawerOpen = mDrawerLayout.isDrawerOpen(Gravity.START);
2503 // Apply only when the orientation was changed
2504 int orientation = getResources().getConfiguration().orientation;
2505 if (this.mOrientation == orientation) return;
2506 this.mOrientation = orientation;
2508 // imitate a closed drawer while layout is rebuilt to avoid NullPointerException
2510 mDrawerLayout.closeDrawer(Gravity.START);
2513 if (this.mOrientation == Configuration.ORIENTATION_LANDSCAPE) {
2515 ViewGroup statusBar = (ViewGroup)findViewById(R.id.navigation_statusbar);
2516 if (statusBar.getParent() != null) {
2517 ViewGroup parent = (ViewGroup) statusBar.getParent();
2518 parent.removeView(statusBar);
2521 // Calculate the action button size (all the buttons must fit in the title bar)
2522 int bw = (int)getResources().getDimension(R.dimen.default_buttom_width);
2523 int abw = this.mActionBar.getChildCount() * bw;
2525 int cc = statusBar.getChildCount();
2526 for (int i = 0; i < cc; i++) {
2527 View child = statusBar.getChildAt(i);
2528 if (child instanceof ButtonItem) {
2532 // Currently there isn't overflow menu
2533 int w = abw + rbw - bw;
2535 // Add to the new location
2536 ViewGroup newParent = (ViewGroup)findViewById(R.id.navigation_title_landscape_holder);
2537 LinearLayout.LayoutParams params =
2538 new LinearLayout.LayoutParams(
2540 ViewGroup.LayoutParams.MATCH_PARENT);
2541 statusBar.setLayoutParams(params);
2542 newParent.addView(statusBar);
2545 theme.setBackgroundDrawable(this, statusBar, "titlebar_drawable"); //$NON-NLS-1$
2548 View holder = findViewById(R.id.navigation_statusbar_portrait_holder);
2549 holder.setVisibility(View.GONE);
2553 ViewGroup statusBar = (ViewGroup)findViewById(R.id.navigation_statusbar);
2554 if (statusBar.getParent() != null) {
2555 ViewGroup parent = (ViewGroup) statusBar.getParent();
2556 parent.removeView(statusBar);
2559 // Add to the new location
2560 ViewGroup newParent = (ViewGroup)findViewById(
2561 R.id.navigation_statusbar_portrait_holder);
2562 LinearLayout.LayoutParams params =
2563 new LinearLayout.LayoutParams(
2564 ViewGroup.LayoutParams.MATCH_PARENT,
2565 ViewGroup.LayoutParams.MATCH_PARENT);
2566 statusBar.setLayoutParams(params);
2567 newParent.addView(statusBar);
2570 theme.setBackgroundDrawable(this, statusBar, "statusbar_drawable"); //$NON-NLS-1$
2573 newParent.setVisibility(View.VISIBLE);
2576 // if drawer was open, imitate reopening
2578 mDrawerToggle.onDrawerOpened(mDrawer);
2583 * Method that removes all the history items that refers to virtual unmounted filesystems
2585 private void removeUnmountedHistory() {
2586 int cc = mHistory.size() - 1;
2587 for (int i = cc; i >= 0; i--) {
2588 History history = mHistory.get(i);
2589 if (history.getItem() instanceof NavigationViewInfoParcelable) {
2590 NavigationViewInfoParcelable navigableInfo =
2591 ((NavigationViewInfoParcelable) history.getItem());
2592 VirtualMountPointConsole vc =
2593 VirtualMountPointConsole.getVirtualConsoleForPath(
2594 navigableInfo.getCurrentDir());
2595 if (vc != null && !vc.isMounted()) {
2597 mDrawerHistory.removeViewAt(mDrawerHistory.getChildCount() - i - 1);
2601 mDrawerHistoryEmpty.setVisibility(
2602 mDrawerHistory.getChildCount() == 0 ? View.VISIBLE : View.GONE);
2603 updateHistoryPositions();
2607 * Method that removes all the selection items that refers to virtual unmounted filesystems
2609 private void removeUnmountedSelection() {
2610 for (NavigationView view : mNavigationViews) {
2611 view.removeUnmountedSelection();
2613 mSelectionBar.setSelection(getNavigationView(mCurrentNavigationView).getSelectedFiles());
2617 * Method that applies the current theme to the activity
2621 int orientation = getResources().getConfiguration().orientation;
2622 Theme theme = ThemeManager.getCurrentTheme(this);
2623 theme.setBaseThemeNoActionBar(this);
2626 // imitate a closed drawer while layout is rebuilt to avoid NullPointerException
2627 boolean drawerOpen = mDrawerLayout.isDrawerOpen(Gravity.START);
2629 mDrawerLayout.closeDrawer(Gravity.START);
2633 View v = findViewById(R.id.navigation_layout);
2634 theme.setBackgroundDrawable(this, v, "background_drawable"); //$NON-NLS-1$
2637 theme.setTitlebarDrawable(this, getActionBar(), "titlebar_drawable"); //$NON-NLS-1$
2639 // Hackery to theme search view
2640 mSearchView = (SearchView) findViewById(R.id.navigation_search_bar);
2641 int searchPlateId = mSearchView.getContext().getResources()
2642 .getIdentifier("android:id/search_plate", null, null);
2643 View searchPlate = mSearchView.findViewById(searchPlateId);
2644 if (searchPlate != null) {
2645 int searchTextId = searchPlate.getContext().getResources()
2646 .getIdentifier("android:id/search_src_text", null, null);
2647 TextView searchText = (TextView) searchPlate.findViewById(searchTextId);
2648 if (searchText != null) {
2649 searchText.setTextColor(Color.WHITE);
2650 searchText.setHintTextColor(Color.WHITE);
2653 int magId = getResources().getIdentifier("android:id/search_mag_icon", null, null);
2654 ImageView magImage = (ImageView) mSearchView.findViewById(magId);
2655 if (magImage != null) {
2656 magImage.setLayoutParams(new LinearLayout.LayoutParams(0, 0));
2660 SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
2661 mSearchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
2662 mSearchView.setIconifiedByDefault(false);
2664 mCustomTitleView = (NavigationCustomTitleView) findViewById(R.id.navigation_title_flipper);
2665 mCustomTitleView.setVisibility(View.VISIBLE);
2668 v = findViewById(R.id.navigation_statusbar);
2669 if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
2670 theme.setBackgroundDrawable(this, v, "titlebar_drawable"); //$NON-NLS-1$
2672 theme.setBackgroundDrawable(this, v, "statusbar_drawable"); //$NON-NLS-1$
2674 v = findViewById(R.id.ab_overflow);
2675 theme.setImageDrawable(this, (ImageView)v, "ab_overflow_drawable"); //$NON-NLS-1$
2676 v = findViewById(R.id.ab_actions);
2677 theme.setImageDrawable(this, (ImageView)v, "ab_actions_drawable"); //$NON-NLS-1$
2678 v = findViewById(R.id.ab_search);
2679 theme.setImageDrawable(this, (ImageView)v, "ab_search_drawable"); //$NON-NLS-1$
2682 v = findViewById(R.id.ab_configuration);
2683 theme.setImageDrawable(this, (ImageView)v, "expander_open_drawable"); //$NON-NLS-1$
2684 v = findViewById(R.id.ab_close);
2685 theme.setImageDrawable(this, (ImageView)v, "expander_close_drawable"); //$NON-NLS-1$
2686 v = findViewById(R.id.ab_sort_mode);
2687 theme.setImageDrawable(this, (ImageView)v, "ab_sort_mode_drawable"); //$NON-NLS-1$
2688 v = findViewById(R.id.ab_layout_mode);
2689 theme.setImageDrawable(this, (ImageView)v, "ab_layout_mode_drawable"); //$NON-NLS-1$
2690 v = findViewById(R.id.ab_view_options);
2691 theme.setImageDrawable(this, (ImageView)v, "ab_view_options_drawable"); //$NON-NLS-1$
2694 v = findViewById(R.id.navigation_selectionbar);
2695 theme.setBackgroundDrawable(this, v, "selectionbar_drawable"); //$NON-NLS-1$
2696 v = findViewById(R.id.ab_selection_done);
2697 theme.setImageDrawable(this, (ImageView)v, "ab_selection_done_drawable"); //$NON-NLS-1$
2698 v = findViewById(R.id.navigation_status_selection_label);
2699 theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2701 // - Navigation drawer
2702 v = findViewById(R.id.history_empty);
2703 theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2705 for (int i=0; i<mDrawerHistory.getChildCount(); i++) {
2706 View item = mDrawerHistory.getChildAt(i);
2708 v = item.findViewById(R.id.history_item_name);
2709 theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2710 v = item.findViewById(R.id.history_item_directory);
2711 theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2715 int cc = this.mNavigationViews.length;
2716 for (int i = 0; i < cc; i++) {
2717 getNavigationView(i).applyTheme();
2720 // if drawer was open, imitate reopening
2722 mDrawerToggle.onDrawerOpened(mDrawer);
2727 * Method that applies the current theme to the tab host
2729 private void applyTabTheme() {
2731 Theme theme = ThemeManager.getCurrentTheme(this);
2733 View v = findViewById(R.id.drawer);
2734 theme.setBackgroundDrawable(this, v, "background_drawable"); //$NON-NLS-1$
2736 v = findViewById(R.id.drawer_bookmarks_tab);
2737 theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2738 v = findViewById(R.id.drawer_history_tab);
2739 theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2741 v = findViewById(R.id.ab_settings);
2742 theme.setImageDrawable(this, (ButtonItem) v, "ab_settings_drawable"); //$NON-NLS-1$
2743 v = findViewById(R.id.ab_clear_history);
2744 theme.setImageDrawable(this, (ButtonItem) v, "ab_delete_drawable"); //$NON-NLS-1$
2747 public void updateActiveDialog(Dialog dialog) {
2748 mActiveDialog = dialog;