Akom's Tech Ruminations

Various tech outbursts - code and solutions to practical problems

Switchable Storage Locations in an Android App

Posted by Admin • Saturday, October 13. 2012 • Category: Android
This is also a typical pattern. In my app, I need to offer the user a choice of storage locations without getting too low-level. I am content with offering three options in a ListPreference:
  1. Private to application
  2. Public but on the main storage
  3. Public but on the removable storage (actual SD card)
Here is how I am doing it in a relatively generic and reusable manner (using an enum)

Continue reading "Switchable Storage Locations in an Android App"

Getting location of the removable storage on Android

Posted by Admin • Saturday, October 13. 2012 • Category: Android
Seems like a fairly typical problem, yet there are dozens of implementations and no standard. Here is mine:

        private static File s_removableStoragePath;

        /**
          Utility function that attempts to find the removable storage directory
         
(as opposed to {@link Environment#getExternalStorageDirectory()} which is usually non-removable)
          by running "mount" and parsing the output.   This implementation looks for
         
the strings "vfat" and "vold", eg:
          /dev/block/vold/179:97 /mnt/extSdCard vfat rw,dirsync,nosuid,nodev,noexec,noatime,nodiratime,uid=1000,gid=1023,fmask=0002,dmask=0002,allow_utime=0020,codepage=cp437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro 0 0
         

          The result will be cached indefinitely.
         

         * @return either a valid file or null.  This may not be accessible, but it does exist
         */

        public static File findRemovableStorage() {
                if (s_removableStoragePath != null && s_removableStoragePath.exists()) {
                        return s_removableStoragePath;
                }
                s_removableStoragePath = null;
                String result = null;
                try {
                        Process process = new ProcessBuilder().command("mount")
                                        .redirectErrorStream(true).start();

                        process.waitFor();

                        InputStream is = process.getInputStream();
                        BufferedReader isr = new BufferedReader(new InputStreamReader(is));

                        String line = null;
                        while ((line = isr.readLine()) != null) {
                                if (-1 != line.indexOf("vold") && -1 != line.indexOf("vfat")) {
                                        String[] blocks = line.split("\\s");
                                        if (blocks.length > 2) {
                                                result = blocks[1];
                                        }
                                }
                        }
                        if (result != null) {
                                s_removableStoragePath = new File(result);
                                if (!s_removableStoragePath.exists()) {
                                        s_removableStoragePath = null;
                                }
                        }
                } catch (Throwable t) {
                        Log.e(IntegratorUtils.class.getSimpleName(),
                                        "Unable to find external mount point");
                }
                return s_removableStoragePath;
        }