Androidのストレージ構成がわからない開発者

Androidには内部ストレージと外部ストレージというものある
簡単に説明すると

という事になる。

Androidの機種は内部ストレージの容量が小さいものが多いので、SDカードで補強といった感じで使っている人も多いだろう

今回問題にするのはSDカードと内部ストレージをアプリ側からどのようにアクセスするかというのがということだ

とりあえずファイラーで見る


▲EZファイルエクスプローラーにて現れた2つのSDカード

僕の使っているHuawei P9liteでは上記のように出てくる。ここで一つ問題になる。

なぜ2つのSDカードが存在するのか

不条理なフォルダ構成

上記のファイルを見ておそらく思う事だろう。

こんな風に思った人は意気揚々と「端末」をタップして中のファイルを漁る…


▲驚異の空フォルダ なんと…端末の中は空フォルダではないか。一体僕のデータはどこに行ってしまったのか??
その答えは2つのSDカードフォルダにある。なんとこのSDカードフォルダ
「0」フォルダが内部ストレージ  「C031-1B0D」が外部ストレージなのだ!!

アプリ内からファイルを探る

2つのSDカード、なぜこんなことが起きてしまったのかというと、むかしむかしあるところにAndroidと2人のユーザがおりまして…(以下略)
----詳細については

さて、なんか闇が深そうなAndroidのファイル構成の探求をまだまだ続けていきます
先ほど内部ストレージだと言った「0」フォルダですが、Android内のパスは「/storage/emulated/0」となっています。
次にSDカードにあたる「C031-1B0D」フォルダは、Android内のパスは「/storage/C031-1B0D」となっています。

なぜ内部ストレージにはemulatedフォルダが間に挟まるのか不思議ですが、さらに不思議なことが。 adb shell からAndroidのファイルを除くと「/sdcard/」フォルダが存在します。これはSDカードのデータが入っているのではなく、

内部ストレージ
のデータが入っています(「0」フォルダと同じです)

これ以上探求しても頭が混乱するので答え

端末内の「/sdcard/」「/storage/emulated/0/」「/storage/self/primary/」「/storage/sdcard0/」「/mnt/user/0/primary」は全て同じデータで内部ストレージのデータである(お互いにリンクされている)。
「/storage/C031-1B0D/」「/storage/sdcard1/」はお互いにリンクされておりSDカードのデータだと思われる。
EZファイルエクスプローラーの「端末」フォルダは絶対パスでいうところの「/」を表しており、アプリでは「/」直下のファイル構造を取得することはできない。

おそらくリンクされてるフォルダの実態は「/mnt/user/0/primary」と「/storage/C031-1B0D/」であると筆者は考えている。
その理由はマルチユーザ対応 ANDROID 4.2以降の内部ストレージと外部ストレージ (4.4対応を追記)を読むとよい。


開発者が各ストレージのファイルにアクセスするには

内部ストレージにアクセスする

Environment.getExternalStorageDirectory().getPath();
これで十分です

SDカードにアクセスする

Android:SDカード(外部ストレージ)のパスを取得する方法(機種依存対策)
このサイトに書いてある方法で大丈夫です
逆に言えばいちいち取り外し可能かを調べなかればいけません

        File[] folderList=getExternalFilesDirs(null);
        for(int i=0;i<folderList.length;i++){
        if (Environment.isExternalStorageRemovable(folderList[i])) {
        //取り外し可能なのでSDカード
        String SDPath=folderList[i].getPath().split("Android")[0];
        System.out.println(SDPath);
        }
        }
        
▲具体的なコード(Activity.javaで走らせることを想定しています)
更新:2017/09/16

記事リンク