/* * Copyright 2014 Albert Vaca Cintora <albertvaka@gmail.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kde.kdeconnect.Helpers; import android.os.Environment; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Scanner; import java.util.StringTokenizer; //Code from http://stackoverflow.com/questions/9340332/how-can-i-get-the-list-of-mounted-external-storage-of-android-device/19982338#19982338 //modified to work on Lollipop and other devices public class StorageHelper { public static class StorageInfo { public final String path; public final boolean readonly; public final boolean removable; public final int number; StorageInfo(String path, boolean readonly, boolean removable, int number) { this.path = path; this.readonly = readonly; this.removable = removable; this.number = number; } } /* * This function is bullshit because there is no proper way to do this in Android. * Patch after patch I'm making it even more horrible by trying to make it work for *more* * devices while trying no to break previously working ones. * If this function was a living being, it would be begging "please kill me". */ public static List<StorageInfo> getStorageList() { List<StorageInfo> list = new ArrayList<>(); String def_path = Environment.getExternalStorageDirectory().getPath(); boolean def_path_removable = Environment.isExternalStorageRemovable(); String def_path_state = Environment.getExternalStorageState(); boolean def_path_available = def_path_state.equals(Environment.MEDIA_MOUNTED) || def_path_state.equals(Environment.MEDIA_MOUNTED_READ_ONLY); boolean def_path_readonly = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED_READ_ONLY); HashSet<String> paths = new HashSet<>(); int cur_removable_number = 1; if (def_path_available) { paths.add(def_path); list.add(0, new StorageInfo(def_path, def_path_readonly, def_path_removable, def_path_removable ? cur_removable_number++ : -1)); } File storage = new File("/storage/"); if (storage.exists() && storage.isDirectory()) { String mounts = null; try { Scanner scanner = new Scanner( new File("/proc/mounts") ); mounts = scanner.useDelimiter("\\A").next(); scanner.close(); //Log.e("Mounts",mounts); } catch(Exception e) { e.printStackTrace(); } File dirs[] = storage.listFiles(); for (File dir : dirs) { //Log.e("getStorageList", "path: "+dir.getAbsolutePath()); if (dir.isDirectory() && dir.canRead() && dir.canExecute()) { String path, path2; path2 = dir.getAbsolutePath(); try { //Log.e(dir.getAbsolutePath(), dir.getCanonicalPath()); path = dir.getCanonicalPath(); } catch(Exception e){ path = path2; } if (!path.startsWith("/storage/emulated") || dirs.length == 1) { if (!paths.contains(path) && !paths.contains(path2)) { if (mounts == null || mounts.contains(path) || mounts.contains(path2)) { list.add(0, new StorageInfo(path, false, true, cur_removable_number++)); paths.add(path); } } } } } } else { //Legacy code for Android < 4.0 that still didn't have /storage ArrayList<String> entries = new ArrayList<>(); BufferedReader buf_reader = null; try { buf_reader = new BufferedReader(new FileReader("/proc/mounts")); String entry; while((entry = buf_reader.readLine()) != null) { //Log.e("getStorageList", entry); if (entry.contains("vfat") || entry.contains("exfat") || entry.contains("ntfs") || entry.contains("/mnt")) { if (entry.contains("/storage/sdcard")) entries.add(0, entry); else entries.add(entry); } } } catch (Exception e) { e.printStackTrace(); } finally { if (buf_reader != null) { try { buf_reader.close(); } catch (IOException ex) { } } } for (String line : entries) { StringTokenizer tokens = new StringTokenizer(line, " "); tokens.nextToken(); //device String mount_point = tokens.nextToken(); //mount point if (paths.contains(mount_point)) { continue; } tokens.nextToken(); //file system List<String> flags = Arrays.asList(tokens.nextToken().split(",")); //flags boolean readonly = flags.contains("ro"); if (line.contains("/dev/block/vold")) { if (!line.contains("/mnt/secure") && !line.contains("/mnt/asec") && !line.contains("/mnt/obb") && !line.contains("/dev/mapper") && !line.contains("tmpfs")) { paths.add(mount_point); list.add(new StorageInfo(mount_point, readonly, true, cur_removable_number++)); } } } } return list; } }