/** * List directories in subtree, limited by runtime and depth; remove empty branches (w/o books). * * @param root is directory to start with * @param maxDepth is maximum depth * @param limitTs is limit for android.os.SystemClock.uptimeMillis() * @return true if completed, false if stopped by limit. */ public boolean listSubtrees(FileInfo root, int maxDepth, long limitTs) { for (int depth = 1; depth <= maxDepth; depth++) { boolean res = listSubtree(root, depth, limitTs); if (res) return true; long ts = android.os.SystemClock.uptimeMillis(); if (ts > limitTs) return false; // limited by time // iterate deeper } return false; // limited by depth }
/** * List directories in subtree, limited by runtime and depth; remove empty branches (w/o books). * * @param root is directory to start with * @param maxDepth is maximum depth * @param limitTs is limit for android.os.SystemClock.uptimeMillis() * @return true if completed, false if stopped by limit. */ private boolean listSubtree(FileInfo root, int maxDepth, long limitTs) { long ts = android.os.SystemClock.uptimeMillis(); if (ts > limitTs || maxDepth <= 0) return false; listDirectory(root); for (int i = root.dirCount() - 1; i >= -0; i--) { boolean res = listSubtree(root.getDir(i), maxDepth - 1, limitTs); if (!res) return false; } if (mHideEmptyDirs) root.removeEmptyDirs(); return true; }
/** * Lists all directories from root to directory of specified file, returns found directory. * * @param file * @param root * @return */ public FileInfo findParent(FileInfo file, FileInfo root) { FileInfo parent = findParentInternal(file, root); if (parent == null) { autoAddRootForFile(new File(file.pathname)); parent = findParentInternal(file, root); if (parent == null) { L.e("Cannot find root directory for file " + file.pathname); return null; } } long maxTs = android.os.SystemClock.uptimeMillis() + MAX_DIR_LIST_TIME; listSubtrees(root, mHideEmptyDirs ? 5 : 1, maxTs); return parent; }
/** * Scan single directory for dir and file properties in background thread. * * @param baseDir is directory to scan * @param readyCallback is called on completion * @param recursiveScan is true to scan subdirectories recursively, false to scan current * directory only * @param scanControl is to stop long scanning */ public void scanDirectory( final CRDBService.LocalBinder db, final FileInfo baseDir, final Runnable readyCallback, final boolean recursiveScan, final ScanControl scanControl) { // Call in GUI thread only! BackgroundThread.ensureGUI(); log.d("scanDirectory(" + baseDir.getPathName() + ") " + (recursiveScan ? "recursive" : "")); listDirectory(baseDir); listSubtree(baseDir, 2, android.os.SystemClock.uptimeMillis() + 700); if ((!getDirScanEnabled() || baseDir.isScanned) && !recursiveScan) { readyCallback.run(); return; } Engine.ProgressControl progress = engine.createProgress(recursiveScan ? 0 : R.string.progress_scanning); scanDirectoryFiles( db, baseDir, scanControl, progress, new Runnable() { @Override public void run() { // GUI thread onDirectoryContentChanged(baseDir); try { if (scanControl.isStopped()) { // scan is stopped readyCallback.run(); return; } else { baseDir.isScanned = true; if (recursiveScan) { if (scanControl.isStopped()) { // scan is stopped readyCallback.run(); return; } // make list of subdirectories to scan final ArrayList<FileInfo> dirsToScan = new ArrayList<FileInfo>(); for (int i = baseDir.dirCount() - 1; i >= 0; i--) { File dir = new File(baseDir.getDir(i).getPathName()); if (!engine.getPathCorrector().isRecursivePath(dir)) dirsToScan.add(baseDir.getDir(i)); } final Runnable dirIterator = new Runnable() { @Override public void run() { // process next directory from list if (dirsToScan.size() == 0 || scanControl.isStopped()) { readyCallback.run(); return; } final FileInfo dir = dirsToScan.get(0); dirsToScan.remove(0); final Runnable callback = this; BackgroundThread.instance() .postGUI( new Runnable() { @Override public void run() { scanDirectory(db, dir, callback, true, scanControl); } }); } }; dirIterator.run(); } else { readyCallback.run(); } } } catch (Exception e) { // treat as finished readyCallback.run(); } } }); }