4

I want to save a text file to the SD card I inserted into my HTC One M8 running lollipop. However when I run this code it saves to internal storage instead.

String FILENAME = "mysavefile.txt";

    File file = new File(Environment.getExternalStorageDirectory(), FILENAME);

    if (isExternalStorageWritable()) {
        errorSD.setVisibility(View.INVISIBLE);
        try {
            FileOutputStream fos = new FileOutputStream(file, false);
            fos.write(allInformation.getBytes(), 0, 81);
            fos.close();
            successfulSubmissionToast();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            errorSD.setVisibility(View.VISIBLE);
        } catch (IOException e) {
            e.printStackTrace();
        }

It should be saving to

/storage/ext_sd

but instead it is saving to

/storage/emulated/0

Then I tried manually entering in the location of my SD card to see if that would work but it ended up throwing the FileNotFoundException

File file = new File("/storage/ext_sd", FILENAME);

Edit: I believe the issue is that there are multiple external storages. One being permanent and one temporary. The question is how do you access the second one.

jtreiner
  • 43
  • 4
  • 1
    Have you tried reading the documentation for [Using the External Storage](http://developer.android.com/guide/topics/data/data-storage.html#filesExternal)? – alanv Mar 25 '15 at 01:59
  • Yes I have multiple times but I could not find a solution to my issue. I understand that external storage does not always refer to the SD card but if it doesn't then how do I save to the SD card? – jtreiner Mar 25 '15 at 02:06
  • Where exactly in internal storage did it save the file? – Daniel Nugent Mar 25 '15 at 02:24
  • It didn't of course - it saved it on the External Storage, but not on the SD card which is apparently some sort of secondary external storage on this device. Vendors handle that in an inconsistent manner. – Chris Stratton Mar 25 '15 at 02:28
  • Its saving it to the outermost file of internal storage where the movies, music, downloads etc. folders are. /storage/emulated/0 – jtreiner Mar 25 '15 at 02:30
  • That is not an internal storage location, it is an **external storage** location, just not on the SD card. "external" refers to an API, not a physical characteristic. – Chris Stratton Mar 25 '15 at 02:30
  • Ok, then how do I save to SD card? or is it impossible? – jtreiner Mar 25 '15 at 02:37
  • Check [here](https://source.android.com/devices/storage/#multiple-external-storage-devices) to see how android handle multiple external storage. – alijandro Mar 25 '15 at 03:40
  • yes, this seems to be the solution. Can you please provide a code example of how this would work? – jtreiner Mar 25 '15 at 04:39
  • @jtreiner Check the new answer I posted below. – alijandro Mar 25 '15 at 06:56

4 Answers4

2

First of all, we need to understand about what is difference between Internal Storage, External Storage (aka primary external storage) and Secondary External Storage?

Internal Storage: is storage that is not accessible by the user, except via installed apps (or by rooting their device). Example: data/data/app_packageName

Primary External Storage: In built shared storage which is "accessible by the user by plugging in a USB cable and mounting it as a drive on a host computer". Example: When we say Nexus 5 32 GB.

Secondary External Storage: Removable storage. Example: SD Card.

getExternalStorageDirectory ()

It will return path of the primary external storage directory

To access removable SD (Secondary external storage) there are below APIs:

getExternalFilesDirs(), getExternalCacheDirs(), and getExternalMediaDirs()

Check there documentation for further information

Vikasdeep Singh
  • 20,983
  • 15
  • 78
  • 104
1

If the Android device following the guide here when deal with multiple external storage, we can use the following code to detect where to write the data for Android kitkat or higher version.

    final String APP_EXTERNAL_CACHE = "Android" + File.separator + "data"
            + File.separator + getPackageName() + File.separator + "cache";
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        for (File file : getExternalCacheDirs()) {
            if (file != null) {
                String mountPoint = file.getAbsolutePath().replace(APP_EXTERNAL_CACHE, "");

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    if (Environment.isExternalStorageRemovable(file)) {
                        Log.d(TAG, "removable external " + file.getAbsolutePath());
                    }
                    if (Environment.isExternalStorageEmulated(file)) {
                        Log.d(TAG, "emulated internal " + file.getAbsolutePath());
                    }
                } else {
                    if (mountPoint.contains("emulated")) {
                        Log.d(TAG, "emulated internal " + mountPoint);
                    } else {
                        Log.d(TAG, "removable external " + mountPoint);
                    }
                }
            }
        }
    }

And declare the relating permission in the manifest.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
alijandro
  • 11,627
  • 2
  • 58
  • 74
1

I want to save a text file to the SD card I inserted into my HTC One M8 running lollipop

You are welcome to try getExternalFilesDirs(), getExternalCacheDirs(), and getExternalMediaDirs() on Context. Note the plural form of the method name. For these methods, if they return more than one entry, the second and subsequent ones should be on removable media, pointing to directories that you can read and write, without any particular permission (e.g., WRITE_EXTERNAL_STORAGE).

Outside of those locations, for devices that shipped with Android 4.4+, you have no access to removable storage.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
-1

I think it's because HTC one modified the sdcard mount point, you should try adb shell ls -l commands to find out which path the sdcard mounted.

For example in nexus 4:

lrwxrwxrwx root     root              2015-03-24 18:26 sdcard -> /storage/emulated/legacy
drwxr-x--x root     sdcard_r          2015-03-24 18:26 storage

and you should make sure it is not a link: ls -l /storage/emulated/legacy

lrwxrwxrwx root     root              2015-03-24 18:26 legacy -> /mnt/shell/emulated/0

The path /mnt/shell/emulated/0 is actually sdcard path.

Try read How can I get external SD card path for Android 4.0+? too, this may help you a lot.

UPDATE

I tried this code:

    String test = "/storage/emulated/legacy"; // work
    //String test = "/mnt/shell/emulated/legacy"; // not work
    File sdDir = new File(test);
    if (sdDir.exists()) {
        File file = new File(test, "test.sdcard");
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

So you'd better try /storage/emulated/* directories to find out which is exactly your sdcard.

Community
  • 1
  • 1
tianyu
  • 179
  • 2
  • 6
  • Actually, no, you cannot use the ADB shell to find where something is mounted for apps, because the mounts are different for ADB vs. apps. But you can use a file manager app or terminal emulator, because they are (at least so far) generally the same for different apps. – Chris Stratton Mar 25 '15 at 02:29
  • I used a file manager and found that /storage/ext_sd is where the SD card is. /storage/emulated/0 is not the SD card. I know this because i removed the SD card and it was still there while /storage/ext_sd disappeared. – jtreiner Mar 25 '15 at 02:34
  • Depending on your goals that may help - ie, it is an answer for a given Android version on a given device. But by no means is it a portable answer. You also may find that you don't have permission to access it that way. – Chris Stratton Mar 25 '15 at 02:38
  • For me there are two files under /storage/emulated/. 0 and legacy. But they both lead to the same thing neither being the SD card. – jtreiner Mar 25 '15 at 04:05