108

I understand that ExternalFiles is to be used on API 8 and up and getExternalStorageDirectory is for 7 and down. However I am a little confused between the use. For example I wanted to check that a folder that exists and previously you would use something like:

File ChildFolder = new File(Environment.getExternalStorageDirectory() + "/ParentFolder/Child");

However every example I see says to use getExternalFilesDir (null), File.ext. Since I am above API 8 I want to use this method but how do I just check for a folder? I will check for a files existence at another point but for now just want to see if the folders exist??

Mayank Kumar Chaudhari
  • 16,027
  • 10
  • 55
  • 122
GPGVM
  • 5,515
  • 10
  • 56
  • 97

4 Answers4

153
getExternalFilesDir()

It returns the path to files folder inside Android/data/data/your_package/ on your SD card. It is used to store any required files for your app (e.g. images downloaded from web or cache files). Once the app is uninstalled, any data stored in this folder is gone too.

getExternalStorageDirectory()

It returns the root path to your SD card (e.g mnt/sdcard/). If you save data on this path and uninstall the app, that data won't be lost.

waqaslam
  • 67,549
  • 16
  • 165
  • 178
  • 1
    So are you saying that Google Android guys want you to only use getExternalFilesDir() API 8 and up therefore if you are compliant your files will be deleted at uninstall? Don't get me wrong I want this behavior as I don't want files left around if someone uninstalls. The other item I am unsure of, but experimenting now, is exactly how it returns if a folder is there. For example will it return anything for this line: File(getExternalFilesDir(null), "/ParentFldr/ChildFldr"); – GPGVM Apr 12 '12 at 14:36
  • 7
    Google Android wants you to use whatever they provide within the framework. So its up to your choice and design requirements. If you don't want the files to stay left when the app is uninstalled then your are encouraged to use **getExternalFilesDir()** or **getExternalCacheDir()** – waqaslam Apr 12 '12 at 14:50
  • Well sure I can see exactly what you are saying...I'm just confused by this line from Dev Docs. "If you're using API Level 7 or lower, use getExternalStorageDirectory(), to..." and "If you're using API Level 8 or greater, use getExternalFilesDir() to open a File that..." these two lines come from here: http://developer.android.com/guide/topics/data/data-storage.html#filesExternal. I believe you and have used both with success I just didn't want to use something that may disappear from future API releases. – GPGVM Apr 12 '12 at 19:20
  • 5
    Its because in API 8, they introduced advanced media scanner features which allows to scan data from folders like music, pictures, ringtones, etc. Those directories are automatically created only if you use **getExternalFilesDir()**. Now since this feature wasn't available in API 7 that's why they recommended to use **getExternalStorageDirectory()**. Simple... – waqaslam Apr 12 '12 at 19:31
  • I need to go back and do more reading. Something is not clicking in my pea brain and you've certainly been patient trying to help me. Thank You very much. – GPGVM Apr 13 '12 at 03:25
  • 2
    its ok, give it some time, soon there will be an *eureka* moment :) – waqaslam Apr 13 '12 at 05:56
  • Do the files placed in `getExternalFilesDir()` get deleted when mounting device as a Disk Storage? – Alex Semeniuk Feb 14 '13 at 10:07
  • @AlexSemeniuk nothing gets deleted but will be unavailable till the storage is mounted back. – waqaslam Feb 14 '13 at 10:14
  • 8
    It's important to know that `getExternalStorageDirectory()` does *not necessarily* -- maybe even **not usually** -- return the "path to your SD card." Instead it returns the "primary external storage directory". The docs (https://developer.android.com/reference/android/os/Environment.html#getExternalStorageDirectory()) say: – LarsH Jun 22 '17 at 14:11
  • 2
    'Note: don't be confused by the word "external" here. This directory can better be thought as media/shared storage. It is a filesystem that can hold a relatively large amount of data and that is shared across all applications (does not enforce permissions). **Traditionally** this is an **SD card**, but it may also be implemented as built-in storage in a device that is distinct from the protected internal storage and can be mounted as a filesystem on a computer.' – LarsH Jun 22 '17 at 14:11
  • What is `SD` card? These have always been wrongly used. That method returns the path to the primary storage on your phone. It works even without an actual SD card plugged into the SD card slot. – TheRealChx101 Sep 19 '22 at 21:15
