LoginSignup
27
28

More than 5 years have passed since last update.

SDカードのパスを(強引に)取得する方法

Posted at

はじめに

Androidで外部ストレージ(SDカード)のパスを取得する場合、昔であればEnvironment.getExternalStorageDirectory()が使えました。
しかし、最近ではこのメソッドはほとんどの場合内部ストレージのパスを返すようになってしまい、しかもSDカードのパスは機種によってバラバラという混沌とした状況になっています。

調べてみるとvold.fstabをなめ回すなどの裏技的手法があることがわかりますが、一部の機種では使用できないという情報もあるので、ここでは別の方法を紹介します。

リムーバブルストレージのパスを取得する

肝となるのはStorageManagerが隠し持っているgetVolumeList()というメソッドです。
このメソッドはStorageVolumeオブジェクトの一覧を返し、StorageVolumeはファイルパスや取り外し可否などの情報を持っています。
非公開のメソッド・クラスにアクセスするので、リフレクションを使用します。
このメソッドはマウントされていないストレージのパスも取得します。

リムーバブルストレージのパス一覧を取得する
public static String[] getRemovableStoragePaths(Context context) {
    List<String> paths = new ArrayList<String>();
    try {
        StorageManager sm = (StorageManager)context.getSystemService(Context.STORAGE_SERVICE);
        Method getVolumeList = sm.getClass().getDeclaredMethod("getVolumeList");
        Object[] volumeList = (Object[])getVolumeList.invoke(sm);
        for (Object volume : volumeList) {
            Method getPath = volume.getClass().getDeclaredMethod("getPath");
            Method isRemovable = volume.getClass().getDeclaredMethod("isRemovable");
            String path = (String)getPath.invoke(volume);
            boolean removable = (Boolean)isRemovable.invoke(volume);
            if (removable) {
                paths.add(path);
            }
        }
    } catch (ClassCastException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    return paths.toArray(new String[paths.size()]);
}

メリット

  • ICS以降で(たぶん)動く(Honeycombはソースも実機もないので知らん)
  • 機種への依存度が低い気がする(未確認のため情報求む)
  • リムーバブルかどうかの判断ができるので、誤って内部ストレージを検出する心配がない
  • USB機器など複数の外部ストレージがある場合にも対応できる

デメリット

  • Gingerbread以前では使えない(getVolumeList()が無いと言われる)
  • 非公開APIなので、将来使えなくなる可能性がある

ちなみにKitKatでは

Context#getExternalFilesDirs(String)というAPIが追加され、複数の外部ストレージ上のアプリ固有パスを取得できるようになったようです。
KitKat以降ではSDカードへの書き込みが制限されたので、書き込みが目的であればこちらを使ったほうが良さそうです。

27
28
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
28