In many cases, your app creates files that other apps don't need to access, or
shouldn't access. The system provides the following locations for storing such
*app-specific* files:

- **Internal storage directories:** These directories include both a dedicated
  location for storing persistent files, and another location for storing
  cache data. The system prevents other apps from accessing these locations, and
  on Android 10 (API level 29) and higher, these locations are encrypted. These
  characteristics make these locations a good place to store sensitive data that
  only your app itself can access.

- **External storage directories:** These directories include both a dedicated
  location for storing persistent files, and another location for storing
  cache data. Although it's possible for another app to access these directories
  if that app has the proper permissions, the files stored in these directories
  are meant for use only by your app. If you specifically intend to create files
  that other apps should be able to access, your app should store these files in
  the [shared storage](https://developer.android.com/training/data-storage/shared) part of external storage
  instead.

When the user uninstalls your app, the files saved in app-specific storage are
removed. Because of this behavior, you shouldn't use this storage to save
anything that the user expects to persist independently of your app. For
example, if your app allows users to capture photos, the user would expect that
they can access those photos even after they uninstall your app. So you should
instead use shared storage to save those types of files to the appropriate
[media collection](https://developer.android.com/training/data-storage/shared/media).

The following sections describe how to store and access files within
app-specific directories.

## Access from internal storage

For each app, the system provides directories within internal storage where an
app can organize its files. One directory is designed for [your app's
persistent files](https://developer.android.com/training/data-storage/app-specific#internal-access-files), and another contains [your app's
cached files](https://developer.android.com/training/data-storage/app-specific#internal-create-cache). Your app doesn't require any system
permissions to read and write to files in these directories.

Other apps cannot access files stored within internal storage. This makes
internal storage a good place for app data that other apps shouldn't access.

Keep in mind, however, that these directories tend to be small. Before writing
app-specific files to internal storage, your app should [query the free
space](https://developer.android.com/training/data-storage/app-specific#query-free-space) on the device.

### Access persistent files

Your app's ordinary, persistent files reside in a directory that you can
access using the [`filesDir`](https://developer.android.com/reference/android/content/Context#getFilesDir())
property of a context object. The framework provides several methods to help you
access and store files in this directory.

#### Access and store files

You can use the [`File`](https://developer.android.com/reference/java/io/File) API to access and store files.

To help maintain your app's performance, don't open and close the same
file multiple times.

The following code snippet demonstrates how to use the `File` API:  

### Kotlin

```kotlin
val file = File(context.filesDir, filename)
```

### Java

```java
File file = new File(context.getFilesDir(), filename);
```

#### Store a file using a stream

As an alternative to using the `File` API, you can call
[`openFileOutput()`](https://developer.android.com/reference/android/content/Context#openFileOutput(java.lang.String,%20int))
to get a [`FileOutputStream`](https://developer.android.com/reference/java/io/FileOutputStream) that writes
to a file within the `filesDir` directory.

The following code snippet shows how to write some text to a file:  

### Kotlin

```kotlin
val filename = "myfile"
val fileContents = "Hello world!"
context.openFileOutput(filename, Context.MODE_PRIVATE).use {
        it.write(fileContents.toByteArray())
}
```

### Java

```java
String filename = "myfile";
String fileContents = "Hello world!";
try (FileOutputStream fos = context.openFileOutput(filename, Context.MODE_PRIVATE)) {
    fos.write(fileContents.toByteArray());
}
```
| **Caution:** On devices that run Android 7.0 (API level 24) or higher, unless you pass the `Context.MODE_PRIVATE` file mode into `openFileOutput()`, a [`SecurityException`](https://developer.android.com/reference/java/lang/SecurityException) occurs.

To [allow other apps to access files](https://developer.android.com/training/secure-file-sharing) stored in
this directory within internal storage, use a
[`FileProvider`](https://developer.android.com/reference/androidx/core/content/FileProvider) with the
[`FLAG_GRANT_READ_URI_PERMISSION`](https://developer.android.com/reference/android/content/Intent#FLAG_GRANT_READ_URI_PERMISSION)
attribute.

#### Access a file using a stream

To read a file as a stream, use
[`openFileInput()`](https://developer.android.com/reference/android/content/Context#openFileInput(java.lang.String)):  

### Kotlin

```kotlin
context.openFileInput(filename).bufferedReader().useLines { lines ->
    lines.fold("") { some, text ->
        "$some\n$text"
    }
}
```

### Java

```java
FileInputStream fis = context.openFileInput(filename);
InputStreamReader inputStreamReader =
        new InputStreamReader(fis, StandardCharsets.UTF_8);
StringBuilder stringBuilder = new StringBuilder();
try (BufferedReader reader = new BufferedReader(inputStreamReader)) {
    String line = reader.readLine();
    while (line != null) {
        stringBuilder.append(line).append('\n');
        line = reader.readLine();
    }
} catch (IOException e) {
    // Error occurred when opening raw file for reading.
} finally {
    String contents = stringBuilder.toString();
}
```
| **Note:** If you need to access a file as a stream at install time, save the file in your project's `/res/raw` directory. You can open these files with [`openRawResource()`](https://developer.android.com/reference/android/content/res/Resources#openRawResource(int)), passing in the filename prefixed with `R.raw` as the resource ID. This method returns an [`InputStream`](https://developer.android.com/reference/java/io/InputStream) that you can use to read the file. You cannot write to the original file.

#### View list of files

You can get an array containing the names of all files within the `filesDir`
directory by calling
[`fileList()`](https://developer.android.com/reference/android/content/Context#fileList()), as shown in
the following code snippet:  

### Kotlin

```kotlin
var files: Array<String> = context.fileList()
```

### Java

```java
Array<String> files = context.fileList();
```

#### Create nested directories

You can also create nested directories, or open an inner directory, by calling
[`getDir()`](https://developer.android.com/reference/kotlin/android/content/Context#getdir) in Kotlin-based
code or by passing the root directory and a new directory name into a `File`
constructor in Java-based code:  

### Kotlin

```kotlin
context.getDir(dirName, Context.MODE_PRIVATE)
```

### Java

```java
File directory = context.getFilesDir();
File file = new File(directory, filename);
```
| **Note:** [`dataDir`](https://developer.android.com/reference/kotlin/android/content/pm/ApplicationInfo#datadir) is always an ancestor directory of this new directory.

### Create cache files

If you need to store sensitive data only temporarily, you should use the app's
designated cache directory within internal storage to save the data. As is the
case for all app-specific storage, the files stored in this directory are
removed when the user uninstalls your app, although the files in this directory
might be [removed sooner](https://developer.android.com/training/data-storage/app-specific#internal-remove-cache).
| **Note:** This cache directory is designed to store a small amount of your app's sensitive data. To determine how much cache space is currently available for your app, call [`getCacheQuotaBytes()`](https://developer.android.com/reference/android/os/storage/StorageManager#getCacheQuotaBytes(java.util.UUID)).

To create a cached file, call
[`File.createTempFile()`](https://developer.android.com/reference/java/io/File#createTempFile(java.lang.String,%20java.lang.String)):  

### Kotlin

```kotlin
File.createTempFile(filename, null, context.cacheDir)
```

### Java

```java
File.createTempFile(filename, null, context.getCacheDir());
```

Your app accesses a file in this directory using the
[`cacheDir`](https://developer.android.com/reference/android/content/Context#getCacheDir()) property of a
context object and the [`File`](https://developer.android.com/reference/java/io/File) API:  

### Kotlin

```kotlin
val cacheFile = File(context.cacheDir, filename)
```

### Java

```java
File cacheFile = new File(context.getCacheDir(), filename);
```
| **Caution:** When the device is low on internal storage space, Android may delete these cache files to recover space. So check for the existence of your cache files before reading them.

### Remove cache files

Even though Android sometimes deletes cache files on its own, you shouldn't rely
on the system to clean up these files for you. You should always maintain your
app's cache files within internal storage.

To remove a file from the cache directory within internal storage, use one of
the following methods:

- The [`delete()`](https://developer.android.com/reference/java/io/File#delete()) method on a `File` object
  that represents the file:

  ### Kotlin

  ```kotlin
  cacheFile.delete()
  ```

  ### Java

  ```java
  cacheFile.delete();
  ```
- The
  [`deleteFile()`](https://developer.android.com/reference/android/content/Context#deleteFile(java.lang.String))
  method of the app's context, passing in the name of the file:

  ### Kotlin

  ```kotlin
  context.deleteFile(cacheFileName)
  ```

  ### Java

  ```java
  context.deleteFile(cacheFileName);
  ```

## Access from external storage

If internal storage doesn't provide enough space to store app-specific files,
consider using external storage instead. The system provides directories within
external storage where an app can organize files that provide value to the user
only within your app. One directory is designed for [your app's persistent
files](https://developer.android.com/training/data-storage/app-specific#external-access-files), and another contains [your app's cached
files](https://developer.android.com/training/data-storage/app-specific#external-cache-create).

On Android 4.4 (API level 19) or higher, your app doesn't need to request any
storage-related permissions to access app-specific directories within external
storage. The files stored in these directories are removed when your app is
uninstalled.
| **Caution:** The files in these directories aren't guaranteed to be accessible, such as when a removable SD card is taken out of the device. If your app's functionality depends on these files, you should instead store the files within [internal storage](https://developer.android.com/training/data-storage/app-specific#internal).

On devices that run Android 9 (API level 28) or lower, your app can access the
app-specific files that belong to other apps, provided that your app has the
appropriate storage permissions. To give users more control over their files and
to limit file clutter, apps that target Android 10 (API level 29) and higher are given
scoped access into external storage, or [scoped
storage](https://developer.android.com/training/data-storage#scoped-storage), by default. When scoped
storage is enabled, apps cannot access the app-specific directories that belong
to other apps.

### Verify that storage is available

Because external storage resides on a physical volume that the user might be
able to remove, verify that the volume is accessible before trying to read
app-specific data from, or write app-specific data to, external storage.

You can query the volume's state by calling
[`Environment.getExternalStorageState()`](https://developer.android.com/reference/android/os/Environment#getExternalStorageState()).
If the returned state is
[`MEDIA_MOUNTED`](https://developer.android.com/reference/android/os/Environment#MEDIA_MOUNTED), then
you can read and write app-specific files within external storage. If it's
[`MEDIA_MOUNTED_READ_ONLY`](https://developer.android.com/reference/android/os/Environment#MEDIA_MOUNTED_READ_ONLY),
you can only read these files.

For example, the following methods are useful to determine the storage
availability:  

### Kotlin

```kotlin
// Checks if a volume containing external storage is available
// for read and write.
fun isExternalStorageWritable(): Boolean {
    return Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED
}

// Checks if a volume containing external storage is available to at least read.
fun isExternalStorageReadable(): Boolean {
     return Environment.getExternalStorageState() in
        setOf(Environment.MEDIA_MOUNTED, Environment.MEDIA_MOUNTED_READ_ONLY)
}
```

### Java

```java
// Checks if a volume containing external storage is available
// for read and write.
private boolean isExternalStorageWritable() {
    return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
}

// Checks if a volume containing external storage is available to at least read.
private boolean isExternalStorageReadable() {
     return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) ||
            Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED_READ_ONLY);
}
```

On devices without removable external storage, use the following command to
enable a virtual volume for testing your external storage availability logic:  

```
adb shell sm set-virtual-disk true
```

### Select a physical storage location

Sometimes, a device that allocates a partition of its internal memory as
external storage also provides an SD card slot. This means that the device has
multiple physical volumes that could contain external storage, so you need to
select which one to use for your app-specific storage.

To access the different locations, call
[`ContextCompat.getExternalFilesDirs()`](https://developer.android.com/reference/androidx/core/content/ContextCompat#getExternalFilesDirs(android.content.Context,%20java.lang.String)).
As shown in the code snippet, the first element in the returned array is
considered the primary external storage volume. Use this volume unless it's full
or unavailable.  

### Kotlin

```kotlin
val externalStorageVolumes: Array<out File> =
        ContextCompat.getExternalFilesDirs(applicationContext, null)
val primaryExternalStorage = externalStorageVolumes[0]
```

### Java

```java
File[] externalStorageVolumes =
        ContextCompat.getExternalFilesDirs(getApplicationContext(), null);
File primaryExternalStorage = externalStorageVolumes[0];
```
| **Note:** If your app is used on a device that runs Android 4.3 (API level 18) or lower, then the array contains just one element, which represents the primary external storage volume.

### Access persistent files

To access app-specific files from external storage, call
[`getExternalFilesDir()`](https://developer.android.com/reference/android/content/Context#getExternalFilesDir(java.lang.String)).

To help maintain your app's performance, don't open and close the same
file multiple times.

The following code snippet demonstrates how to call `getExternalFilesDir()`:  

### Kotlin

```kotlin
val appSpecificExternalDir = File(context.getExternalFilesDir(null), filename)
```

### Java

```java
File appSpecificExternalDir = new File(context.getExternalFilesDir(null), filename);
```
| **Note:** On Android 11 (API level 30) and higher, apps cannot create their own app-specific directory on external storage.

### Create cache files

To add an app-specific file to the cache within external storage, get a
reference to the
[`externalCacheDir`](https://developer.android.com/reference/android/content/Context#getExternalCacheDir()):  

### Kotlin

```kotlin
val externalCacheFile = File(context.externalCacheDir, filename)
```

### Java

```java
File externalCacheFile = new File(context.getExternalCacheDir(), filename);
```

### Remove cache files

To remove a file from the external cache directory, use the
[`delete()`](https://developer.android.com/reference/java/io/File#delete()) method on a `File` object that
represents the file:  

### Kotlin

```kotlin
externalCacheFile.delete()
```

### Java

```java
externalCacheFile.delete();
```

### Media content

If your app works with media files that provide value to the user only within
your app, it's best to store them in app-specific directories within external
storage, as demonstrated in the following code snippet:  

### Kotlin

```kotlin
fun getAppSpecificAlbumStorageDir(context: Context, albumName: String): File? {
    // Get the pictures directory that's inside the app-specific directory on
    // external storage.
    val file = File(context.getExternalFilesDir(
            Environment.DIRECTORY_PICTURES), albumName)
    if (!file?.mkdirs()) {
        Log.e(LOG_TAG, "Directory not created")
    }
    return file
}
```

### Java

```java
@Nullable
File getAppSpecificAlbumStorageDir(Context context, String albumName) {
    // Get the pictures directory that's inside the app-specific directory on
    // external storage.
    File file = new File(context.getExternalFilesDir(
            Environment.DIRECTORY_PICTURES), albumName);
    if (file == null || !file.mkdirs()) {
        Log.e(LOG_TAG, "Directory not created");
    }
    return file;
}
```

It's important that you use directory names provided by API constants like
[`DIRECTORY_PICTURES`](https://developer.android.com/reference/android/os/Environment#DIRECTORY_PICTURES).
These directory names ensure that the files are treated properly by the system.
If none of the [pre-defined sub-directory
names](https://developer.android.com/reference/android/os/Environment#fields) suit your files, you can
instead pass `null` into `getExternalFilesDir()`. This returns the root
app-specific directory within external storage.

## Query free space

Many users don't have much storage space available on their devices, so your app
should consume space thoughtfully.

If you know ahead of time how much data you're storing, you can find out how
much space the device can provide your app by calling
[`getAllocatableBytes()`](https://developer.android.com/reference/android/os/storage/StorageManager#getAllocatableBytes(java.util.UUID)).
The return value of `getAllocatableBytes()` might be larger than the current
amount of free space on the device. This is because the system has identified
files that it can remove from other apps' cache directories.

If there's enough space to save your app's data, call
[`allocateBytes()`](https://developer.android.com/reference/android/os/storage/StorageManager#allocateBytes(java.io.FileDescriptor,%20long)).
Otherwise, your app can request the user to [remove some
files](https://developer.android.com/training/data-storage/app-specific#user-remove-device-files) from the device or [remove all cache
files](https://developer.android.com/training/data-storage/app-specific#user-remove-all-cache-files) from the device.

The following code snippet shows an example of how your app can query free space
on the device:  

### Kotlin

```kotlin
// App needs 10 MB within internal storage.
const val NUM_BYTES_NEEDED_FOR_MY_APP = 1024 * 1024 * 10L;

val storageManager = applicationContext.getSystemService<StorageManager>()!!
val appSpecificInternalDirUuid: UUID = storageManager.getUuidForPath(filesDir)
val availableBytes: Long =
        storageManager.getAllocatableBytes(appSpecificInternalDirUuid)
if (availableBytes >= NUM_BYTES_NEEDED_FOR_MY_APP) {
    storageManager.allocateBytes(
        appSpecificInternalDirUuid, NUM_BYTES_NEEDED_FOR_MY_APP)
} else {
    val storageIntent = Intent().apply {
        // To request that the user remove all app cache files instead, set
        // "action" to ACTION_CLEAR_APP_CACHE.
        action = ACTION_MANAGE_STORAGE
    }
}
```

### Java

```java
// App needs 10 MB within internal storage.
private static final long NUM_BYTES_NEEDED_FOR_MY_APP = 1024 * 1024 * 10L;

StorageManager storageManager =
        getApplicationContext().getSystemService(StorageManager.class);
UUID appSpecificInternalDirUuid = storageManager.getUuidForPath(getFilesDir());
long availableBytes =
        storageManager.getAllocatableBytes(appSpecificInternalDirUuid);
if (availableBytes >= NUM_BYTES_NEEDED_FOR_MY_APP) {
    storageManager.allocateBytes(
            appSpecificInternalDirUuid, NUM_BYTES_NEEDED_FOR_MY_APP);
} else {
    // To request that the user remove all app cache files instead, set
    // "action" to ACTION_CLEAR_APP_CACHE.
    Intent storageIntent = new Intent();
    storageIntent.setAction(ACTION_MANAGE_STORAGE);
}
```
| **Note:** You aren't required to check the amount of available space before you save your file. You can instead try writing the file right away, then catch an [`IOException`](https://developer.android.com/reference/java/io/IOException) if one occurs. You may need to do this if you don't know exactly how much space you need. For example, if you change the file's encoding before you save it by converting a PNG image to JPEG, you don't know the file's size beforehand.

### Create a storage management activity

Your app can declare and create a custom activity that, when launched, allows
the user to manage the data that your app has stored on the user's device. You
declare this custom "manage space" activity using the
[`android:manageSpaceActivity`](https://developer.android.com/guide/topics/manifest/application-element#space)
attribute in the manifest file. File manager apps can [invoke this
activity](https://developer.android.com/training/data-storage/manage-all-files#invoke-storage-management-activity)
even when your app doesn't export the activity; that is, when your activity sets
[`android:exported`](https://developer.android.com/guide/topics/manifest/activity-element#exported) to
`false`.

### Ask user to remove some device files

To request that the user choose files on the device to remove, invoke an intent
that includes the
[`ACTION_MANAGE_STORAGE`](https://developer.android.com/reference/android/os/storage/StorageManager#ACTION_MANAGE_STORAGE)
action. This intent displays a prompt to the user. If desired, this prompt can
show the amount of free space available on the device. To show this
user-friendly information, use the result of the following calculation:  

```
StorageStatsManager.getFreeBytes() / StorageStatsManager.getTotalBytes()
```

### Ask user to remove all cache files

Alternatively, you can request that the user clear the cache files from **all**
apps on the device. To do so, invoke an intent that includes the
[`ACTION_CLEAR_APP_CACHE`](https://developer.android.com/reference/android/os/storage/StorageManager#ACTION_CLEAR_APP_CACHE)
intent action.
| **Caution:** The `ACTION_CLEAR_APP_CACHE` intent action can substantially affect device battery life and might remove a large number of files from the device.

## Additional resources

For more information about saving files to the device's storage, consult the
following resources.

### Videos

- [Preparing for Scoped Storage (Android Dev Summit
  '19)](https://www.youtube.com/watch?v=UnJ3amzJM94)