package com.matsuhiro.android.storage;
import java.io.File;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.matsuhiro.android.download.DownloadTask;
import android.annotation.SuppressLint;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;
import android.text.TextUtils;
import android.util.Log;
@SuppressLint("SdCardPath")
public class StorageUtils {
private static final String TAG = DownloadTask.class.getSimpleName();
@SuppressWarnings("deprecation")
public static long getAvailableStorage(String storageDirectory) {
try {
StatFs stat = new StatFs(storageDirectory);
long avaliableSize = ((long) stat.getAvailableBlocks() * (long) stat.getBlockSize());
return avaliableSize;
} catch (RuntimeException ex) {
return 0;
}
}
/* method getStorageDirectories() from Stack Overflow:
*
* http://stackoverflow.com/a/18871043/1865860
*
* Q: http://stackoverflow.com/users/290163/romulus-urakagi-tsai
* A: http://stackoverflow.com/users/2791190/dmitriy-lozenko
*/
private static final Pattern DIR_SEP = Pattern.compile("/");
/**
* Raturns all available SD-Cards in the system (include emulated)
*
* Warning: Hack! Based on Android source code of version 4.3 (API 18)
* Because there is no standart way to get it.
* TODO: Test on future Android versions 4.4+
*
* @return paths to all available SD-Cards in the system (include emulated)
*/
public static String[] getStorageDirectories() {
// Final set of paths
final Set<String> rv = new HashSet<String>();
// Primary physical SD-CARD (not emulated)
final String rawExternalStorage = System.getenv("EXTERNAL_STORAGE");
// All Secondary SD-CARDs (all exclude primary) separated by ":"
final String rawSecondaryStoragesStr = System.getenv("SECONDARY_STORAGE");
// Primary emulated SD-CARD
final String rawEmulatedStorageTarget = System.getenv("EMULATED_STORAGE_TARGET");
if(TextUtils.isEmpty(rawEmulatedStorageTarget)) {
// Device has physical external storage; use plain paths.
if(TextUtils.isEmpty(rawExternalStorage)) {
// EXTERNAL_STORAGE undefined; falling back to default.
rv.add("/storage/sdcard0");
} else {
rv.add(rawExternalStorage);
}
} else {
// Device has emulated storage; external storage paths should have
// userId burned into them.
final String rawUserId;
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
rawUserId = "";
} else {
final String path = Environment.getExternalStorageDirectory().getAbsolutePath();
final String[] folders = DIR_SEP.split(path);
final String lastFolder = folders[folders.length - 1];
boolean isDigit = false;
try {
Integer.valueOf(lastFolder);
isDigit = true;
} catch(NumberFormatException ignored) {
//
}
rawUserId = isDigit ? lastFolder : "";
}
// /storage/emulated/0[1,2,...]
if(TextUtils.isEmpty(rawUserId)) {
rv.add(rawEmulatedStorageTarget);
} else {
rv.add(rawEmulatedStorageTarget + File.separator + rawUserId);
}
}
// Add all secondary storages
if(!TextUtils.isEmpty(rawSecondaryStoragesStr)) {
// All Secondary SD-CARDs splited into array
final String[] rawSecondaryStorages = rawSecondaryStoragesStr.split(File.pathSeparator);
Collections.addAll(rv, rawSecondaryStorages);
}
return rv.toArray(new String[rv.size()]);
}
private static boolean matchFound(String text, String regEx) {
Pattern pattern = Pattern.compile(regEx);
Matcher matcher = pattern.matcher(text);
if (matcher.find()) return true;
return false;
}
public static String[] getAlternateStorageDirectories() {
return new String[] {
"/mnt/sdcard",
"/emmc",
"/mnt/sdcard/external_sd",
"/mnt/external_sd",
"/sdcard/sd",
"/mnt/sdcard/bpemmctest",
"/mnt/sdcard/_ExternalSD",
"/mnt/sdcard-ext",
"/mnt/Removable/MicroSD",
"/Removable/MicroSD",
"/mnt/external1",
"/mnt/extSdCard",
"/mnt/extsd",
"/mnt/usb_storage",
"/extSdCard",
"/mnt/extSdCard",
"/mnt/UsbDriveA",
"/mnt/UsbDriveB", };
}
public static String findStoragePath(File file) {
String path = file.getAbsolutePath();
String[] storages = getStorageDirectories();
for (int i = 0; i < storages.length; i++) {
if (matchFound(path, storages[i])) {
Log.v(TAG, "storageInUse: " + storages[i]);
return storages[i];
}
}
String[] alt_storages = getAlternateStorageDirectories();
for (int i = 0; i < alt_storages.length; i++) {
if (matchFound(path, alt_storages[i])) {
Log.v(TAG, "storageInUse: " + alt_storages[i]);
return alt_storages[i];
}
}
return Environment.getExternalStorageDirectory().getPath();
}
}