package com.door43.util;
import android.os.Environment;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.StringTokenizer;
/**
* This class provides utilites for determine what storage is available to the app.
* This is nessesary because android will not reliably determine the sd card.
* see http://stackoverflow.com/questions/9340332/how-can-i-get-the-list-of-mounted-external-storage-of-android-device
*
*/
public class StorageUtils {
private static final String TAG = "StorageUtils";
public static class StorageInfo {
public final String path;
public final boolean readonly;
public final boolean removable;
public final int number;
StorageInfo(String path, boolean readonly, boolean removable, int number) {
this.path = path;
this.readonly = readonly;
this.removable = removable;
this.number = number;
}
public String getDisplayName() {
StringBuilder res = new StringBuilder();
if (!removable) {
res.append("Internal SD card");
} else if (number > 1) {
res.append("SD card " + number);
} else {
res.append("SD card");
}
if (readonly) {
res.append(" (Read only)");
}
return res.toString();
}
/**
* Returns the name of the mount directory
* @return
*/
public String getMountName() {
String pieces[] = path.split("/");
return pieces[pieces.length-1];
}
}
public static List<StorageInfo> getStorageList() {
List<StorageInfo> list = new ArrayList<StorageInfo>();
String def_path = Environment.getExternalStorageDirectory().getPath();
boolean def_path_removable = Environment.isExternalStorageRemovable();
String def_path_state = Environment.getExternalStorageState();
boolean def_path_available = def_path_state.equals(Environment.MEDIA_MOUNTED)
|| def_path_state.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
boolean def_path_readonly = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED_READ_ONLY);
HashSet<String> paths = new HashSet<String>();
int cur_removable_number = 1;
if (def_path_available) {
paths.add(def_path);
list.add(0, new StorageInfo(def_path, def_path_readonly, def_path_removable, def_path_removable ? cur_removable_number++ : -1));
}
BufferedReader buf_reader = null;
try {
buf_reader = new BufferedReader(new FileReader("/proc/mounts"));
String line;
while ((line = buf_reader.readLine()) != null) {
if (line.contains("vfat") || line.contains("/mnt")) {
StringTokenizer tokens = new StringTokenizer(line, " ");
String unused = tokens.nextToken(); //device
String mount_point = tokens.nextToken(); //mount point
if (paths.contains(mount_point)) {
continue;
}
unused = tokens.nextToken(); //file system
List<String> flags = Arrays.asList(tokens.nextToken().split(",")); //flags
boolean readonly = flags.contains("ro");
if (line.contains("/dev/block/vold")) {
if (!line.contains("/mnt/secure")
&& !line.contains("/mnt/asec")
&& !line.contains("/mnt/obb")
&& !line.contains("/dev/mapper")
&& !line.contains("tmpfs")) {
paths.add(mount_point);
list.add(new StorageInfo(mount_point, readonly, true, cur_removable_number++));
}
}
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (buf_reader != null) {
try {
buf_reader.close();
} catch (IOException ex) {}
}
}
return list;
}
/**
* Returns the storage info for the removeable media if it exists
* @return
*/
public static StorageInfo getRemoveableMediaDevice() {
return getMountDevice("sdcard1");
}
/**
* Returns storage info for a mount device
* @param name the name of the mount device
* @return
*/
public static StorageInfo getMountDevice(String name) {
List<StorageUtils.StorageInfo> storageList = getStorageList();
for(StorageUtils.StorageInfo info:storageList) {
if(info.removable && info.getMountName().equals(name)) {
return info;
}
}
return null;
}
}