2

My app has to check if a certain folder is on the secondary storage when the Android version is 4.4+.

I am using this:

private boolean isPathOnSecondaryStorage(String path) {
    boolean res=false;
    String secondaryStorage=System.getenv("SECONDARY_STORAGE");
    String[] secondaryPaths=secondaryStorage.split(":");
    for (int i=0;i<secondaryPaths.length;i++) {
        String secondaryPath=secondaryPaths[i].trim();
        if (path.contains(secondaryPath)) {
            res=true;
        }
    }
    return res;
}

Note that:

  • path is chosen by the user by means of a file chooser activity, starting from /mnt

  • the app wants to check what is mounted as usual, like when an external SD-card is inserted in its slot

So I ask whether the above mentioned code will be always able to detect when the path is on a secondary storage, or instead on some devices it could find strange mounting points different from /mnt (Android 4.4+).

Linga
  • 10,379
  • 10
  • 52
  • 104
P5music
  • 3,197
  • 2
  • 32
  • 81

1 Answers1

1

Here is my current solution. Not ideal, but it should work.

/**
 * Uses the Environmental variable "SECONDARY_STORAGE" to locate a removable micro sdcard
 * 
 * @return  the primary secondary storage directory or
 *          {@code null} if there is no removable storage
 */
public static File getRemovableStorage() {
    final String value = System.getenv("SECONDARY_STORAGE");
    if (!TextUtils.isEmpty(value)) {
        final String[] paths = value.split(":");
        for (String path : paths) {
            File file = new File(path);
            if (file.isDirectory()) {
                return file;
            }
        }
    }
    return null;
}

/**
 * Checks if a file is on the removable SD card.
 * 
 * @see {@link Environment#isExternalStorageRemovable()}
 * @param file a {@link File}
 * @return {@code true} if file is on a removable micro SD card, {@code false} otherwise
 */
public static boolean isFileOnRemovableStorage(File file) {
    final File microSD = getRemovableStorage();
    if (microSD != null) {
        String canonicalPath;
        try {
            canonicalPath = file.getCanonicalPath();
            if (canonicalPath.startsWith(microSD.getAbsolutePath())) {
                return true;
            }
        } catch (IOException e) {
        }
    }
    return false;
}
Jared Rummler
  • 37,824
  • 19
  • 133
  • 148
  • Will getCanonicalPath() always yield the path starting with '/mnt'? It is very important. – P5music Aug 12 '14 at 11:04
  • getCanonicalPath() will follow any symlinks, so if the true path to secondary storage doesn't start with /mnt then the answer is no. It shouldn't matter though since you won't use getCanonicalPath() anywhere else. – Jared Rummler Aug 12 '14 at 20:04
  • 1
    Based on the `for (String path : paths) { File file = new File(path); if (file.isDirectory()) { return file; } }` Why can you make sure the first element is the removable SD card? Thanks. – Hsin-Hsiang Mar 09 '15 at 01:38
  • I remembered that this solution is working before, but today i tested it again on ASUS_Z00LDD, android version 6.0.1 and not working. `System.getenv("SECONDARY_STORAGE")` will result only:`/storage/sdcard1` but when `file.isDirectory()` called, it will not recognize it as an directory. Also the real sd card path is `/storage/3FBF-1DF5/` – HendraWD Aug 30 '17 at 10:14