表題の通りなのですが、
最近のアンドロイドは内部、外部とストレージがあり外部ストレージの判定が困難です。。
今までどおりgetExternalStorageなメソッドで色々取得しようとすると
外部ストレージの情報ではなく内部ストレージの情報が返ってきます。
というわけで下記サイトさまの記事を参考にさせていただき
色々とやってみました。
参考:
http://d.hatena.ne.jp/yohpapa/20111229/1325147606http://inujirushi123.blog.fc2.com/blog-date-20121110.html
細かいことは飛ばしてしまいますが
1.File("/system/etc/vold.fstab")にシステム的に振り分けられる外部ストレージのパスが書いてあるので
それを取得する。
2.Runtime.getRuntime().exec("mount")で1でもってきたパスを使ってマウント判定をする。
3.マウントされてるパスがあればStatFs(path)で今までどおりサイズを取得。
という流れで取れそうです。
というわけで長々と書くのもあれなんでこんな感じ。
-----------------------------------------------
/**
* マウントされてるストレージパスの全容量を返す
* @return -1:ストレージ無 0以外:全容量(Byte)
*/
public static long isGetStorageMemoryTotalSizeFull() {
List<String>mountList = new ArrayList<String>();
for (String path : isGetMountStoragePaths()) {
if (isMounted(path))
mountList.add(path);
}
long size=-1;
for (String path :mountList) {
size = isGetTotalStorageSize(path);
}
return size;
}
/**
* マウントされてるストレージパスの全使用容量を返す
* @return -1:ストレージ無 0以外:全使用容量(Byte)
*/
public static long isGetStorageMemoryAvailableSizeFull() {
List<String>mountList = new ArrayList<String>();
for (String path : isGetMountStoragePaths()) {
if (isMounted(path))
mountList.add(path);
}
long size=-1;
for (String path :mountList) {
size = isGetAvailableStorageSize(path);
}
return size;
}
/**
* マウントされるストレージパスの一覧を取得
* @return List<(String)pathが入る>
*/
public static List<String> isGetMountStoragePaths() {
List<String> mountList = new ArrayList<String>();
Scanner scanner = null;
try {
scanner = new Scanner(new FileInputStream(new File(
"/system/etc/vold.fstab")));
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.startsWith("dev_mount") || line.startsWith("fuse_mount")) {
String path = line.split(" ")[2].replaceAll(":.*$", "");
if (!mountList.contains(path)){
File dir = new File(path + "/");
if (dir.canRead()){
mountList.add(path);
}
}
}
}
} catch (Exception e) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD){
//この判定しないと4.2以降で内部ストレージを外部ストレージとして扱われる(例:Nexus7 (Android4.3)の場合など)
if(Environment.isExternalStorageRemovable()){
mountList = new ArrayList<String>();
mountList.add(Environment.getExternalStorageDirectory().getAbsolutePath());
}
}else{
mountList = new ArrayList<String>();
mountList.add(Environment.getExternalStorageDirectory().getAbsolutePath());
}
} finally {
if (scanner != null) {
scanner.close();
}
}
return mountList;
}
/**
* path先がマウントされてるか
* @return 1(true):ok 0(false):ng
*/
public static boolean isMounted(String path) {
boolean isMounted = false;
Process process =null;
BufferedReader reader = null;
try {
process = Runtime.getRuntime().exec("mount");
reader = new BufferedReader(new InputStreamReader(
process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
if (line.contains(path)) {
isMounted = true;
break;
}
}
// プロセスが終了するまで待つ
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
}
}
process.destroy();
}
return isMounted;
}
/**
* path先の使用容量を返す
* @return 0:失敗 0以外:メモリ容量(Byte)
*/
public static long isGetAvailableStorageSize(String path){
StatFs fs = new StatFs(path);
long bkSize = fs.getBlockSize();
long avaBlocks = fs.getAvailableBlocks();
return bkSize * avaBlocks;
}
/**
* path先の総容量を返す
* @return 0:失敗 0以外:メモリ容量(Byte)
*/
public static long isGetTotalStorageSize(String path){
StatFs fs = new StatFs(path);
long bkSize = fs.getBlockSize();
long bkCount = fs.getBlockCount();
return bkSize * bkCount;
}
-----------------------------------------------
long total=isGetStorageMemoryTotalSizeFull();
で総容量。
long available=isGetStorageMemoryAvailableSizeFull();
で使用容量。
んで総容量が0以下なら外部ストレージがないんじゃないって判定ですかね。
使用率なんかはお好きに。
補足:
isGetMountStoragePathsでパスを取ってますがvold.fstabがないものもあるっぽい。。
このあいだNexus7を4.3にアップデートしたらなくなってました。。
そうするとcatchされるのでそこでisExternalStorageRemovable()を使い取り外しできるストレージかどうかを判定して返してます。
という所でざっくりですがこんな感じで終わります。
もっといい方法あるよ!ってものがあれば教えてほしいです(・ω・;)
最後にサンプルファイルをこちらにおいておきます。
*Util.javaに色々メソッドいれときました。