我有一个预先存储在SD卡中的大量数据的应用程序。
我们支持所有平板电脑 ICS以上。我无法在所有设备上找到正确访问SDCard位置的方法。
我看了这里给出的各种解决方案,但它们似乎并不适用于所有情况。寻找通用解决方案。
即使有人能告诉我SDCard的所有可能挂载点。
只有在可以缩小解决方案范围的情况下,我才会定位Android平板电脑。
答案 0 :(得分:15)
不幸的是,由于Android设备高度分散,这是一个常见问题。 Environment.getExternalStorageDirectory()
指设备制造商认为是“外部存储”的任何内容。在某些设备上,这是可移动媒体,如SD卡。在某些设备上,这是设备上闪存的一部分。(http://developer.android.com/reference/android/os/Environment.html#getExternalStorageDirectory())这里,“外部存储”表示“当安装在主机上时,可以通过USB大容量存储模式访问”。
如果设备制造商已选择将外部存储设备作为板载闪存并且还具有SD卡,则需要与该制造商联系以确定是否可以使用SD卡。对于大多数符合规范的Android设备(来自Google合规性列表的已知设备),Environment.getExternalStorageDirectory()
应该有效。或者您可以编写一个自定义存储类来查看安装点,并为您提供安装SDCard的正确路径。这是我已经实现的东西,它到目前为止已经有效。
public class StorageOptions {
private static ArrayList<String> mMounts = new ArrayList<String>();
private static ArrayList<String> mVold = new ArrayList<String>();
public static String[] labels;
public static String[] paths;
public static int count = 0;
private static final String TAG = StorageOptions.class.getSimpleName();
public static void determineStorageOptions() {
readMountsFile();
readVoldFile();
compareMountsWithVold();
testAndCleanMountsList();
setProperties();
}
private static void readMountsFile() {
/*
* Scan the /proc/mounts file and look for lines like this:
* /dev/block/vold/179:1 /mnt/sdcard vfat
* rw,dirsync,nosuid,nodev,noexec,
* relatime,uid=1000,gid=1015,fmask=0602,dmask
* =0602,allow_utime=0020,codepage
* =cp437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro 0 0
*
* When one is found, split it into its elements and then pull out the
* path to the that mount point and add it to the arraylist
*/
// some mount files don't list the default
// path first, so we add it here to
// ensure that it is first in our list
mMounts.add("/mnt/sdcard");
try {
Scanner scanner = new Scanner(new File("/proc/mounts"));
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("/mnt/sdcard"))
mMounts.add(element);
}
}
} catch (Exception e) {
// Auto-generated catch block
e.printStackTrace();
}
}
private static void readVoldFile() {
/*
* Scan the /system/etc/vold.fstab file and look for lines like this:
* dev_mount sdcard /mnt/sdcard 1
* /devices/platform/s3c-sdhci.0/mmc_host/mmc0
*
* When one is found, split it into its elements and then pull out the
* path to the that mount point and add it to the arraylist
*/
// some devices are missing the vold file entirely
// so we add a path here to make sure the list always
// includes the path to the first sdcard, whether real
// or emulated.
mVold.add("/mnt/sdcard");
try {
Scanner scanner = new Scanner(new File("/system/etc/vold.fstab"));
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(":"));
// don't add the default vold path
// it's already in the list.
if (!element.equals("/mnt/sdcard"))
mVold.add(element);
}
}
} catch (Exception e) {
// Auto-generated catch block
e.printStackTrace();
}
}
private static void compareMountsWithVold() {
/*
* Sometimes the two lists of mount points will be different. We only
* want those mount points that are in both list.
*
* Compare the two lists together and remove items that are not in both
* lists.
*/
for (int i = 0; i < mMounts.size(); i++) {
String mount = mMounts.get(i);
if (!mVold.contains(mount))
mMounts.remove(i--);
}
// don't need this anymore, clear the vold list to reduce memory
// use and to prepare it for the next time it's needed.
mVold.clear();
}
private static void testAndCleanMountsList() {
/*
* Now that we have a cleaned list of mount paths Test each one to make
* sure it's a valid and available path. If it is not, remove it from
* the list.
*/
for (int i = 0; i < mMounts.size(); i++) {
String mount = mMounts.get(i);
File root = new File(mount);
if (!root.exists() || !root.isDirectory() || !root.canWrite())
mMounts.remove(i--);
}
}
@SuppressWarnings("unchecked")
private static void setProperties() {
/*
* At this point all the paths in the list should be valid. Build the
* public properties.
*/
Constants.mMounts = new ArrayList<String>();
ArrayList<String> mLabels = new ArrayList<String>();
int j = 0;
if (mMounts.size() > 0) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD)
mLabels.add("Auto");
else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
if (Environment.isExternalStorageRemovable()) {
mLabels.add("External SD Card 1");
j = 1;
} else
mLabels.add("Internal Storage");
} else {
if (!Environment.isExternalStorageRemovable()
|| Environment.isExternalStorageEmulated())
mLabels.add("Internal Storage");
else {
mLabels.add("External SD Card 1");
j = 1;
}
}
if (mMounts.size() > 1) {
for (int i = 1; i < mMounts.size(); i++) {
mLabels.add("External SD Card " + (i + j));
}
}
}
labels = new String[mLabels.size()];
mLabels.toArray(labels);
paths = new String[mMounts.size()];
mMounts.toArray(paths);
Constants.mMounts = (ArrayList<String>) mMounts.clone();
Constants.mLabels = (ArrayList<String>) mLabels.clone();
count = Math.min(labels.length, paths.length);
// don't need this anymore, clear the mounts list to reduce memory
// use and to prepare it for the next time it's needed.
mMounts.clear();
}
}
我从SO发现了一个类似的问题,不幸的是我没有链接,但它可能在索尼的Android开发者网站上(不幸的是没有链接)。 Wagic - 一个C ++游戏引擎库实现了相同的代码,它们的代码在这里:http://wagic.googlecode.com/svn-history/r4300/trunk/projects/mtg/Android/src/net/wagic/utils/StorageOptions.java 所以你可以看看实现。我希望Google的某个人能够回答这个问题并提供一种从所有Android设备读取SD卡挂载点的方法
答案 1 :(得分:1)
你的想法并不简单, String f = Environment.getExternalStorageDirectory()。getAbsolutePath(); Log.v(“TAG”,f); //打印sdcard的路径
它返回设备存储路径而不是外部SD卡路径。
答案 2 :(得分:-1)
如果您尝试获取SD卡的路径,请使用此代码
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
然后使用它来获取特定文件夹/文件的路径
String path = baseDir + "/your folder(s)/" + fileName;
答案 3 :(得分:-6)
简单。
String f = Environment.getExternalStorageDirectory().getAbsolutePath();
Log.v("TAG",f);//to print the path of sdcard
如果您想访问文件,那么。
String f = Environment.getExternalStorageDirectory()+"/file.ext";
Log.v("TAG",f);//to print the path of file in Logcat.