获取外部SD卡定位在Android中 [英] Get External SDCard Location in Android

查看:120
本文介绍了获取外部SD卡定位在Android中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个庞大的数据pre-存储在SD卡的应用程序。

I have an app with huge data pre-stored in the SD Card.

我们都支持所有片 ICS起。我没能找到一种方法来正确地访问所有设备上的SD卡的位置。

We are supporting all tablets ICS onwards. I am not able to find a way to access the SDCard location correctly on ALL devices.

我看了一下这里给出的SO各种解决方案,但他们似乎并没有在所有情况下工作。寻找一个通用的解决方案。

I looked at various solutions given here on SO but they do not seem to work in all cases. Looking for a generic solution.

即使任何人都可以告诉我SD卡的所有可能的挂载点。

Even if anyone can tell me all the possible mount points of SDCard.

我针对Android平板电脑仅可以缩小解决方案。

I am targeting android tablets only if that can narrow down the solution.

推荐答案

不幸的是,这是一个常见的​​问题,是由于这样的事实,Android设备的高度分散。 Environment.getExternalStorageDirectory()指的是什么设备制造商认为是外部存储。在某些设备上,这是可移动媒体,如SD卡。在某些设备上,这是基于设备的闪存的一部分。(<一href="http://developer.android.com/reference/android/os/Environment.html#getExternalStorageDirectory()">http://developer.android.com/reference/android/os/Environment.html#getExternalStorageDirectory())在这里,外部存储安装在主机上时,通过USB大容量存储模式访问驱动器的意思。 如果设备制造商已选择具有外部存储上板载闪存,也有一个SD卡,则需要联系该制造商,以确定您是否可以使用SD卡。对于大多数符合要求的Andr​​oid设备(已知的来自谷歌遵守列表)的 Environment.getExternalStorageDirectory()应该工作。或者,你可以写自己看的挂载点,并为您提供了正确的路径安装SD卡的自定义存储类。这是我已经实现,它至今工作。

Unfortunately this is a common problem due to the fact that Android devices are highly fragmented. Environment.getExternalStorageDirectory() refers to whatever the device manufacturer considers to be "external storage". On some devices, this is removable media, like an SD card. On some devices, this is a portion of on-device flash.(http://developer.android.com/reference/android/os/Environment.html#getExternalStorageDirectory()) Here, "external storage" means "the drive accessible via USB Mass Storage mode when mounted on a host machine". If a device manufacturer has elected to have external storage be on-board flash and also has an SD card, you will need to contact that manufacturer to determine whether or not you can use the SD card. For most conforming android devices(known ones from google compliance list) the Environment.getExternalStorageDirectory() should work. Or you could write a custom storage class that looks at the mount points and gives you the right path to the mounted SDCard. This is something I've implemented and it has worked so far.

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发现这一关的一个类似的问题,那我没有链接不幸,但它那儿就可能索尼的Andr​​oid开发者网站(不链接有两种不幸)。 Wagic - 一个C ++游戏引擎库实现相同的和他们的code是在这里:<一href="http://wagic.google$c$c.com/svn-history/r4300/trunk/projects/mtg/Android/src/net/wagic/utils/StorageOptions.java">http://wagic.google$c$c.com/svn-history/r4300/trunk/projects/mtg/Android/src/net/wagic/utils/StorageOptions.java 所以你可以看看执行。我希望有人从谷歌可以回答这个问题,并提供来自所有Android设备读取SD卡装入点单方式

I found this off of a similar question from SO, that I dont have the link to unfortunately, but it s there on probably Sony's Android developer site(no links there either unfortunately). Wagic - a C++ game engine library implements the same and their code is here: http://wagic.googlecode.com/svn-history/r4300/trunk/projects/mtg/Android/src/net/wagic/utils/StorageOptions.java so you could look at the implementation. I wish someone from Google can answer this question and provide a single way that reads the SDcard mount point from all Android devices

这篇关于获取外部SD卡定位在Android中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