100

First of all, we need to understand 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.

getExternalFilesDir (String type)

It returns the path to files folder inside Android/data/data/your_package/ on primary external storage. Which is inbuilt storage.

Environment.getExternalStorageDirectory()

It will return the path of the secondary external storage directory

Vikasdeep Singh
  • 20,983
  • 15
  • 78
  • 104
  • Thanks for explaining the different types of storage. However, maybe edit the _internal storage_ item to mention that the method call to get that value is getFilesDir(). Well, I guess that method actually returns data/data/app_packageName/files but it is still internal storage. – raddevus Nov 10 '15 at 13:30
  • 3
    @VicJordan Please write about `File getExternalStoragePublicDirectory (String type)` and `File getFilesDir ()` as well – AnV Jul 29 '16 at 08:55
  • 2
    Thanks Vic. Environment.getExternalStorageDirectory() outputs /storage/emulated/0 – gimmegimme Feb 10 '17 at 04:05
  • Do you have any documentation for the statement that primary external storage is alway built-in, whereas secondary is always removable? I thought those were independent issues... some phones don't have built-in "external" storage, in which case the primary external storage might be the removable SD card. – LarsH Jun 05 '17 at 16:52
  • @LarsH, as per my knowledge currently there is no phone in the market or coming near future which will not have built-in primary external storage. There were phones at the time of gingerbread when such phones existed but not now. Could you please name "some" phones which don't have built-in "primary external storage"? – Vikasdeep Singh Jun 07 '17 at 02:35
  • I've encountered such phones, and I don't have a device with a version as old as Gingerbread, so I should be able to come up with one. If so I will post here, but it will take some time to test for this. However even if I can't find such an example, it seems pretty dangerous to represent "As far as I'm aware, on all phones since Gingerbread, X is effectively equivalent to Y" as "X = Y". Especially if there's no documentation to support the idea. – LarsH Jun 08 '17 at 17:02
  • Is this path(Android/data/data/your_package/) limited for any application? for example, if Primary External Storage has 3 gig free,could I (android developer) save 3 gig data on this folder? – Fereshteh Naji Jun 12 '19 at 10:26
  • 1
    This answer is wrong. getExternalStorageDirectory returns /storage/emulated/0 which is the Primary internal storage – MSeiz5 Jul 19 '19 at 11:41
  • `Android/data/data/your_package/` has an extra "data" in it. Should be: `Android/data/your_package/` – BLuFeNiX Jul 29 '21 at 15:23
  • t's important to know that getExternalStorageDirectory() does not necessarily -- maybe even not usually -- return the "path to your SD card." Instead it returns the "primary external storage directory". – nikhil123 Sep 15 '21 at 06:12
23

! IMPORTANT UPDATE ! for whoever comes across this question.

As this is a somewhat old question just wanted to provide some additional information. Since KitKat even apps that have WRITE_EXTERNAL_STORAGE permission are only allowed to write to Android/data/data/your_package/ on external storage, a.k.a getExternalFilesDir()

If you will try to write to getExternalStorageDirectory() + "/somefolder/anotherfolder/" you will get a SecurityException on most devices

