Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions Library/src/com/matsuhiro/android/download/DownloadTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -310,13 +310,15 @@ private long download() throws NetworkErrorException, IOException,
/*
* check memory
*/
long storage = StorageUtils.getAvailableStorage();
String mFileStorage = StorageUtils.findStoragePathForGivenFile(mFile);
long storageSpace = StorageUtils.getAvailableStorage(mFileStorage);

if (DEBUG) {
Log.i(null, "storage:" + storage + " totalSize:" + length);
Log.v(TAG, "storageSpace: " + storageSpace + "; total file size: " + length);
}

if (length - mPreviousFileSize > storage) {
throw new NoMemoryException("SD card no memory.");
if (length - mPreviousFileSize > storageSpace) {
throw new NoMemoryException("Not enough free space on destination storage.");
}

RandomAccessFile outputStream = new ProgressReportingRandomAccessFile(mTempFile, "rw");
Expand Down
141 changes: 137 additions & 4 deletions Library/src/com/matsuhiro/android/storage/StorageUtils.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@

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.os.Build;
import android.os.Environment;
import android.os.StatFs;
import android.text.TextUtils;
import android.util.Log;

public class StorageUtils {

private static final String TAG = DownloadTask.class.getSimpleName();

public static long getAvailableStorage() {

String storageDirectory = null;
storageDirectory = Environment.getExternalStorageDirectory().toString();
@SuppressWarnings("deprecation")
public static long getAvailableStorage(String storageDirectory) {

try {
StatFs stat = new StatFs(storageDirectory);
Expand All @@ -19,5 +31,126 @@ public static long getAvailableStorage() {
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 findStoragePathForGivenFile(File file) {

String path = file.getAbsolutePath();

String[] storages = getStorageDirectories();
for (int i = 0; i < storages.length; i++) {
if (matchFound(path, storages[i])) {
Log.d(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.d(TAG, "storageInUse: " + alt_storages[i]);
return alt_storages[i];
}
}

return Environment.getExternalStorageDirectory().getPath();
}
}