package mil.nga.giat.mage.sdk.utils; import android.os.Build; import android.os.Environment; import java.io.File; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Scanner; public class StorageUtility { public enum StorageType { LOCAL("SD Card"), EXTERNAL("External SD Card"); private String name; private StorageType(String name) { this.name = name; } public String getName() { return name; } } public static File getDefaultStorageLocation() { return getDefaultStorageLocation(1); } public static File getDefaultStorageLocation(long bytes) { Map<StorageType, File> map = getWritableStorageLocations(); if (map.isEmpty()) { return null; } File ex = map.get(StorageType.EXTERNAL); if(ex != null && ex.exists() && ex.canWrite() && ex.getUsableSpace() >= bytes) { return ex; } ex = map.get(StorageType.LOCAL); if(ex != null && ex.exists() && ex.canWrite() && ex.getUsableSpace() >= bytes) { return ex; } return null; } public static Map<StorageType, File> getWritableStorageLocations() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { return getAllNewStorageLocations(true); } else { return getAllLegacyStorageLocations(true); } } public static Map<StorageType, File> getReadableStorageLocations() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { return getAllNewStorageLocations(false); } else { return getAllLegacyStorageLocations(false); } } private static Map<StorageType, File> getAllNewStorageLocations(boolean writeable) { Map<StorageType, File> locations = new LinkedHashMap<>(); String externalStorage = System.getenv("EXTERNAL_STORAGE"); if (externalStorage != null) { File externalStorageDir = new File(externalStorage); if (writeable && externalStorageDir.exists() && externalStorageDir.canWrite()) { locations.put(StorageType.LOCAL, externalStorageDir); } if (!writeable && externalStorageDir.exists() && externalStorageDir.canRead()) { locations.put(StorageType.LOCAL, externalStorageDir); } } String secondaryStorage = System.getenv("SECONDARY_STORAGE"); if (secondaryStorage != null){ File secondaryStorageDir = new File(secondaryStorage); if (writeable && secondaryStorageDir.exists() && secondaryStorageDir.canWrite()) { locations.put(StorageType.EXTERNAL, secondaryStorageDir); } if (!writeable && secondaryStorageDir.exists() && secondaryStorageDir.canRead()) { locations.put(StorageType.EXTERNAL, secondaryStorageDir); } } return locations; } /** * @return A map of all storage locations available */ private static Map<StorageType, File> getAllLegacyStorageLocations(boolean writeable) { Map<StorageType, File> map = new LinkedHashMap<>(); List<String> mMounts = new ArrayList<>(); List<String> mVold = new ArrayList<>(); mMounts.add("/mnt/sdcard"); mVold.add("/mnt/sdcard"); try { File mountFile = new File("/proc/mounts"); if (mountFile.exists()) { Scanner scanner = new Scanner(mountFile); while (scanner.hasNext()) { String line = scanner.nextLine(); if (line.startsWith("/dev/block/vold/")) { String[] lineElements = line.split(" "); String element = lineElements[1]; // don't add the default mount path // it's already in the list. if (!element.equals("/mnt/sdcard")) mMounts.add(element); } } scanner.close(); } } catch (Exception e) { e.printStackTrace(); } try { File voldFile = new File("/system/etc/vold.fstab"); if (voldFile.exists()) { Scanner scanner = new Scanner(voldFile); while (scanner.hasNext()) { String line = scanner.nextLine(); if (line.startsWith("dev_mount")) { String[] lineElements = line.split(" "); String element = lineElements[2]; if (element.contains(":")) element = element.substring(0, element.indexOf(":")); if (!element.equals("/mnt/sdcard")) mVold.add(element); } } scanner.close(); } } catch (Exception e) { e.printStackTrace(); } for (int i = 0; i < mMounts.size(); i++) { String mount = mMounts.get(i); if (!mVold.contains(mount)) mMounts.remove(i--); } mVold.clear(); List<String> mountHash = new ArrayList<>(10); for (String mount : mMounts) { File root = new File(mount); if (root.exists() && root.isDirectory() && ((root.canWrite() && writeable) || root.canRead() && !writeable)) { File[] list = root.listFiles(); String hash = "["; if (list != null) { for (File f : list) { hash += f.getName().hashCode() + ":" + f.length() + ", "; } } hash += "]"; if (!mountHash.contains(hash)) { StorageType key = StorageType.LOCAL; if (map.size() == 0) { key = StorageType.LOCAL; } else if (map.size() == 1) { key = StorageType.EXTERNAL; } mountHash.add(hash); map.put(key, root); } } } mMounts.clear(); if (map.isEmpty()) { map.put(StorageType.LOCAL, Environment.getExternalStorageDirectory()); } return map; } }