SGal
  • 1,072
  • 12
  • 13
  • 13
    According to the docs, apps that have the WRITE_EXTERNAL_STORAGE permission CAN write to other packages' external storage, not just their own. It's apps that do NOT have the permission that can only write to their own directory: https://developer.android.com/reference/android/content/Context.html#getExternalFilesDir(java.lang.String) "Starting in KITKAT, no permissions are required to read or write to the returned path; it's always accessible to the calling app... To access paths belonging to other packages, WRITE_EXTERNAL_STORAGE and/or READ_EXTERNAL_STORAGE are required." – Oded Jun 12 '16 at 22:30
  • This is where "on most devices" begins to matter as android docs generalizes the idea, but manufacturers sometimes have things like InternalStorage (built-in storage for app data), ExternalStorage-Primary (*also built-in storage* with a bigger access scope) and ExternalStorage-Secondary (this would be mounted stuff like SD cards). Now you can take a guess which path get*External*StorageDirectory returns – SGal Jun 14 '16 at 09:05
  • 8
    That's doesn't address the incorrect information in your answer. "Since KitKat even apps that have WRITE_EXTERNAL_STORAGE permission are only allowed to write to Android/data/data/your_package/ on external storage, a.k.a getExternalFilesDir()". Per the docs, this is wrong. With WRITE_EXTERNAL_STORAGE, apps can write to all external storage. – Oded Jun 19 '16 at 06:31
  • 1
    @Oded, have you tested this? My understanding of the docs, and my experience with KitKat and later devices, is different from yours. (Wish I had time to hash out all the details now. Maybe later.) My experience is that SGal is right. Then there's also Lollipop which is a little different. – LarsH Jun 05 '17 at 16:55
  • 3
    This answer is blatantly false, according to Android's documentation. See https://developer.android.com/reference/android/Manifest.permission.html#WRITE_EXTERNAL_STORAGE "Starting in API level 19, this permission is not required to read/write files in your application-specific directories returned by getExternalFilesDir(String) and getExternalCacheDir()." (Note that API level 19 = KitKat.) No idea how it got so many upvotes. – Ajedi32 Oct 05 '17 at 16:39
  • @Ajedi32 maybe because behavior of some phones (Galaxy S2 in my experience) is not according to the documentation. Might be a bug, might be a configuration (multiple internal/external partitions) that google didn't account for when documenting. I can read, I know what documentation says. Just putting out there what my personal experience was. – SGal Oct 10 '17 at 09:09
  • I can say one hundred percent that on SM-N900 Android 5.0 it raises a SecurityException when trying to read data using createPackageContext(..). getExternalFilesDirs(null) – Сергей Apr 15 '19 at 08:54
16

!! IMPORTANT !!

Environment.getExternalStorageDirectory() is deprecated and Context#getExternalFilesDir(String), MediaStore, or Intent#ACTION_OPEN_DOCUMENT, should be used instead.

This method was deprecated in API level 29. To improve user privacy, direct access to shared/external storage devices is deprecated. When an app targets Build.VERSION_CODES.Q, the path returned from this method is no longer directly accessible to apps. Apps can continue to access content stored on shared/external storage by migrating to alternatives such as Context#getExternalFilesDir(String), MediaStore, or Intent#ACTION_OPEN_DOCUMENT.

https://developer.android.com/reference/android/os/Environment.html#getExternalStorageDirectory()

Also beginning from Android.M developers need to ask for permissions at run time.

See more details in documentation here and this question

Environment.getExternalStorageDirectory() deprecated in API level 29 java

Community
  • 1
  • 1
Mayank Kumar Chaudhari
  • 16,027
  • 10
  • 55
  • 122
  • if anyone is looking for a stack overflow link and not something copy pasted from google docs look here https://stackoverflow.com/questions/57116335/environment-getexternalstoragedirectory-deprecated-in-api-level-29-java – Rowan Berry Mar 06 '20 at 02:59
  • 6
    Starting in Android 11, apps cannot create their own app-specific directory on external storage. – Darksymphony Nov 12 '20 at 21:16
  • Apps \*technically\* cannot, but system can do this for them: https://stackoverflow.com/questions/64044993/android-11-doesnt-create-app-directory-on-external-storage – mirh Nov 14 '21 at 23:33