项目中需要获取用户的内置存储卡和外置存储卡(扩展卡),就遇到一个问题,通过Environment.getExternalStorageDirectory()只能获取内置存储卡的位置,网上找了相关资料,得到的解决方法大多都是代码写死路劲,比如内置卡的路劲一般都是/mnt/sdcard或者/storage/sdcard0,外置存储卡的路劲一般都是/mnt/sdcard1或者/storage/sdcard1,这种方法多数还是管用的,就是对于程序员自己来说,不能打保票说特别系统改造比较大的手机不出问题,经过几天努力,看了其他项目的相关源码,终于解决问题,在这里记录下,希望对同行有所帮助,下面直接是代码,都有相关注释的,看起来so easy。
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.content.Context;
import android.os.Environment;
import android.os.storage.StorageManager;
public class SDCardUtil {
/**
* 内置
*/
static String SDCARD_INTERNAL = "internal";
/**
* 外置
*/
static String SDCARD_EXTERNAL = "external";
/**
* API14以下通过读取Linux的vold.fstab文件来获取SDCard信息
*
* @return
*/
public static HashMap<String, SDCardInfo> getSDCardInfoBelow14() {
HashMap<String, SDCardInfo> sdCardInfos = new HashMap<String, SDCardInfo>();
BufferedReader bufferedReader = null;
List<String> dev_mountStrs = null;
try {
// API14以下通过读取Linux的vold.fstab文件来获取SDCard信息
bufferedReader = new BufferedReader(new FileReader(Environment.getRootDirectory().getAbsoluteFile()
+ File.separator + "etc" + File.separator + "vold.fstab"));
dev_mountStrs = new ArrayList<String>();
String line = null;
while ((line = bufferedReader.readLine()) != null) {
if (line.startsWith("dev_mount")) {
dev_mountStrs.add(line);
}
}
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
for (int i = 0; dev_mountStrs != null && i < dev_mountStrs.size(); i++) {
SDCardInfo sdCardInfo = new SDCardInfo();
String[] infoStr = dev_mountStrs.get(i).split(" ");
sdCardInfo.setLabel(infoStr[1]);
sdCardInfo.setMountPoint(infoStr[2]);
if (sdCardInfo.getMountPoint().equals(Environment.getExternalStorageDirectory().getAbsolutePath())) {
sdCardInfo.setMounted(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED));
sdCardInfos.put(SDCARD_INTERNAL, sdCardInfo);
} else if (sdCardInfo.getMountPoint().startsWith("/mnt")
&& !sdCardInfo.getMountPoint().equals(Environment.getExternalStorageDirectory().getAbsolutePath())) {
File file = new File(sdCardInfo.getMountPoint() + File.separator + "temp");
if (file.exists()) {
sdCardInfo.setMounted(true);
} else {
if (file.mkdir()) {
file.delete();
sdCardInfo.setMounted(true);
} else {
sdCardInfo.setMounted(false);
}
}
sdCardInfos.put(SDCARD_EXTERNAL, sdCardInfo);
}
}
return sdCardInfos;
}
// API14以上包括14通过改方法获取
public static HashMap<String, SDCardInfo> getSDCardInfo(Context context) {
HashMap<String, SDCardInfo> sdCardInfos = new HashMap<String, SDCardInfo>();
String[] storagePathList = null;
try {
StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
Method getVolumePaths = storageManager.getClass().getMethod("getVolumePaths");
storagePathList = (String[]) getVolumePaths.invoke(storageManager);
} catch (Exception e) {
e.printStackTrace();
}
if (storagePathList != null && storagePathList.length > 0) {
String mSDCardPath = storagePathList[0];
SDCardInfo internalDevInfo = new SDCardInfo();
internalDevInfo.setMountPoint(mSDCardPath);
internalDevInfo.setMounted(checkSDCardMount14(context, mSDCardPath));
sdCardInfos.put(SDCARD_INTERNAL, internalDevInfo);
if (storagePathList.length >= 2) {
String externalDevPath = storagePathList[1];
SDCardInfo externalDevInfo = new SDCardInfo();
externalDevInfo.setMountPoint(storagePathList[1]);
externalDevInfo.setMounted(checkSDCardMount14(context, externalDevPath));
sdCardInfos.put(SDCARD_EXTERNAL, externalDevInfo);
}
}
return sdCardInfos;
}
/**
* @Description:判断SDCard是否挂载上,返回值为true证明挂载上了,否则未挂载
* @Date 2013-11-12
* @param context 上下文
* @param mountPoint 挂载点
*/
protected static boolean checkSDCardMount14(Context context, String mountPoint) {
if (mountPoint == null) {
return false;
}
StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
try {
Method getVolumeState = storageManager.getClass().getMethod("getVolumeState", String.class);
String state = (String) getVolumeState.invoke(storageManager, mountPoint);
return Environment.MEDIA_MOUNTED.equals(state);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}
SDCardInfo类:
public class SDCardInfo
{
/**
* 名称
*/
private String label;
/**
* 挂载点
*/
private String mountPoint;
/**
* 是否已挂载
*/
private boolean mounted;
/**
* @Description:获取SD卡名称
* @Date 2013-11-22
* @return SD卡名称
*/
public String getLabel()
{
return label;
}
/**
* @Description:设置SD卡名称
* @Date 2013-11-22
* @param label
* SD卡名称
*/
public void setLabel(String label)
{
this.label = label;
}
/**
* @Description:获取挂载路径
* @Date 2013-11-22
* @return 挂载路径
*/
public String getMountPoint()
{
return mountPoint;
}
/**
* @Description:设置挂载路径
* @Date 2013-11-22
* @param mountPoint
* 挂载路径
*/
public void setMountPoint(String mountPoint)
{
this.mountPoint = mountPoint;
}
/**
* @Description:是否已经挂载
* @Date 2013-11-22
* @return true:已经挂载,false:未挂载
*/
public boolean isMounted()
{
return mounted;
}
/**
* @Description:设置是否已经挂载
* @Date 2013-11-22
* @param mounted
* true:已经挂载,false:未挂载
*/
public void setMounted(boolean mounted)
{
this.mounted = mounted;
}
@Override
public String toString()
{
return "SDCardInfo [label=" + label + ", mountPoint=" + mountPoint
+ ", mounted=" + mounted + "]";
}
}
用的时候需要区分SDK版本,使用的代码不用贴了吧,太so easy啦。