获取连接到Android设备的所有存储设备的路径列表

Rah*_*602 15 java android sd-card android-sdcard usb-otg

我想获取连接到Android设备的所有存储设备的列表.

例如 - 内部存储(存储所有文件夹,如下载,DCIM等),SD卡和OTG设备.

我知道有很多StackOverflow帖子讨论了这个主题,但没有一个可以满足我的目的,如上所述.

我可以通过调用Environment.getExternalStorageDirectory().getPath()返回内部存储的路径来获取内部存储.

对此的任何帮助都将非常感激,因为没有标准的AFAIK可以使用它来检索所有连接的存储设备的列表.

此外,许多解决方案不适用于不同的设备和Android版本.

Amj*_*han 5

您可以创建一个类EnvironmentSDCardCheck

\n\n
package com.example.storagecheck;\n\nimport android.content.BroadcastReceiver;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.IntentFilter;\nimport android.os.Build;\nimport android.os.Environment;\nimport android.os.storage.StorageManager;\nimport android.support.v4.content.ContextCompat;\nimport android.support.v4.os.EnvironmentCompat;\nimport android.util.Log;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\n\npublic class EnvironmentSDCardCheck {\n    private static final String TAG = "EnvironmentSDCardCheck";\n\n    public final static String TYPE_PRIMARY = "prim\xc3\xa4r";\n    public final static String TYPE_INTERNAL = "intern";\n    public final static String TYPE_SD = "MicroSD";\n    public final static String TYPE_USB = "USB";\n    public final static String TYPE_UNKNOWN = "unbekannt";\n\n    public final static String WRITE_NONE = "none";\n    public final static String WRITE_READONLY = "readonly";\n    public final static String WRITE_APPONLY = "apponly";\n    public final static String WRITE_FULL = "readwrite";\n\n    private static Device[] devices, externalstorage, storage;\n    private static BroadcastReceiver receiver;\n    private static boolean useReceiver = true;\n    private static String userDir;\n\n    public static Device[] getDevices(Context context) {\n        if (devices == null) initDevices(context);\n        return devices;\n    }\n\n    public static Device[] getExternalStorage(Context context) {\n        if (devices == null) initDevices(context);\n        return externalstorage;\n    }\n\n    public static Device[] getStorage(Context context) {\n        if (devices == null) initDevices(context);\n        return storage;\n    }\n\n    public static IntentFilter getRescanIntentFilter() {\n        IntentFilter filter = new IntentFilter();\n        filter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL); \n        filter.addAction(Intent.ACTION_MEDIA_MOUNTED); \n        filter.addAction(Intent.ACTION_MEDIA_REMOVED); \n        filter.addAction(Intent.ACTION_MEDIA_SHARED); \n        filter.addDataScheme("file");\n        return filter;\n    }\n\n    public static void setUseReceiver(Context context, boolean use) {\n        if (use && receiver == null) {\n            receiver = new BroadcastReceiver() {\n                @Override\n                public void onReceive(Context context, Intent intent) {\n                    Log.i(TAG, "Storage " + intent.getAction() + "-" + intent.getData());\n                    initDevices(context);\n                }\n            };\n            context.registerReceiver(receiver, getRescanIntentFilter());\n        } else if (!use && receiver != null) {\n            context.unregisterReceiver(receiver);\n            receiver = null;\n        }\n        useReceiver = use;\n    }\n\n    public static void initDevices(Context context) {\n        if (userDir == null) userDir = "/Android/data/" + context.getPackageName();\n        setUseReceiver(context, useReceiver);\n        StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);\n        Class c = sm.getClass();\n        Object[] vols;\n        try {\n            Method m = c.getMethod("getVolumeList", null);\n            vols = (Object[]) m.invoke(sm, null); // android.os.Storage.StorageVolume\n            Device[] temp = new Device[vols.length];\n            for (int i = 0; i < vols.length; i++) temp[i] = new Device(vols[i]);\n            Device primary = null;\n            for (Device d : temp) if (d.mPrimary) primary = d;\n            if (primary == null) for (Device d : temp)\n                if (!d.mRemovable) {\n                    d.mPrimary = true;\n                    primary = d;\n                    break;\n                }\n            if (primary == null) {\n                primary = temp[0];\n                primary.mPrimary = true;\n            }\n\n            File[] files = ContextCompat.getExternalFilesDirs(context, null);\n            File[] caches = ContextCompat.getExternalCacheDirs(context);\n            for (Device d : temp) {\n                if (files != null) for (File f : files)\n                    if (f != null && f.getAbsolutePath().startsWith(d.getAbsolutePath()))\n                        d.mFiles = f;\n                if (caches != null) for (File f : caches)\n                    if (f != null && f.getAbsolutePath().startsWith(d.getAbsolutePath()))\n                        d.mCache = f;\n            }\n\n            ArrayList<Device> tempDev = new ArrayList<Device>(10);\n            ArrayList<Device> tempStor = new ArrayList<Device>(10);\n            ArrayList<Device> tempExt = new ArrayList<Device>(10);\n            for (Device d : temp) {\n                tempDev.add(d);\n                if (d.isAvailable()) {\n                    tempExt.add(d);\n                    tempStor.add(d);\n                }\n            }\n\n            Device internal = new Device(context);\n            tempStor.add(0, internal); // bei Storage-Alternativen immer\n            if (!primary.mEmulated) tempDev.add(0, internal); // bei Devices nur wenn zus\xc3\xa4tzlich\n\n            devices = tempDev.toArray(new Device[tempDev.size()]);\n            storage = tempStor.toArray(new Device[tempStor.size()]);\n            externalstorage = tempExt.toArray(new Device[tempExt.size()]);\n        } catch (Exception e) {\n            // Fallback auf normale Android-Funktionen\n        }\n\n    }\n\n    public static class Device extends File {\n        String mUserLabel, mUuid, mState, mWriteState, mType;\n        boolean mPrimary, mRemovable, mEmulated, mAllowMassStorage;\n        long mMaxFileSize;\n        File mFiles, mCache;\n\n        Device(Context context) {\n            super(Environment.getDataDirectory().getAbsolutePath());\n            mState = Environment.MEDIA_MOUNTED;\n            mFiles = context.getFilesDir();\n            mCache = context.getCacheDir();\n            mType = TYPE_INTERNAL;\n            mWriteState = WRITE_APPONLY;\n        }\n\n        @SuppressWarnings("NullArgumentToVariableArgMethod")\n        Device(Object storage) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {\n            super((String) storage.getClass().getMethod("getPath", null).invoke(storage, null));\n            for (Method m : storage.getClass().getMethods()) {\n                if (m.getName().equals("getUserLabel") && m.getParameterTypes().length == 0 && m.getReturnType() == String.class)\n                    mUserLabel = (String) m.invoke(storage, null); // ab Android 4.4\n                if (m.getName().equals("getUuid") && m.getParameterTypes().length == 0 && m.getReturnType() == String.class)\n                    mUuid = (String) m.invoke(storage, null); // ab Android 4.4\n                if (m.getName().equals("getState") && m.getParameterTypes().length == 0 && m.getReturnType() == String.class)\n                    mState = (String) m.invoke(storage, null); // ab Android 4.4\n                if (m.getName().equals("isRemovable") && m.getParameterTypes().length == 0 && m.getReturnType() == boolean.class)\n                    mRemovable = (Boolean) m.invoke(storage, null); // ab Android 4.0\n                if (m.getName().equals("isPrimary") && m.getParameterTypes().length == 0 && m.getReturnType() == boolean.class)\n                    mPrimary = (Boolean) m.invoke(storage, null); // ab Android 4.2\n                if (m.getName().equals("isEmulated") && m.getParameterTypes().length == 0 && m.getReturnType() == boolean.class)\n                    mEmulated = (Boolean) m.invoke(storage, null); // ab Android 4.0\n                if (m.getName().equals("allowMassStorage") && m.getParameterTypes().length == 0 && m.getReturnType() == boolean.class)\n                    mAllowMassStorage = (Boolean) m.invoke(storage, null); // ab Android 4.0\n                if (m.getName().equals("getMaxFileSize") && m.getParameterTypes().length == 0 && m.getReturnType() == long.class)\n                    mMaxFileSize = (Long) m.invoke(storage, null); // ab Android 4.0\n                // getDescription (ab 4.1 mit context) liefert keine sinnvollen Werte\n                // getPathFile (ab 4.2) liefert keine sinnvollen Werte\n                // getMtpReserveSpace (ab 4.0) f\xc3\xbcr diese Zwecke unwichtig\n                // getStorageId (ab 4.0) f\xc3\xbcr diese Zwecke unwichtig\n            }\n            if (mState == null) mState = getState();\n\n            if (mPrimary)\n                mType = TYPE_PRIMARY;\n            else {\n                String n = getAbsolutePath().toLowerCase();\n                if (n.indexOf("sd") > 0)\n                    mType = TYPE_SD;\n                else if (n.indexOf("usb") > 0)\n                    mType = TYPE_USB;\n                else\n                    mType = TYPE_UNKNOWN + " " + getAbsolutePath();\n            }\n        }\n\n        public String getType() {\n            return mType;\n        }\n\n        public String getAccess() {\n            if (mWriteState == null) {\n                try {\n                    mWriteState = WRITE_NONE;\n                    File[] root = listFiles();\n                    if (root == null || root.length == 0)\n                        throw new IOException("root empty/unreadable");\n                    mWriteState = WRITE_READONLY;\n                    File t = File.createTempFile("jow", null, getFilesDir());\n                    //noinspection ResultOfMethodCallIgnored\n                    t.delete();\n                    mWriteState = WRITE_APPONLY;\n                    t = File.createTempFile("jow", null, this);\n                    //noinspection ResultOfMethodCallIgnored\n                    t.delete();\n                    mWriteState = WRITE_FULL;\n                } catch (IOException ignore) {\n                    Log.v(TAG, "test " + getAbsolutePath() + " ->" + mWriteState + "<- " + ignore.getMessage());\n                }\n            }\n            return mWriteState;\n        }\n\n        public boolean isAvailable() {\n            String s = getState();\n            return (\n                    Environment.MEDIA_MOUNTED.equals(s) ||\n                            Environment.MEDIA_MOUNTED_READ_ONLY.equals(s)\n            );\n            // MEDIA_SHARED: als USB freigegeben; bitte Handy auf MTP umstellen\n        }\n\n        public String getState() {\n            if (mRemovable || mState == null) {\n                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)\n                    // Android 5.0? Da gibts was neues\n                    mState = Environment.getExternalStorageState(this);\n                else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)\n                    // Android 4.4? Dann dort nachfragen\n                    mState = Environment.getStorageState(this);\n                else if (canRead() && getTotalSpace() > 0)\n                    // lesbar und Gr\xc3\xb6\xc3\x9fe vorhanden => gibt es\n                    mState = Environment.MEDIA_MOUNTED;\n                else if (mState == null || Environment.MEDIA_MOUNTED.equals(mState))\n                    // nicht lesbar, keine Gr\xc3\xb6\xc3\x9fe aber noch MOUNTED || oder ungesetzt => UNKNOWN\n                    mState = EnvironmentCompat.MEDIA_UNKNOWN;\n            }\n            return mState;\n        }\n\n        public File getFilesDir() {\n            if (mFiles == null) {\n                mFiles = new File(this, userDir + "/files");\n                if (!mFiles.isDirectory())\n                    //noinspection ResultOfMethodCallIgnored\n                    mFiles.mkdirs();\n            }\n            return mFiles;\n        }\n\n        public File getCacheDir() {\n            if (mCache == null) {\n                mCache = new File(this, userDir + "/cache");\n                if (!mCache.isDirectory())\n                    //noinspection ResultOfMethodCallIgnored\n                    mCache.mkdirs();\n            }\n            return mCache;\n        }\n\n        public boolean isPrimary() {\n            return mPrimary;\n        }\n\n        public boolean isRemovable() {\n            return mRemovable;\n        }\n        public boolean isEmulated() {\n            return mEmulated;\n        }\n\n        public boolean isAllowMassStorage() {\n            return mAllowMassStorage;\n        }\n\n        public long getMaxFileSize() {\n            return mMaxFileSize;\n        }\n\n        public String getUserLabel() {\n            return mUserLabel;\n        }\n\n        public String getUuid() {\n            return mUuid;\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后您可以用它来检查 SD 卡或 USB 或未知当前是否与设备连接

\n\n
\n

这样你就可以获得连接的sd卡、usb等。

\n
\n\n
private boolean checkSdCardPermission() {\n    boolean flag = false;\n    try {\n        EnvironmentSDCard.Device[] devices = EnvironmentSDCard.getExternalStorage(MainActivity.this);\n        for (EnvironmentSDCard.Device d : devices) {\n            if (d.getType().equals(EnvironmentSDCard.TYPE_SD) || d.getType().contains(EnvironmentSDCard.TYPE_UNKNOWN) || d.getType().contains(EnvironmentSDCard.TYPE_USB)) {\n                flag = d.isAvailable();\n                if (flag)\n                    break;\n            }\n        }\n    } catch (Exception e) {\n    }\n    return flag;\n}\n
Run Code Online (Sandbox Code Playgroud)\n