Skip to content

Instantly share code, notes, and snippets.

@douzifly
Created June 9, 2014 02:56
Show Gist options
  • Save douzifly/4bbc7969eef815fffbb4 to your computer and use it in GitHub Desktop.
Save douzifly/4bbc7969eef815fffbb4 to your computer and use it in GitHub Desktop.
SdcardUtil
package com.qvod.player.utils;
import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
/**
* Author : 胡启明@Qvod
*/
public class SdcardUtil {
private static final String TAG = "SdcardUtil";
private static final String MOUNTS_PATH = "/proc/mounts";
private static final String VOLD_PATH = "/system/etc/vold.fstab";
private static final int TYPE_ALL = 3;
private static final int TYPE_INTERN = 1;
private static final int TYPE_EXTERN = 2;
/**
* 检查内置的sd卡是否可用
*
* @return
*/
public static boolean checkSDPath() {
return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
}
/**
* 获取外置sd卡
*
* @return
*/
public static String[] getExternStoragePaths(Context ctx) {
return getExternStoragePaths(ctx, null);
}
/**
* 获取外置sd卡
* @param ctx
* @param filterPath 需要过滤的路径
* @return
*/
public static String[] getExternStoragePaths(Context ctx, String filterPath) {
List<String> paths = null;
// 首先通过sdk4.0以上的隐藏方法来获取挂载的sd卡
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD){
paths = findByStorageManager(ctx, TYPE_EXTERN);
}
if(paths == null || paths.size() < 1){
// 通过sdk隐藏方法获取失败,再通过读取系统文件获取
paths = findByReadFile(TYPE_EXTERN);
}
if(paths != null && paths.size() > 0){
filterSamePath(paths, filterPath);
return paths.size() > 0 ? paths.toArray(new String[paths.size()]) : null;
}
return null;
}
/**
* 获取内置sd卡
*
* @return
*/
public static String getInternStoragePath(Context ctx) {
List<String> paths = null;
// 首先通过sdk4.0以上的隐藏方法来获取挂载的sd卡
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD){
paths = findByStorageManager(ctx, TYPE_INTERN);
}
if(paths == null || paths.size() < 1){
// 通过sdk隐藏方法获取失败,再通过读取系统文件获取
paths = findByReadFile(TYPE_INTERN);
}
if(paths != null && paths.size() > 0){
return paths.get(0);
}
return null;
}
/**
* 通过读取系统文件获取
* @param internPath
* @return
*/
private static List<String> findByReadFile(int type){
String internPath = Environment.getExternalStorageDirectory().getPath();
if(type == TYPE_INTERN){
List<String> paths = new ArrayList<String>();
paths.add(internPath);
filterValidPaths(paths);
return paths;
}
String filterPath = type == TYPE_EXTERN ? internPath : null;
List<String> paths = new ArrayList<String>();
List<String> voldPaths = readVoldFile(filterPath);
List<String> mountPaths = readMountsFile(filterPath);
if (voldPaths == null || voldPaths.size() < 1 || mountPaths == null || mountPaths.size() < 1) {
return null;
}
for (String path : voldPaths) {
if (mountPaths.contains(path)) {
paths.add(path);
}
}
filterValidPaths(paths);
return paths;
}
/**
* 获取内置sd卡的路径,如果没有挂载则返回空
*
* @return
*/
public static String getSDPath() {
return getSDPath(true);
}
/**
* 获取内置sd卡的路径,如果没有挂载则返回空
*
* @param needMounted
* 需要挂载如果当前没有挂载则返回空,否则直接返回路径
* @return
*/
public static String getSDPath(boolean needMounted) {
if (needMounted) {
if (checkSDPath()) {
return Environment.getExternalStorageDirectory().toString();
} else {
return null;
}
} else {
return Environment.getExternalStorageDirectory().getPath();
}
}
/**
* 获取所有sd卡
*
* @return
*/
public static String[] getAllStoragePaths(Context ctx) {
return getAllStoragePaths(ctx, null);
}
/**
* 获取所有sd卡
* @param ctx
* @param filterPath 需要过滤的路径
* @return
*/
public static String[] getAllStoragePaths(Context ctx, String filterPath) {
List<String> paths = null;
// 首先通过sdk4.0以上的隐藏方法来获取挂载的sd卡
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD){
paths = findByStorageManager(ctx, TYPE_ALL);
}
if(paths == null || paths.size() < 1){
// 通过sdk隐藏方法获取失败,再通过读取系统文件获取
paths = findByReadFile(TYPE_ALL);
}
if(paths != null && paths.size() > 0){
filterSamePath(paths, filterPath);
return paths.size() > 0 ? paths.toArray(new String[paths.size()]) : null;
}
return null;
}
public static void filterSamePath(List<String> list, String path) {
if (list == null || path == null) {
return;
}
path = path.endsWith("/") ? path.substring(0, path.length()-1) : path;
Iterator<String> it = list.iterator();
while(it.hasNext()) {
String str = it.next();
String subStr = str.endsWith("/") ? str.substring(0, str.length()-1) : str;
if (subStr.equals(path)) {
it.remove();
}
}
}
/**
* 读取系统文件vold.fstab获取挂载的SD卡
*
* @param filterPath
* @return
*/
private static List<String> readVoldFile(String filterPath) {
File file = new File(VOLD_PATH);
if (!file.exists()) {
return null;
}
Scanner scanner = null;
List<String> paths = null;
try {
scanner = new Scanner(file);
paths = new ArrayList<String>();
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.contains("usb"))
continue;
// don't add the default vold path
// it's already in the list.
if (!element.equals(filterPath) && !paths.contains(element)) {
paths.add(element);
}
}
}
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.toString());
} finally {
if (scanner != null) {
scanner.close();
}
}
return paths;
}
/**
* 读取系统文件mounts获取挂载的SD卡
*
* @param filterPath
* @return
*/
private static List<String> readMountsFile(String filterPath) {
File file = new File(MOUNTS_PATH);
if (!file.exists()) {
return null;
}
Scanner scanner = null;
List<String> paths = null;
try {
scanner = new Scanner(file);
paths = new ArrayList<String>();
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(filterPath) && !paths.contains(element)) {
paths.add(element);
}
}
}
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.toString());
} finally {
if (scanner != null) {
scanner.close();
}
}
return paths;
}
/**
* 通过4.0以上的隐藏api获取
* @param ctx
* @param type
* @return
*/
@SuppressLint("NewApi")
private static List<String> findByStorageManager(Context ctx, int type) {
if (ctx == null) {
return null;
}
Log.d(TAG, "StorageManager type: " + type);
try {
StorageManager sm = (StorageManager) ctx.getSystemService(Context.STORAGE_SERVICE);
Method method = StorageManager.class.getMethod("getVolumeList", null);
StorageVolume[] volumes = (StorageVolume[]) method.invoke(sm, null);
ArrayList<String> result = new ArrayList<String>();
for (StorageVolume volume : volumes) {
Log.d(TAG, "StorageManager path: " + volume.getPath() + " isRemovable(): " + volume.isRemovable()
+ " isEmulated(): " + volume.isEmulated());
int volType = volume.isRemovable() ? TYPE_EXTERN : TYPE_INTERN;
int resType = volType & type;
Log.d(TAG, "StorageManager volType: " + volType + " resType: " + resType);
if(resType != 0){
result.add(volume.getPath());
}
}
// // 如果是获取外置SD卡,需要将调用系统api获取到的内置SD卡路径过滤掉
// String filterPath = type == TYPE_EXTERN ?
// Environment.getExternalStorageDirectory().getPath() : null;
String filterPath = null;
filterValidPaths(result, filterPath);
return result;
} catch (Exception e) {
Log.e(TAG, "Exception : " + e.toString());
}
return null;
}
/**
* 将不存在的sd卡过滤掉;
*
* @param paths
*/
private static void filterValidPaths(List<String> paths) {
filterValidPaths(paths, null);
}
/**
* 将不存在的SD卡和需要过滤的路径过滤掉
* @param paths
* @param filterPath
*/
private static void filterValidPaths(List<String> paths, String filterPath) {
if (paths == null || paths.size() < 1) {
return;
}
Iterator<String> it = paths.iterator();
while (it.hasNext()) {
String path = it.next();
File file = new File(path);
if (path == null || path.equals(filterPath) ||
!file.exists() || !file.isDirectory() || !file.canWrite()) {
it.remove();
}
}
}
/**
* 获取可用空间
*
* @param pathStr
* @return
*/
public static long getAvailaleSize(String pathStr) {
File path = new File(pathStr); // 取得sdcard文件路径
if (!path.exists()) {
return -1;
}
StatFs stat = new StatFs(path.getPath());
long blockSize = stat.getBlockSize();
long availableBlocks = stat.getAvailableBlocks();
return availableBlocks * blockSize;
}
/**
*
* 获取sd卡的大小
*
* @param pathStr
* sd卡的路径
* @return sd卡的大小,单位byte
*/
public static long getSdCardSize(String pathStr) {
File path = new File(pathStr);
if (!path.exists()) {
return -1;
}
StatFs stat = new StatFs(path.getPath());
long blockSize = stat.getBlockSize();
long totalBlocks = stat.getBlockCount();
return totalBlocks * blockSize;
}
/**
* 获取容量最大的sdcard
*
* @return
*/
public static String findStoragePath(Context ctx) {
String[] findPath = getAllStoragePaths(ctx);
// find the largest free size sd card
if (findPath == null || findPath.length == 0) {
return null;
}
long freeSize = -1;
String paString = null;
for (String string : findPath) {
if (checkSDPath() && string != null) {
long size = getAvailaleSize(string);
// Log.i(TAG, string + " free size : " + size);
if (freeSize < size) {
paString = string;
}
freeSize = freeSize < size ? size : freeSize;
}
}
return paString;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment