package in.srain.cube.file;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.AssetManager;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.Environment;
import android.os.StatFs;
import in.srain.cube.util.Version;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class FileUtil {
/**
* Get a usable cache directory (external if available, internal otherwise).
* .
* Check if media is mounted or storage is built-in, if so, try and use external cache folder
* otherwise use internal cache folder
* .
* If both of them can not meet the requirement, use the bigger one.
*
* @param context The context to use
* @param uniqueName A unique folder name to append to the cache folder
* @return The cache folder
*/
public static CacheDirInfo getDiskCacheDir(Context context, String uniqueName, long requireSpace) {
File sdPath = null;
File internalPath = null;
Long sdCardFree = 0L;
boolean usingInternal = false;
if (hasSDCardMounted()) {
sdPath = getExternalCacheDir(context);
sdCardFree = getUsableSpace(sdPath);
}
CacheDirInfo cacheDirInfo = new CacheDirInfo();
cacheDirInfo.requireSize = requireSpace;
// sd card can not meet the requirement
// try to use the build-in storage
if (sdPath == null || sdCardFree < requireSpace) {
internalPath = context.getCacheDir();
long internalFree = getUsableSpace(internalPath);
// both lower then requirement, choose the bigger one
if (internalFree < requireSpace) {
if (internalFree > sdCardFree) {
usingInternal = true;
cacheDirInfo.realSize = internalFree;
} else {
usingInternal = false;
cacheDirInfo.realSize = sdCardFree;
}
cacheDirInfo.isNotEnough = true;
} else {
usingInternal = true;
cacheDirInfo.realSize = requireSpace;
}
} else {
usingInternal = false;
cacheDirInfo.realSize = requireSpace;
}
cacheDirInfo.isInternal = usingInternal;
if (usingInternal) {
cacheDirInfo.path = new File(internalPath.getPath() + File.separator + uniqueName);
} else {
cacheDirInfo.path = new File(sdPath.getPath() + File.separator + uniqueName);
}
return cacheDirInfo;
}
/**
* Get the external application cache directory.
*
* @param context The context to use
* @return The external cache folder : /storage/sdcard0/Android/data/com.srain.sdk/cache
*/
@TargetApi(VERSION_CODES.FROYO)
public static File getExternalCacheDir(Context context) {
if (Version.hasFroyo()) {
File path = context.getExternalCacheDir();
// In some case, even the sd card is mounted, getExternalCacheDir will return null, may be it is nearly full.
if (path != null) {
return path;
}
}
// Before Froyo or the path is null, we need to construct the external cache folder ourselves
final String cacheDir = "/Android/data/" + context.getPackageName() + "/cache/";
return new File(Environment.getExternalStorageDirectory().getPath() + cacheDir);
}
/**
* Check how much usable space is available at a given path.
*
* @param path The path to check
* @return The space available in bytes by user, not by root, -1 means path is null, 0 means path is not exist.
*/
@SuppressWarnings("deprecation")
@TargetApi(VERSION_CODES.GINGERBREAD)
public static long getUsableSpace(File path) {
if (path == null) {
return -1;
}
if (Version.hasGingerbread()) {
return path.getUsableSpace();
} else {
if (!path.exists()) {
return 0;
} else {
final StatFs stats = new StatFs(path.getPath());
return (long) stats.getBlockSize() * (long) stats.getAvailableBlocks();
}
}
}
@SuppressWarnings("deprecation")
@TargetApi(VERSION_CODES.GINGERBREAD)
public static long getUsedSpace(File path) {
if (path == null) {
return -1;
}
if (Version.hasGingerbread()) {
return path.getTotalSpace() - path.getUsableSpace();
} else {
if (!path.exists()) {
return -1;
} else {
final StatFs stats = new StatFs(path.getPath());
return (long) stats.getBlockSize() * (stats.getBlockCount() - stats.getAvailableBlocks());
}
}
}
/**
* @param path
* @return -1 means path is null, 0 means path is not exist.
*/
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
public static long getTotalSpace(File path) {
if (path == null) {
return -1;
}
if (Version.hasGingerbread()) {
return path.getTotalSpace();
} else {
if (!path.exists()) {
return 0;
} else {
final StatFs stats = new StatFs(path.getPath());
return (long) stats.getBlockSize() * (long) stats.getBlockCount();
}
}
}
public static boolean hasSDCardMounted() {
String state = Environment.getExternalStorageState();
if (state != null && state.equals(Environment.MEDIA_MOUNTED)) {
return true;
} else {
return false;
}
}
/**
* external: "/storage/emulated/0/Android/data/in.srain.sample/files"
* internal: "/data/data/in.srain.sample/files"
*/
public static String wantFilesPath(Context context, boolean externalStorageFirst) {
String path = null;
if (externalStorageFirst && hasSDCardMounted()) {
path = context.getExternalFilesDir("").getAbsolutePath();
} else {
path = context.getFilesDir().getAbsolutePath();
}
return path;
}
public static File wantFile(String dir, String fileName) {
File wallpaperDirectory = new File(dir);
wallpaperDirectory.mkdirs();
File outputFile = new File(wallpaperDirectory, fileName);
return outputFile;
}
public static boolean write(String filePath, String content) {
File file = new File(filePath);
if (!file.getParentFile().exists())
file.getParentFile().mkdirs();
FileWriter writer = null;
try {
writer = new FileWriter(file);
writer.write(content);
} catch (IOException e) {
} finally {
try {
if (writer != null) {
writer.close();
return true;
}
} catch (IOException e) {
}
}
return false;
}
/**
* @param context
* @param filePath file path relative to assets, like request_init1/search_index.json
* @return
*/
public static String readAssert(Context context, String filePath) {
try {
if (filePath.startsWith(File.separator)) {
filePath = filePath.substring(File.separator.length());
}
AssetManager assetManager = context.getAssets();
InputStream inputStream = assetManager.open(filePath);
DataInputStream stream = new DataInputStream(inputStream);
int length = stream.available();
byte[] buffer = new byte[length];
stream.readFully(buffer);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byteArrayOutputStream.write(buffer);
stream.close();
return byteArrayOutputStream.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String read(String filePath) {
File file = new File(filePath);
if (!file.exists())
return null;
FileInputStream fileInput = null;
FileChannel channel = null;
try {
fileInput = new FileInputStream(filePath);
channel = fileInput.getChannel();
ByteBuffer buffer = ByteBuffer.allocate((int) channel.size());
channel.read(buffer);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byteArrayOutputStream.write(buffer.array());
return byteArrayOutputStream.toString();
} catch (Exception e) {
} finally {
if (fileInput != null) {
try {
fileInput.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (channel != null) {
try {
channel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
public static class CacheDirInfo {
public File path;
public boolean isInternal = false;
public boolean isNotEnough = false;
public long realSize;
public long requireSize;
}
}