6

さまざまな Android デバイス (Samsung、Motorola、LG、Sony、HTC) でリムーバブル SD カードを検出してアクセスする方法を探しています。

また、2.2 と互換性がある必要があるためEnvironment.isExternalStorageRemovable()、利用できません。

Motorola には独自のライブラリがあり、Samsung の場合、次の存在を検出できます。/external_sd/

私はそれらの残りの手がかりがありません。たとえば、/_ExternalSD/一部の LG で a を見たことがありますが、SD を取り外してもディレクトリは残ります。

おまけの質問:ACTION_MEDIA_MOUNTEDインテントはそれらのいずれかに対してブロードキャストされますか?

これに関するヒントは非常に役立ちます。

4

5 に答える 5

4

これは、デバイス上のすべての SD カードを見つけるために使用するクラスです。内蔵と取り外し可能。アイス クリーム サンドイッチで使用していますが、2 倍のレベルで機能するはずです。

public class GetRemovableDevice {

private final static String TAG = "GetRemoveableDevice";

public GetRemovableDevice() {
}

public static String[] getDirectories() {
    MyLog.d(TAG, "getStorageDirectories");
    File tempFile;
    String[] directories = null;
    String[] splits;
    ArrayList<String> arrayList = new ArrayList<String>();
    BufferedReader bufferedReader = null;
    String lineRead;

    try {
        arrayList.clear(); // redundant, but what the hey
        bufferedReader = new BufferedReader(new FileReader("/proc/mounts"));

        while ((lineRead = bufferedReader.readLine()) != null) {
            MyLog.d(TAG, "lineRead: " + lineRead);
            splits = lineRead.split(" ");

            // System external storage
            if (splits[1].equals(Environment.getExternalStorageDirectory()
                    .getPath())) {
                arrayList.add(splits[1]);
                MyLog.d(TAG, "gesd split 1: " + splits[1]);
                continue;
            }

            // skip if not external storage device
            if (!splits[0].contains("/dev/block/")) {
                continue;
            }

            // skip if mtdblock device

            if (splits[0].contains("/dev/block/mtdblock")) {
                continue;
            }

            // skip if not in /mnt node

            if (!splits[1].contains("/mnt")) {
                continue;
            }

            // skip these names

            if (splits[1].contains("/secure")) {
                continue;
            }

            if (splits[1].contains("/mnt/asec")) {
                continue;
            }

            // Eliminate if not a directory or fully accessible
            tempFile = new File(splits[1]);
            if (!tempFile.exists()) {
                continue;
            }
            if (!tempFile.isDirectory()) {
                continue;
            }
            if (!tempFile.canRead()) {
                continue;
            }
            if (!tempFile.canWrite()) {
                continue;
            }

            // Met all the criteria, assume sdcard
            arrayList.add(splits[1]);
        }

    } catch (FileNotFoundException e) {
    } catch (IOException e) {
    } finally {
        if (bufferedReader != null) {
            try {
                bufferedReader.close();
            } catch (IOException e) {
            }
        }
    }

    // Send list back to caller

    if (arrayList.size() == 0) {
        arrayList.add("sdcard not found");
    }
    directories = new String[arrayList.size()];
    for (int i = 0; i < arrayList.size(); i++) {
        directories[i] = arrayList.get(i);
    }
    return directories;
}

}

MyLog.d は、Log.d を展開するトレース クラスであり、削除できます。

クラスは /proc/mounts/ を読み取り、以下を読み取ります。

  1. パス名が内部 sdcard ディレクトリであるかどうかを確認します
  2. ブロックデバイスかどうかを確認します
  3. mtdblock デバイスをスキップします
  4. マウントされていないものはすべてスキップします
  5. secure および asec ディレクトリをスキップします
  6. 存在し、ディレクトリであり、読み取り/書き込みアクセス可能であることを確認します

これがすべて一致する場合、sdcard があると見なされ、パスがアレイ リストに追加されます。パス名の文字列配列を返します。

getDirectories 関数を呼び出すには、次のようなコードを記述します。

String[] sdcardDirectories = GetRemoveableDevice.getDirectories();

返されたパスは、ユーザー選択リストの作成、ファイルのスキャンなどに使用できます。

最後に、エミュレーター テストの MyLog.d の 2 行を次に示します (2 行目はエミュレーターの SD カードです)。

09-19 15:57:12.511: D/GetRemoveableDevice(651): lineRead: /dev/block/mtdblock2 /cache yaffs2 rw,nosuid,nodev 0 0

09-19 15:57:12.511: D/GetRemoveableDevice(651): lineRead: /dev/block/vold/179:0 /mnt/sdcard vfat rw,dirsync,nosuid,nodev,noexec,uid=1000,gid=1015 ,fmask=0702,dmask=0702,allow_utime=0020,codepage=cp437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro 0 0

于 2012-09-19T20:02:29.577 に答える
2

Howards クラスに基づいて、Galaxy S3 で動作するようにいくつかの変更を加えました。

  1. Environment.getExternalStorageDirectory() は、S3 の内部ストレージを返します。
  2. リムーバブル ストレージは必ずしも /mnt の下にマウントされているとは限りません
  3. リムーバブル メディアには vfat ファイルシステムが必要です

_

public static String getDirectory() {
        Log.d(TAG, "getStorageDirectories");
        File tempFile;
        String[] splits;
        ArrayList<String> arrayList = new ArrayList<String>();
        BufferedReader bufferedReader = null;
        String lineRead;

        try {
            arrayList.clear(); // redundant, but what the hey
            bufferedReader = new BufferedReader(new FileReader("/proc/mounts"));

            while ((lineRead = bufferedReader.readLine()) != null) {
                Log.d(TAG, "lineRead: " + lineRead);
                splits = lineRead.split(" ");

                // skip if not external storage device
                if (!splits[0].contains("/dev/block/")) {
                    continue;
                }

                // skip if mtdblock device
                if (splits[0].contains("/dev/block/mtdblock")) {
                    continue;
                }

                // skip if not in vfat node
                if (!splits[2].contains("vfat")) {
                    continue;
                }

                // skip these names
                if (splits[1].contains("/secure")) {
                    continue;
                }

                if (splits[1].contains("/mnt/asec")) {
                    continue;
                }

                // Eliminate if not a directory or fully accessible
                tempFile = new File(splits[1]);
                if (!tempFile.exists()) {
                    continue;
                }
                if (!tempFile.isDirectory()) {
                    continue;
                }
                if (!tempFile.canRead()) {
                    continue;
                }
                if (!tempFile.canWrite()) {
                    continue;
                }

                // Met all the criteria, assume sdcard
                return splits[1];
            }

        } catch (FileNotFoundException e) {
        } catch (IOException e) {
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                }
            }
        }

        return null;
    }
于 2013-11-30T16:59:56.050 に答える
1

これらの機能は、すべてのAndroidバージョンで利用できます。

  • 外部ストレージ上のアプリケーションのフォルダを取得するには、を呼び出しますContext.getExternalFilesDir

  • アプリが外部ストレージにアクセスするには明示的な権限が必要であり、アプリが経由で利用可能かどうかを確認する必要があることに注意してくださいEnvironment.getExternalStorageState

  • そして、はい、ACTION_MEDIA_MOUNTEDリムーバブルメディアがアクセス可能になるたびに放送されます(あなたはまた聞いてACTION_MEDIA_EJECTくださいACTION_MEDIA_REMOVED

于 2012-04-23T14:27:42.063 に答える