If you can, use SharedPreferences or a database to save it. If you have to, you can also save it in files.
The Ins and the Outs: Choose your storage
Android devices have two storage areas, internal and external.
The inside story: Internal storage
Internal storage is always available and secure by default. It’s usually used to store an apps data.
Files saved here are deleted when the app is uninstalled.
No permission is needed for reading or writing here.
The great outdoors: External storage
External storage can be part of the device’s storage area or be on a separate removable card. Data stored here is not secure and may not always be available.
By default, these files will not be deleted when the app is removed.
Permission is needed to write to this area. Apps may also need reading permission.
Here today, gone tomorrow: Save temporary files in the cache
You can also save application data in temporary cache files. This uses valuable memory so try to keep your file size below 1MB and delete any unused files.
There is both an internal and external cache. Files saved in either of these will be deleted when the app is uninstalled.
Note that internal cache files may be erased at any time if the system needs extra memory.
Put it in your pocket: Saving files in the internal storage area
Use getFilesDir() to get a directory in the internal storage where your app’s data will be saved.
You can also use openFileOutput() to get a FileOutputStream that will write the file to the app’s internal directory.
Put it in your wallet: Saving files in the external storage area
Always check if the external storage is available - removing the SD card or connecting the device to a PC will make it unavailable.
There are two categories of external files, Public and Private.
In both cases use directory names provided by the Environment class constants, such as DIRECTORY_MUSIC and DIRECTORY_PICTURES.
Come one, come all: Public files
These files are accessible to other apps and remain when the app is uninstalled. Use getExternalStoragePublicDirectory() to get a File object.
No trespassing: Private files
This is where you store files used by your app. They are deleted when the app is uninstalled. Use getExternalFilesDir() to get a File object. This creates a directory inside a directory associated with your app.
How big is big?
You can check how much space is available for storing your data by using these methods:
- getFreeSpace() – tells you how much available free space there is
- getTotalSpace() – gives you the total space in the storage area – used and unused
Check for available space before trying to save a file or alternatively, try and write the file and catch an exception if there is not enough space.
Get some space
Free up space by deleting all unnecessary files.
Tutorial
This tutorial shows you how to save files in the external public directory, the internal storage area and the internal cache.
The tutorial app has two Activities. The main Activity displays three buttons. Pressing either of the buttons saves a file and displays a button on success. Pressing this button starts the second Activity which reads the appropriate file and displays either an image or text.
Three boolean objects saved as SharedPreferences determines whether the show buttons are displayed.
Going public: Saving a file in the external public directory
Here’s the code for saving an image in the external public directory.
The original image is saved as a drawable resource. It’s decoded and presented as a Bitmap to be saved in the device’s public directory, Pictures. Here’s a screenshot of the saved file as listed in the device’s File Explorer:
Note the following:
- getExternalStorageState() – checks whether the external storage is available
- getExternalStoragePublicDirectory() – gets the external storage public directory
- Environment.Directory_Pictures – a public directory specifically for saving pictures
- File – constructs a file in the directory, pictureFolder with the name represented by the filename parameter
- FileOutputStream – an output stream that writes bytes to the file, filePicture
- compress – compresses the image and then writes it to the file. I’m using the jpg format and compressing the file to 80% its original quality. The last parameter, out is the stream to which I am writing the file
- close() – closes the stream and frees up any resources
- the try/catch statement – gracefully handles any exceptions thrown if there is a problem writing to the file
Shh, keep it private: Saving a file to the internal storage area
Here’s how to save a text file in the internal storage area. The text I am using is the string, stringToSave.
The file will be saved in this location on the device: data/data/
Here’s the code. Note the following:
- FileOutPutStream - an output stream that writes bytes to the file, aFileName. I could also have used getFilesDir()to get a directory in the internal storage where the app’s data will be saved – see the project files for the code
- openFileOutPut - opens a private file for this application
- MODE_PRIVATE - default file creation mode. The file is only accessible by the app creating it
- getBytes() – gets an array of bytes representing the characters of the string that we want to save, aStringToSave
- close() – closes the stream and frees up resources
- the try/catch statement – gracefully handles any exceptions thrown if there is a problem writing to the file
Nothing lasts forever: Saving a file in the internal cache
Here’s how to save an image in the internal cache.
The original image is saved as a drawable resource. It’s decoded and presented as a Bitmap to be saved in the device’s internal cache.
Note the following:
- getCacheDir().getPath() – gets the path to the app’s cache directory
- File – create a File using the path passed as a parameter
- File.separator – inserts a file separator (/) between the path and file name
- FileOutPutStream - an output stream that writes bytes to the file, aFileName
- compress – compresses the image and then writes it to the file. I’m using the jpg format and compressing the file to 80% its original quality. The last parameter, out is the stream to which I am writing the file
- the try/catch statement – gracefully handles any exceptions thrown if there is a problem writing to the file
Pressing the buttons: Handling the button presses
The Activity implements an OnClickListener to deal with the button presses. The following code executes when any of the buttons are pressed:
Pressing buttons 4, 5 and 6 executes the appropriate code to save a file. On success, an appropriate button is displayed at the bottom of the screen. Pressing this starts the DisplayImage Activity
The DisplayImage Activity reads the relevant file and displays either an image or text.
You may also be interested in our Firebase tutorial, Using a Firebase Realtime Database in your app
Check out the second part of this series of articles where I show you how to read the files from Android's file system. Part 2: Making a withdrawal: Reading the files.
The tutorial application was created using Android Studio. You can download the project files here