}
} else if (intent.getAction().compareTo(
- FileManagerSettings.INTENT_FILE_CHANGED) == 0) {
- // Retrieve the file that was changed
- String file =
- intent.getStringExtra(FileManagerSettings.EXTRA_FILE_CHANGED_KEY);
- try {
- FileSystemObject fso = CommandHelper.getFileInfo(context, file, null);
- if (fso != null) {
- getCurrentNavigationView().refresh(fso);
- }
- } catch (Exception e) {
- ExceptionUtil.translateException(context, e, true, false);
- }
-
- } else if (intent.getAction().compareTo(
FileManagerSettings.INTENT_THEME_CHANGED) == 0) {
applyTheme();
if (curDir != null) {
VirtualMountPointConsole vc = VirtualMountPointConsole.getVirtualConsoleForPath(
mNavigationViews[mCurrentNavigationView].getCurrentDir());
- getCurrentNavigationView().refresh(true);
if (vc != null && !vc.isMounted()) {
onRequestBookmarksRefresh();
removeUnmountedHistory();
if (searchInfo != null && searchInfo.isSuccessNavigation()) {
//Navigate to previous history
back();
- } else {
- // I don't know is the search view was changed, so try to do a refresh
- // of the navigation view
- getCurrentNavigationView().refresh(true);
}
}
// reset bookmarks list to default as the user could have set a
*/
@Override
public void onRequestRefresh(Object o, boolean clearSelection) {
- if (o instanceof FileSystemObject) {
- // Refresh only the item
- this.getCurrentNavigationView().refresh((FileSystemObject)o);
- } else if (o == null) {
- // Refresh all
- getCurrentNavigationView().refresh();
- }
if (clearSelection) {
this.getCurrentNavigationView().onDeselectAll();
}
@Override
public void onRequestRemove(Object o, boolean clearSelection) {
if (o instanceof FileSystemObject) {
- // Remove from view
- this.getCurrentNavigationView().removeItem((FileSystemObject)o);
-
//Remove from history
removeFromHistory((FileSystemObject)o);
- } else {
- onRequestRefresh(null, clearSelection);
}
if (clearSelection) {
this.getCurrentNavigationView().onDeselectAll();
}
} catch (Exception e) {
- // Notify the user
+ // Do nothing, objects should be removed by the FileObserver in NavigationView
ExceptionUtil.translateException(this, e);
-
- // Remove the object
- if (e instanceof FileNotFoundException || e instanceof NoSuchFileOrDirectory) {
- // If have a FileSystemObject reference then there is no need to search
- // the path (less resources used)
- if (item instanceof FileSystemObject) {
- getCurrentNavigationView().removeItem((FileSystemObject)item);
- } else {
- getCurrentNavigationView().removeItem((String)item);
- }
- }
return;
}
import android.content.SharedPreferences;
import android.content.res.TypedArray;
import android.os.AsyncTask;
+import android.os.FileObserver;
import android.os.storage.StorageVolume;
import android.util.AttributeSet;
import android.util.Log;
// Restrictions
private Map<DisplayRestrictions, Object> mRestrictions;
+ private FileObserver mCurrentDirObserver;
+
/**
* @hide
*/
public void recycle() {
if (this.mAdapter != null) {
this.mAdapter.dispose();
+ this.mCurrentDirObserver.stopWatching();
}
}
}
/**
- * Method that removes a {@link FileSystemObject} from the view
- *
- * @param fso The file system object
- */
- public void removeItem(FileSystemObject fso) {
- // Delete also from internal list
- if (fso != null) {
- int cc = this.mFiles.size()-1;
- for (int i = cc; i >= 0; i--) {
- FileSystemObject f = this.mFiles.get(i);
- if (f != null && f.compareTo(fso) == 0) {
- this.mFiles.remove(i);
- break;
- }
- }
- }
- this.mAdapter.remove(fso);
- }
-
- /**
- * Method that removes a file system object from his path from the view
- *
- * @param path The file system object path
- */
- public void removeItem(String path) {
- FileSystemObject fso = this.mAdapter.getItem(path);
- if (fso != null) {
- this.mAdapter.remove(fso);
- }
- }
-
- /**
* Method that returns the current directory.
*
* @return String The current directory
final String newDir, final boolean addToHistory,
final boolean reload, final boolean useCurrent,
final SearchInfoParcelable searchInfo, final FileSystemObject scrollTo) {
+ if (mCurrentDirObserver != null) {
+ mCurrentDirObserver.stopWatching();
+ mCurrentDirObserver = null;
+ }
NavigationTask task = new NavigationTask(useCurrent, addToHistory, reload,
searchInfo, scrollTo, mRestrictions, mChRooted);
task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, newDir);
void onPostExecuteTask(
List<FileSystemObject> files, boolean addToHistory, boolean isNewHistory,
boolean hasChanged, SearchInfoParcelable searchInfo,
- String newDir, final FileSystemObject scrollTo) {
+ final String newDir, final FileSystemObject scrollTo) {
try {
//Check that there is not errors and have some data
if (files == null) {
//The current directory is now the "newDir"
this.mCurrentDir = newDir;
+ mCurrentDirObserver = new FileObserver(newDir) {
+ @Override
+ public void onEvent(int event, final String path) {
+ Runnable runnable = null;
+ final String fullPath = newDir + '/' + path;
+ // This is done because the implementation doesn't match the documentation
+ // for FileObserver and we are given undocumented flags.
+ event &= FileObserver.ALL_EVENTS;
+
+ switch (event) {
+ case FileObserver.CREATE:
+ case FileObserver.MOVED_TO: {
+ final FileSystemObject fso = FileHelper.createFileSystemObject(
+ new File(fullPath));
+
+ if (FileHelper.shouldShow(fso, mRestrictions, mChRooted)) {
+ runnable = new Runnable() {
+ @Override
+ public void run() {
+ mAdapter.add(fso);
+ // TODO: refactor to move this off of UI thread
+ mAdapter.sort(FileHelper.getSortComparator());
+ }
+ };
+ break;
+ }
+ } case FileObserver.DELETE:
+ case FileObserver.MOVED_FROM: {
+ runnable = new Runnable() {
+ @Override
+ public void run() {
+ mAdapter.remove(mAdapter.getItem(fullPath));
+ }
+ };
+ break;
+ } case FileObserver.DELETE_SELF: {
+ // TODO: Actually handle this
+ break;
+
+ } case FileObserver.MODIFY: {
+ runnable = new Runnable() {
+ @Override
+ public void run() {
+ FileHelper.updateFileSystemObject(mAdapter.getItem(fullPath));
+ mAdapter.notifyDataSetChanged();
+ }
+ };
+ break;
+ }
+ default:
+ Log.w(TAG, "Unknown event " + event + " for " + fullPath);
+ }
+
+ if (runnable != null) {
+ post(runnable);
+ }
+ }
+ };
+ mCurrentDirObserver.startWatching();
+
if (this.mOnDirectoryChangedListener != null) {
FileSystemObject dir = FileHelper.createFileSystemObject(new File(newDir));
this.mOnDirectoryChangedListener.onDirectoryChanged(dir);
*/
@Override
public void onRequestRefresh(Object o, boolean clearSelection) {
- if (o instanceof FileSystemObject) {
- refresh((FileSystemObject)o);
- } else if (o == null) {
- refresh();
- }
if (clearSelection) {
onDeselectAll();
}
*/
@Override
public void onRequestRemove(Object o, boolean clearSelection) {
- if (o != null && o instanceof FileSystemObject) {
- removeItem((FileSystemObject)o);
- } else {
- onRequestRefresh(null, clearSelection);
- }
if (clearSelection) {
onDeselectAll();
}
return fso;
}
+
+ public static boolean shouldShow(FileSystemObject file,
+ Map<DisplayRestrictions, Object> restrictions,
+ boolean chRooted) {
+ //Retrieve user preferences
+ SharedPreferences prefs = Preferences.getSharedPreferences();
+ FileManagerSettings showHiddenPref = FileManagerSettings.SETTINGS_SHOW_HIDDEN;
+ FileManagerSettings showSystemPref = FileManagerSettings.SETTINGS_SHOW_SYSTEM;
+ FileManagerSettings showSymlinksPref = FileManagerSettings.SETTINGS_SHOW_SYMLINKS;
+
+ //Hidden files
+ if (!prefs.getBoolean(
+ showHiddenPref.getId(),
+ ((Boolean)showHiddenPref.getDefaultValue()).booleanValue()) || chRooted) {
+ if (file.isHidden()) {
+ return false;
+ }
+ }
+
+ //System files
+ if (!prefs.getBoolean(
+ showSystemPref.getId(),
+ ((Boolean)showSystemPref.getDefaultValue()).booleanValue()) || chRooted) {
+ if (file instanceof SystemFile) {
+ return false;
+ }
+ }
+
+ //Symlinks files
+ if (!prefs.getBoolean(
+ showSymlinksPref.getId(),
+ ((Boolean)showSymlinksPref.getDefaultValue()).booleanValue()) || chRooted) {
+ if (file instanceof Symlink) {
+ return false;
+ }
+ }
+
+ // Restrictions (only apply to files)
+ if (restrictions != null) {
+ if (!isDirectory(file)) {
+ if (!isDisplayAllowed(file, restrictions)) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ public static Comparator<FileSystemObject> getSortComparator() {
+
+ //Retrieve user preferences
+ SharedPreferences prefs = Preferences.getSharedPreferences();
+ FileManagerSettings sortModePref = FileManagerSettings.SETTINGS_SORT_MODE;
+ FileManagerSettings showDirsFirstPref = FileManagerSettings.SETTINGS_SHOW_DIRS_FIRST;
+
+ final boolean showDirsFirst =
+ prefs.getBoolean(
+ showDirsFirstPref.getId(),
+ ((Boolean)showDirsFirstPref.getDefaultValue()).booleanValue());
+ final NavigationSortMode sortMode =
+ NavigationSortMode.fromId(
+ prefs.getInt(sortModePref.getId(),
+ ((ObjectIdentifier) sortModePref.getDefaultValue()).getId()));
+
+ return new Comparator<FileSystemObject>() {
+ @Override
+ public int compare(FileSystemObject lhs, FileSystemObject rhs) {
+ //Parent directory always goes first
+ boolean isLhsParentDirectory = lhs instanceof ParentDirectory;
+ boolean isRhsParentDirectory = rhs instanceof ParentDirectory;
+ if (isLhsParentDirectory || isRhsParentDirectory) {
+ if (isLhsParentDirectory && isRhsParentDirectory) {
+ return 0;
+ }
+ return (isLhsParentDirectory) ? -1 : 1;
+ }
+
+ //Need to sort directory first?
+ if (showDirsFirst) {
+ boolean isLhsDirectory = FileHelper.isDirectory(lhs);
+ boolean isRhsDirectory = FileHelper.isDirectory(rhs);
+ if (isLhsDirectory || isRhsDirectory) {
+ if (isLhsDirectory && isRhsDirectory) {
+ //Apply sort mode
+ return FileHelper.doCompare(lhs, rhs, sortMode);
+ }
+ return (isLhsDirectory) ? -1 : 1;
+ }
+ }
+
+ //Apply sort mode
+ return FileHelper.doCompare(lhs, rhs, sortMode);
+ }
+ };
+ }
+
/**
* Method that applies the configuration modes to the listed files
* (sort mode, hidden files, ...).
public static List<FileSystemObject> applyUserPreferences(
List<FileSystemObject> files, Map<DisplayRestrictions, Object> restrictions,
boolean noSort, boolean chRooted) {
- //Retrieve user preferences
- SharedPreferences prefs = Preferences.getSharedPreferences();
- FileManagerSettings sortModePref = FileManagerSettings.SETTINGS_SORT_MODE;
- FileManagerSettings showDirsFirstPref = FileManagerSettings.SETTINGS_SHOW_DIRS_FIRST;
- FileManagerSettings showHiddenPref = FileManagerSettings.SETTINGS_SHOW_HIDDEN;
- FileManagerSettings showSystemPref = FileManagerSettings.SETTINGS_SHOW_SYSTEM;
- FileManagerSettings showSymlinksPref = FileManagerSettings.SETTINGS_SHOW_SYMLINKS;
//Remove all unnecessary files (no required by the user)
int cc = files.size();
for (int i = cc - 1; i >= 0; i--) {
- FileSystemObject file = files.get(i);
-
- //Hidden files
- if (!prefs.getBoolean(
- showHiddenPref.getId(),
- ((Boolean)showHiddenPref.getDefaultValue()).booleanValue()) || chRooted) {
- if (file.isHidden()) {
- files.remove(i);
- continue;
- }
- }
-
- //System files
- if (!prefs.getBoolean(
- showSystemPref.getId(),
- ((Boolean)showSystemPref.getDefaultValue()).booleanValue()) || chRooted) {
- if (file instanceof SystemFile) {
- files.remove(i);
- continue;
- }
- }
-
- //Symlinks files
- if (!prefs.getBoolean(
- showSymlinksPref.getId(),
- ((Boolean)showSymlinksPref.getDefaultValue()).booleanValue()) || chRooted) {
- if (file instanceof Symlink) {
- files.remove(i);
- continue;
- }
- }
-
- // Restrictions (only apply to files)
- if (restrictions != null) {
- if (!isDirectory(file)) {
- if (!isDisplayAllowed(file, restrictions)) {
- files.remove(i);
- continue;
- }
- }
+ if (!shouldShow(files.get(i), restrictions, chRooted)) {
+ files.remove(i);
}
}
//Apply sort mode
if (!noSort) {
- final boolean showDirsFirst =
- prefs.getBoolean(
- showDirsFirstPref.getId(),
- ((Boolean)showDirsFirstPref.getDefaultValue()).booleanValue());
- final NavigationSortMode sortMode =
- NavigationSortMode.fromId(
- prefs.getInt(sortModePref.getId(),
- ((ObjectIdentifier)sortModePref.getDefaultValue()).getId()));
- Collections.sort(files, new Comparator<FileSystemObject>() {
- @Override
- public int compare(FileSystemObject lhs, FileSystemObject rhs) {
- //Parent directory always goes first
- boolean isLhsParentDirectory = lhs instanceof ParentDirectory;
- boolean isRhsParentDirectory = rhs instanceof ParentDirectory;
- if (isLhsParentDirectory || isRhsParentDirectory) {
- if (isLhsParentDirectory && isRhsParentDirectory) {
- return 0;
- }
- return (isLhsParentDirectory) ? -1 : 1;
- }
-
- //Need to sort directory first?
- if (showDirsFirst) {
- boolean isLhsDirectory = FileHelper.isDirectory(lhs);
- boolean isRhsDirectory = FileHelper.isDirectory(rhs);
- if (isLhsDirectory || isRhsDirectory) {
- if (isLhsDirectory && isRhsDirectory) {
- //Apply sort mode
- return FileHelper.doCompare(lhs, rhs, sortMode);
- }
- return (isLhsDirectory) ? -1 : 1;
- }
- }
-
- //Apply sort mode
- return FileHelper.doCompare(lhs, rhs, sortMode);
- }
-
- });
+ Collections.sort(files, getSortComparator());
}
//Return the files
return relative.toString() + s1.substring(s2.length());
}
+ private static void applyFileToFileSystemObject(File file, FileSystemObject fso) {
+ // The user and group name of the files. Use the defaults one for sdcards
+ final String USER = "root"; //$NON-NLS-1$
+ final String GROUP = "sdcard_r"; //$NON-NLS-1$
+
+ // The user and group name of the files. In ChRoot, aosp give restrict access to
+ // this user and group. This applies for permission also. This has no really much
+ // interest if we not allow to change the permissions
+ AID userAID = AIDHelper.getAIDFromName(USER);
+ AID groupAID = AIDHelper.getAIDFromName(GROUP);
+ User user = new User(userAID.getId(), userAID.getName());
+ Group group = new Group(groupAID.getId(), groupAID.getName());
+ Permissions perm = file.isDirectory()
+ ? Permissions.createDefaultFolderPermissions()
+ : Permissions.createDefaultFilePermissions();
+
+ // Build a directory?
+ Date lastModified = new Date(file.lastModified());
+
+ fso.setName(file.getName());
+ fso.setParent(file.getParent());
+ fso.setUser(user);
+ fso.setGroup(group);
+ fso.setPermissions(perm);
+ fso.setLastModifiedTime(lastModified);
+ fso.setLastAccessedTime(lastModified);
+ fso.setLastChangedTime(lastModified);
+ }
+
/**
* Method that creates a {@link FileSystemObject} from a {@link File}
*
*/
public static FileSystemObject createFileSystemObject(File file) {
try {
- // The user and group name of the files. Use the defaults one for sdcards
- final String USER = "root"; //$NON-NLS-1$
- final String GROUP = "sdcard_r"; //$NON-NLS-1$
-
- // The user and group name of the files. In ChRoot, aosp give restrict access to
- // this user and group. This applies for permission also. This has no really much
- // interest if we not allow to change the permissions
- AID userAID = AIDHelper.getAIDFromName(USER);
- AID groupAID = AIDHelper.getAIDFromName(GROUP);
- User user = new User(userAID.getId(), userAID.getName());
- Group group = new Group(groupAID.getId(), groupAID.getName());
- Permissions perm = file.isDirectory()
- ? Permissions.createDefaultFolderPermissions()
- : Permissions.createDefaultFilePermissions();
-
- // Build a directory?
- Date lastModified = new Date(file.lastModified());
- if (file.isDirectory()) {
- return
- new Directory(
- file.getName(),
- file.getParent(),
- user, group, perm,
- lastModified, lastModified, lastModified); // The only date we have
- }
-
- // Build a regular file
- return
- new RegularFile(
- file.getName(),
- file.getParent(),
- user, group, perm,
- file.length(),
- lastModified, lastModified, lastModified); // The only date we have
+ FileSystemObject fso = file.isDirectory() ? new Directory() : new RegularFile();
+ applyFileToFileSystemObject(file, fso);
+ return fso;
} catch (Exception e) {
Log.e(TAG, "Exception retrieving the fso", e); //$NON-NLS-1$
}
return null;
}
+
+ /**
+ * Method that updates a {@link FileSystemObject}
+ *
+ * @param fso The {@link FileSystemObject} to update
+ */
+ public static void updateFileSystemObject(FileSystemObject fso) {
+ try {
+ applyFileToFileSystemObject(new File(fso.getFullPath()), fso);
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to apply changes to " + fso.getFullPath(), e);
+ }
+ }
+
/**
* Method that copies recursively to the destination
*