SamPhoenix
SamPhoenix

Reputation: 99

how to save files on externalStorage

I've already figured out that on some devices the externalStorage may be set as the device Storage, like on my Samsung Galaxy 4 10.1 with 5.0.2. Android OS.

The Question now is how can I still say to save it on the SD-Card ? For Example:

    private File makeFolder(String folder) {
    File dir = new File(Environment.getExternalStorageDirectory() + "/" + folder + "/");

    if (!(dir.exists() && dir.isDirectory())) {
        dir.mkdirs();
    }
    return dir;
}

On my older Devices (like my Sony Ericson Pro) this works just fine. So how to solve this?

Upvotes: 0

Views: 528

Answers (1)

La Machine
La Machine

Reputation: 363

You are into a slightly complicated area of Android programming :)

I can not give you complete answer here, but I can give some pointers:

On almost all devices I've seen, Environment.getExternalStorageDirectory() will give you the path to the root directory of an emulated SDCARD - which is not a physical SDCARD. Manufacturers are free to map the physical SDCARD to this path - but usually, they emulate an SDCARD using internal memory)

And prior to Kitkat, there are no API available to even to determine the presence of a physical SDCARD.

From Kitkat onwards, you can see if a physical SDCARD is present by checking the result of appContext.getExternalFilesDirs() which will give you your app's private data directory path on all available storage media.

If a physical SDCARD is present and mounted, appContext.getExternalFilesDirs() will give you two paths are result. Then the first one is for the emulated SDCARD. You may notice that this path will contain same subpath that returned by Environment.getExternalStorageDirectory().

The following example will make this clearer. I am assuming a Samsung S4 with a real SDCARD inserted and mounted in it

The first path returned will be:

/storage/emulated/0/Android/data/com.example.yourapp/files.

The second path is interesting - as this path is your app's accessible area on the the real physical SDCARD. This path will be of the form:

/storage/extSdCard/Android/data/com.example.yourapp/files

This is the only path that you have write access in Kitkat.

So, from Kitkat onwards, from the presence of these two paths, (and added checks for mounted SDCARD), you can easily find out whether your app is running on a phone with real SDCARD or not. You can even parse the second path to get the root directory of the real SDCARD (just remove /Android/... substring from this path)

And yes, now you know why you are so restricted with real SDCARDs in Kitkat. As said in italics above, you have write access to only that directory on a physical SDCARd in Kitkat.

Now comes Marshmallow and things changes again. In Marshmallow you have a storage framework, using which you can present the user with a permission dialog box and you can tell him to grant your app complete access to whatever device or directory therein. Please search for "Intent.ACTION_OPEN_DOCUMENT_TREE" for nice tutorials.

So, in short, as of now, there is no nice way in Android to deal with SDCARD which works uniformly in all versions. Before Kitkat, it is a grey area, In Kitkat, you are severely restricted, and in Lollipop, you are stuck with a system Activity with an absurd looking GUI for permission and not so easy to use framework.

Upvotes: 1

Related Questions