package com.simplecity.amp_library.utils; import android.os.Environment; import android.support.annotation.WorkerThread; import android.text.TextUtils; import com.simplecity.amp_library.interfaces.FileType; import com.simplecity.amp_library.model.BaseFileObject; import com.simplecity.amp_library.model.FileObject; import com.simplecity.amp_library.model.FolderObject; import com.simplecity.amp_library.model.TagInfo; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; public class FileBrowser { private static final String TAG = "FileBrowser"; private File currentDir; /** * Loads the specified folder. * * @param directory The file object to points to the directory to load. * @return An {@link List<BaseFileObject>} object that holds the data of the specified directory. */ @WorkerThread public List<BaseFileObject> loadDir(File directory) { ThreadUtils.ensureNotOnMainThread(); currentDir = directory; List<BaseFileObject> folderObjects = new ArrayList<>(); List<BaseFileObject> fileObjects = new ArrayList<>(); //Grab a list of all files/subdirs within the specified directory. File[] files = directory.listFiles(FileHelper.getAudioFilter()); if (files != null) { for (File file : files) { BaseFileObject baseFileObject; if (file.isDirectory()) { baseFileObject = new FolderObject(); baseFileObject.path = FileHelper.getPath(file); baseFileObject.name = file.getName(); File[] listOfFiles = file.listFiles(FileHelper.getAudioFilter()); if (listOfFiles != null && listOfFiles.length > 0) { for (File listOfFile : listOfFiles) { if (listOfFile.isDirectory()) { ((FolderObject) baseFileObject).folderCount++; } else { ((FolderObject) baseFileObject).fileCount++; } } } else { continue; } if (!folderObjects.contains(baseFileObject)) { folderObjects.add(baseFileObject); } } else { baseFileObject = new FileObject(); baseFileObject.path = FileHelper.getPath(file); baseFileObject.name = FileHelper.getName(file.getName()); baseFileObject.size = file.length(); ((FileObject) baseFileObject).extension = FileHelper.getExtension(file.getName()); if (TextUtils.isEmpty(((FileObject) baseFileObject).extension)) { continue; } ((FileObject) baseFileObject).tagInfo = new TagInfo(baseFileObject.path); if (!fileObjects.contains(baseFileObject)) { fileObjects.add(baseFileObject); } } } } sortFileObjects(fileObjects); sortFolderObjects(folderObjects); if (!SettingsManager.getInstance().getFolderBrowserFilesAscending()) { Collections.reverse(fileObjects); } if (!SettingsManager.getInstance().getFolderBrowserFoldersAscending()) { Collections.reverse(folderObjects); } folderObjects.addAll(fileObjects); if (!FileHelper.isRootDirectory(currentDir)) { FolderObject parentObject = new FolderObject(); parentObject.fileType = FileType.PARENT; parentObject.name = FileHelper.PARENT_DIRECTORY; parentObject.path = FileHelper.getPath(currentDir) + "/" + FileHelper.PARENT_DIRECTORY; folderObjects.add(0, parentObject); } return folderObjects; } public File getCurrentDir() { return currentDir; } @WorkerThread public File getInitialDir() { ThreadUtils.ensureNotOnMainThread(); File dir; String[] files; String settingsDir = SettingsManager.getInstance().getFolderBrowserInitialDir(); if (settingsDir != null) { File file = new File(settingsDir); if (file.exists()) { return file; } } dir = getRootDir(); files = dir.list((dir1, filename) -> dir1.isDirectory() && filename.toLowerCase().contains("storage")); if (files != null && files.length > 0) { dir = new File(dir + "/" + files[0]); //If there's an extsdcard path in our base dir, let's navigate to that. External SD cards are cool. files = dir.list((dir1, filename) -> dir1.isDirectory() && filename.toLowerCase().contains("extsdcard")); if (files != null && files.length > 0) { dir = new File(dir + "/" + files[0]); } else { //If we have external storage, use that as our initial dir if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { dir = Environment.getExternalStorageDirectory(); } } } else { //If we have external storage, use that as our initial dir if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { dir = Environment.getExternalStorageDirectory(); } } //Whether or not there was an sdcard, let's see if there's a 'music' dir for us to navigate to if (dir != null) { files = dir.list((dir1, filename) -> dir1.isDirectory() && filename.toLowerCase().contains("music")); } if (files != null && files.length > 0) { dir = new File(dir + "/" + files[0]); } return dir; } public File getRootDir() { return new File("/"); } public void sortFolderObjects(List<BaseFileObject> baseFileObjects) { switch (SettingsManager.getInstance().getFolderBrowserFoldersSortOrder()) { case SortManager.SortFolders.COUNT: Collections.sort(baseFileObjects, fileCountComparator()); Collections.sort(baseFileObjects, folderCountComparator()); break; case SortManager.SortFolders.DEFAULT: default: Collections.sort(baseFileObjects, filenameComparator()); break; } } public void sortFileObjects(List<BaseFileObject> baseFileObjects) { switch (SettingsManager.getInstance().getFolderBrowserFilesSortOrder()) { case SortManager.SortFiles.SIZE: Collections.sort(baseFileObjects, sizeComparator()); break; case SortManager.SortFiles.FILE_NAME: Collections.sort(baseFileObjects, filenameComparator()); break; case SortManager.SortFiles.ARTIST_NAME: Collections.sort(baseFileObjects, artistNameComparator()); break; case SortManager.SortFiles.ALBUM_NAME: Collections.sort(baseFileObjects, albumNameComparator()); break; case SortManager.SortFiles.TRACK_NAME: Collections.sort(baseFileObjects, trackNameComparator()); break; case SortManager.SortFiles.DEFAULT: default: Collections.sort(baseFileObjects, trackNumberComparator()); Collections.sort(baseFileObjects, albumNameComparator()); Collections.sort(baseFileObjects, artistNameComparator()); break; } } private Comparator sizeComparator() { return (Comparator<BaseFileObject>) (lhs, rhs) -> (int) (rhs.size - lhs.size); } private Comparator filenameComparator() { return (Comparator<BaseFileObject>) (lhs, rhs) -> lhs.name.compareToIgnoreCase(rhs.name); } // private Comparator durationComparator() { // return (Comparator<FileObject>) (lhs, rhs) -> (int) (rhs.duration - lhs.duration); // } private Comparator trackNumberComparator() { return (Comparator<FileObject>) (lhs, rhs) -> lhs.tagInfo.trackNumber - rhs.tagInfo.trackNumber; } private Comparator folderCountComparator() { return (Comparator<FolderObject>) (lhs, rhs) -> rhs.folderCount - lhs.folderCount; } private Comparator fileCountComparator() { return (Comparator<FolderObject>) (lhs, rhs) -> rhs.fileCount - lhs.fileCount; } private Comparator artistNameComparator() { return (Comparator<FileObject>) (lhs, rhs) -> { if (lhs.tagInfo.artistName == null || rhs.tagInfo.artistName == null) { return nullCompare(lhs.tagInfo.artistName, rhs.tagInfo.artistName); } return lhs.tagInfo.artistName.compareToIgnoreCase(rhs.tagInfo.artistName); }; } private Comparator albumNameComparator() { return (Comparator<FileObject>) (lhs, rhs) -> { if (lhs.tagInfo.albumName == null || rhs.tagInfo.albumName == null) { return nullCompare(lhs.tagInfo.albumName, rhs.tagInfo.albumName); } return lhs.tagInfo.albumName.compareToIgnoreCase(rhs.tagInfo.albumName); }; } private Comparator trackNameComparator() { return (Comparator<FileObject>) (lhs, rhs) -> { if (lhs.tagInfo.trackName == null || rhs.tagInfo.trackName == null) { return nullCompare(lhs.tagInfo.trackName, rhs.tagInfo.trackName); } return lhs.tagInfo.trackName.compareToIgnoreCase(rhs.tagInfo.trackName); }; } <T extends Comparable<T>> int nullCompare(T a, T b) { return a == null ? (b == null ? 0 : Integer.MIN_VALUE) : (b == null ? Integer.MAX_VALUE : a.compareTo(b)); } }