| page.title=Storage Options |
| page.tags=database,sharedpreferences,sdcard |
| @jd:body |
| |
| |
| <div id="qv-wrapper"> |
| <div id="qv"> |
| |
| <h2>Storage quickview</h2> |
| <ul> |
| <li>Use Shared Preferences for primitive data</li> |
| <li>Use internal device storage for private data</li> |
| <li>Use external storage for large data sets that are not private</li> |
| <li>Use SQLite databases for structured storage</li> |
| </ul> |
| |
| <h2>In this document</h2> |
| <ol> |
| <li><a href="#pref">Using Shared Preferences</a></li> |
| <li><a href="#filesInternal">Using the Internal Storage</a></li> |
| <li><a href="#filesExternal">Using the External Storage</a></li> |
| <li><a href="#db">Using Databases</a></li> |
| <li><a href="#netw">Using a Network Connection</a></li> |
| </ol> |
| |
| <h2>See also</h2> |
| <ol> |
| <li><a href="#pref">Content Providers and Content Resolvers</a></li> |
| </ol> |
| |
| </div> |
| </div> |
| |
| <p>Android provides several options for you to save persistent application data. The solution you |
| choose depends on your specific needs, such as whether the data should be private to your |
| application or accessible to other applications (and the user) and how much space your data |
| requires. |
| </p> |
| |
| <p>Your data storage options are the following:</p> |
| |
| <dl> |
| <dt><a href="#pref">Shared Preferences</a></dt> |
| <dd>Store private primitive data in key-value pairs.</dd> |
| <dt><a href="#filesInternal">Internal Storage</a></dt> |
| <dd>Store private data on the device memory.</dd> |
| <dt><a href="#filesExternal">External Storage</a></dt> |
| <dd>Store public data on the shared external storage.</dd> |
| <dt><a href="#db">SQLite Databases</a></dt> |
| <dd>Store structured data in a private database.</dd> |
| <dt><a href="#netw">Network Connection</a></dt> |
| <dd>Store data on the web with your own network server.</dd> |
| </dl> |
| |
| <p>Android provides a way for you to expose even your private data to other applications |
| — with a <a href="{@docRoot}guide/topics/providers/content-providers.html">content |
| provider</a>. A content provider is an optional component that exposes read/write access to |
| your application data, subject to whatever restrictions you want to impose. For more information |
| about using content providers, see the |
| <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a> |
| documentation. |
| </p> |
| |
| |
| |
| |
| <h2 id="pref">Using Shared Preferences</h2> |
| |
| <p>The {@link android.content.SharedPreferences} class provides a general framework that allows you |
| to save and retrieve persistent key-value pairs of primitive data types. You can use {@link |
| android.content.SharedPreferences} to save any primitive data: booleans, floats, ints, longs, and |
| strings. This data will persist across user sessions (even if your application is killed).</p> |
| |
| <div class="sidebox-wrapper"> |
| <div class="sidebox"> |
| <h3>User Preferences</h3> |
| <p>Shared preferences are not strictly for saving "user preferences," such as what ringtone a |
| user has chosen. If you're interested in creating user preferences for your application, see {@link |
| android.preference.PreferenceActivity}, which provides an Activity framework for you to create |
| user preferences, which will be automatically persisted (using shared preferences).</p> |
| </div> |
| </div> |
| |
| <p>To get a {@link android.content.SharedPreferences} object for your application, use one of |
| two methods:</p> |
| <ul> |
| <li>{@link android.content.Context#getSharedPreferences(String,int) |
| getSharedPreferences()} - Use this if you need multiple preferences files identified by name, |
| which you specify with the first parameter.</li> |
| <li>{@link android.app.Activity#getPreferences(int) getPreferences()} - Use this if you need |
| only one preferences file for your Activity. Because this will be the only preferences file |
| for your Activity, you don't supply a name.</li> |
| </ul> |
| |
| <p>To write values:</p> |
| <ol> |
| <li>Call {@link android.content.SharedPreferences#edit()} to get a {@link |
| android.content.SharedPreferences.Editor}.</li> |
| <li>Add values with methods such as {@link |
| android.content.SharedPreferences.Editor#putBoolean(String,boolean) putBoolean()} and {@link |
| android.content.SharedPreferences.Editor#putString(String,String) putString()}.</li> |
| <li>Commit the new values with {@link android.content.SharedPreferences.Editor#commit()}</li> |
| </ol> |
| |
| <p>To read values, use {@link android.content.SharedPreferences} methods such as {@link |
| android.content.SharedPreferences#getBoolean(String,boolean) getBoolean()} and {@link |
| android.content.SharedPreferences#getString(String,String) getString()}.</p> |
| |
| <p> |
| Here is an example that saves a preference for silent keypress mode in a |
| calculator: |
| </p> |
| |
| <pre> |
| public class Calc extends Activity { |
| public static final String PREFS_NAME = "MyPrefsFile"; |
| |
| @Override |
| protected void onCreate(Bundle state){ |
| super.onCreate(state); |
| . . . |
| |
| // Restore preferences |
| SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0); |
| boolean silent = settings.getBoolean("silentMode", false); |
| setSilent(silent); |
| } |
| |
| @Override |
| protected void onStop(){ |
| super.onStop(); |
| |
| // We need an Editor object to make preference changes. |
| // All objects are from android.context.Context |
| SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0); |
| SharedPreferences.Editor editor = settings.edit(); |
| editor.putBoolean("silentMode", mSilentMode); |
| |
| // Commit the edits! |
| editor.commit(); |
| } |
| } |
| </pre> |
| |
| |
| |
| |
| <a name="files"></a> |
| <h2 id="filesInternal">Using the Internal Storage</h2> |
| |
| <p>You can save files directly on the device's internal storage. By default, files saved |
| to the internal storage are private to your application and other applications cannot access |
| them (nor can the user). When the user uninstalls your application, these files are removed.</p> |
| |
| <p>To create and write a private file to the internal storage:</p> |
| |
| <ol> |
| <li>Call {@link android.content.Context#openFileOutput(String,int) openFileOutput()} with the |
| name of the file and the operating mode. This returns a {@link java.io.FileOutputStream}.</li> |
| <li>Write to the file with {@link java.io.FileOutputStream#write(byte[]) write()}.</li> |
| <li>Close the stream with {@link java.io.FileOutputStream#close()}.</li> |
| </ol> |
| |
| <p>For example:</p> |
| |
| <pre> |
| String FILENAME = "hello_file"; |
| String string = "hello world!"; |
| |
| FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE); |
| fos.write(string.getBytes()); |
| fos.close(); |
| </pre> |
| |
| <p>{@link android.content.Context#MODE_PRIVATE} will create the file (or replace a file of |
| the same name) and make it private to your application. Other modes available are: {@link |
| android.content.Context#MODE_APPEND}, {@link |
| android.content.Context#MODE_WORLD_READABLE}, and {@link |
| android.content.Context#MODE_WORLD_WRITEABLE}.</p> |
| |
| <p class="note"><strong>Note:</strong> The constants {@link |
| android.content.Context#MODE_WORLD_READABLE} and {@link |
| android.content.Context#MODE_WORLD_WRITEABLE} have been deprecated since API level 17. |
| Starting from Android N their use will result in a {@link java.lang.SecurityException} |
| to be thrown. |
| This means that apps targeting Android N and higher |
| cannot share private files by name, and attempts to share a "file://" URI will result in a |
| {@link android.os.FileUriExposedException} to be thrown. If your app needs to share private |
| files with other apps, it may use a {@link android.support.v4.content.FileProvider} with |
| the {@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION}. |
| See also <a |
| href="{@docRoot}training/secure-file-sharing/index.html">Sharing Files</a>. |
| </p> |
| |
| <p>To read a file from internal storage:</p> |
| |
| <ol> |
| <li>Call {@link android.content.Context#openFileInput openFileInput()} and pass it the |
| name of the file to read. This returns a {@link java.io.FileInputStream}.</li> |
| <li>Read bytes from the file with {@link java.io.FileInputStream#read(byte[],int,int) |
| read()}.</li> |
| <li>Then close the stream with {@link java.io.FileInputStream#close()}.</li> |
| </ol> |
| |
| <p class="note"><strong>Tip:</strong> If you want to save a static file in your application at |
| compile time, save the file in your project <code>res/raw/</code> directory. You can open it with |
| {@link android.content.res.Resources#openRawResource(int) openRawResource()}, passing the |
| <code>R.raw.<em><filename></em></code> resource ID. This method returns an {@link java.io.InputStream} |
| that you can use to read the file (but you cannot write to the original file). |
| </p> |
| |
| |
| <h3 id="InternalCache">Saving cache files</h3> |
| |
| <p>If you'd like to cache some data, rather than store it persistently, you should use {@link |
| android.content.Context#getCacheDir()} to open a {@link |
| java.io.File} that represents the internal directory where your application should save |
| temporary cache files.</p> |
| |
| <p>When the device is |
| low on internal storage space, Android may delete these cache files to recover space. However, you |
| should not rely on the system to clean up these files for you. You should always maintain the cache |
| files yourself and stay within a reasonable limit of space consumed, such as 1MB. When the user |
| uninstalls your application, these files are removed.</p> |
| |
| |
| <h3 id="InternalMethods">Other useful methods</h3> |
| |
| <dl> |
| <dt>{@link android.content.Context#getFilesDir()}</dt> |
| <dd>Gets the absolute path to the filesystem directory where your internal files are saved.</dd> |
| <dt>{@link android.content.Context#getDir(String,int) getDir()}</dt> |
| <dd>Creates (or opens an existing) directory within your internal storage space.</dd> |
| <dt>{@link android.content.Context#deleteFile(String) deleteFile()}</dt> |
| <dd>Deletes a file saved on the internal storage.</dd> |
| <dt>{@link android.content.Context#fileList()}</dt> |
| <dd>Returns an array of files currently saved by your application.</dd> |
| </dl> |
| |
| |
| |
| |
| <h2 id="filesExternal">Using the External Storage</h2> |
| |
| <p>Every Android-compatible device supports a shared "external storage" that you can use to |
| save files. This can be a removable storage media (such as an SD card) or an internal |
| (non-removable) storage. Files saved to the external storage are world-readable and can |
| be modified by the user when they enable USB mass storage to transfer files on a computer.</p> |
| |
| <p class="caution"><strong>Caution:</strong> External storage can become unavailable if the user mounts the |
| external storage on a computer or removes the media, and there's no security enforced upon files you |
| save to the external storage. All applications can read and write files placed on the external |
| storage and the user can remove them.</p> |
| |
| <h3 id="ExternalPermissions">Getting access to external storage</h3> |
| |
| <p>In order to read or write files on the external storage, your app must acquire the |
| {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} |
| or {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} system |
| permissions. For example:</p> |
| <pre> |
| <manifest ...> |
| <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> |
| ... |
| </manifest> |
| </pre> |
| |
| <p>If you need to both read and write files, then you need to request only the |
| {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} permission, because it |
| implicitly requires read access as well.</p> |
| |
| <p class="note"><strong>Note:</strong> Beginning with Android 4.4, these permissions are not |
| required if you're reading or writing only files that are private to your app. For more |
| information, see the section below about |
| <a href="#AccessingExtFiles">saving files that are app-private</a>.</p> |
| |
| |
| |
| <h3 id="MediaAvail">Checking media availability</h3> |
| |
| <p>Before you do any work with the external storage, you should always call {@link |
| android.os.Environment#getExternalStorageState()} to check whether the media is available. The |
| media might be mounted to a computer, missing, read-only, or in some other state. For example, |
| here are a couple methods you can use to check the availability:</p> |
| |
| <pre> |
| /* Checks if external storage is available for read and write */ |
| public boolean isExternalStorageWritable() { |
| String state = Environment.getExternalStorageState(); |
| if (Environment.MEDIA_MOUNTED.equals(state)) { |
| return true; |
| } |
| return false; |
| } |
| |
| /* Checks if external storage is available to at least read */ |
| public boolean isExternalStorageReadable() { |
| String state = Environment.getExternalStorageState(); |
| if (Environment.MEDIA_MOUNTED.equals(state) || |
| Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { |
| return true; |
| } |
| return false; |
| } |
| </pre> |
| |
| <p>The {@link android.os.Environment#getExternalStorageState()} method returns other states that you |
| might want to check, such as whether the media is being shared (connected to a computer), is missing |
| entirely, has been removed badly, etc. You can use these to notify the user with more information |
| when your application needs to access the media.</p> |
| |
| |
| <h3 id="SavingSharedFiles">Saving files that can be shared with other apps</h3> |
| |
| <div class="sidebox-wrapper" > |
| <div class="sidebox"> |
| |
| <h4>Hiding your files from the Media Scanner</h4> |
| |
| <p>Include an empty file named {@code .nomedia} in your external files directory (note the dot |
| prefix in the filename). This prevents media scanner from reading your media |
| files and providing them to other apps through the {@link android.provider.MediaStore} |
| content provider. However, if your files are truly private to your app, you should |
| <a href="#AccessingExtFiles">save them in an app-private directory</a>.</p> |
| |
| </div> |
| </div> |
| |
| <p>Generally, new files that the user may acquire through your app should be saved to a "public" |
| location on the device where other apps can access them and the user can easily copy them from the |
| device. When doing so, you should use to one of the shared public directories, such as {@code |
| Music/}, {@code Pictures/}, and {@code Ringtones/}.</p> |
| |
| <p>To get a {@link java.io.File} representing the appropriate public directory, call {@link |
| android.os.Environment#getExternalStoragePublicDirectory(String) |
| getExternalStoragePublicDirectory()}, passing it the type of directory you want, such as |
| {@link android.os.Environment#DIRECTORY_MUSIC}, {@link android.os.Environment#DIRECTORY_PICTURES}, |
| {@link android.os.Environment#DIRECTORY_RINGTONES}, or others. By saving your files to the |
| corresponding media-type directory, |
| the system's media scanner can properly categorize your files in the system (for |
| instance, ringtones appear in system settings as ringtones, not as music).</p> |
| |
| |
| <p>For example, here's a method that creates a directory for a new photo album in |
| the public pictures directory:</p> |
| |
| <pre> |
| public File getAlbumStorageDir(String albumName) { |
| // Get the directory for the user's public pictures directory. |
| File file = new File(Environment.getExternalStoragePublicDirectory( |
| Environment.DIRECTORY_PICTURES), albumName); |
| if (!file.mkdirs()) { |
| Log.e(LOG_TAG, "Directory not created"); |
| } |
| return file; |
| } |
| </pre> |
| |
| |
| |
| <h3 id="AccessingExtFiles">Saving files that are app-private</h3> |
| |
| <p>If you are handling files that are not intended for other apps to use |
| (such as graphic textures or sound effects used by only your app), you should use |
| a private storage directory on the external storage by calling {@link |
| android.content.Context#getExternalFilesDir(String) getExternalFilesDir()}. |
| This method also takes a <code>type</code> argument to specify the type of subdirectory |
| (such as {@link android.os.Environment#DIRECTORY_MOVIES}). If you don't need a specific |
| media directory, pass <code>null</code> to receive |
| the root directory of your app's private directory.</p> |
| |
| <p>Beginning with Android 4.4, reading or writing files in your app's private |
| directories does not require the {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} |
| or {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} |
| permissions. So you can declare the permission should be requested only on the lower versions |
| of Android by adding the <a |
| href="{@docRoot}guide/topics/manifest/uses-permission-element.html#maxSdk">{@code maxSdkVersion}</a> |
| attribute:</p> |
| <pre> |
| <manifest ...> |
| <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" |
| android:maxSdkVersion="18" /> |
| ... |
| </manifest> |
| </pre> |
| |
| <p class="note"><strong>Note:</strong> |
| When the user uninstalls your application, this directory and all its contents are deleted. |
| Also, the system media scanner does not read files in these directories, so they are not accessible |
| from the {@link android.provider.MediaStore} content provider. As such, you <b>should not |
| use these directories</b> for media that ultimately belongs to the user, such as photos |
| captured or edited with your app, or music the user has purchased with your app—those |
| files should be <a href="#SavingSharedFiles">saved in the public directories</a>.</p> |
| |
| <p>Sometimes, a device that has allocated a partition of the |
| internal memory for use as the external storage may also offer an SD card slot. |
| When such a device is running Android 4.3 and lower, the {@link |
| android.content.Context#getExternalFilesDir(String) getExternalFilesDir()} method provides |
| access to only the internal partition and your app cannot read or write to the SD card. |
| Beginning with Android 4.4, however, you can access both locations by calling |
| {@link android.content.Context#getExternalFilesDirs getExternalFilesDirs()}, |
| which returns a {@link |
| java.io.File} array with entries each location. The first entry in the array is considered |
| the primary external storage and you should use that location unless it's full or |
| unavailable. If you'd like to access both possible locations while also supporting Android |
| 4.3 and lower, use the <a href="{@docRoot}tools/support-library/index.html">support library's</a> |
| static method, {@link android.support.v4.content.ContextCompat#getExternalFilesDirs |
| ContextCompat.getExternalFilesDirs()}. This also returns a {@link |
| java.io.File} array, but always includes only one entry on Android 4.3 and lower.</p> |
| |
| <p class="caution"><strong>Caution</strong> Although the directories provided by {@link |
| android.content.Context#getExternalFilesDir(String) getExternalFilesDir()} and {@link |
| android.content.Context#getExternalFilesDirs getExternalFilesDirs()} are not accessible by the |
| {@link android.provider.MediaStore} content provider, other apps with the {@link |
| android.Manifest.permission#READ_EXTERNAL_STORAGE} permission can access all files on the external |
| storage, including these. If you need to completely restrict access for your files, you should |
| instead write your files to the <a href="#filesInternal">internal storage</a>.</p> |
| |
| |
| |
| |
| |
| <h3 id="ExternalCache">Saving cache files</h3> |
| |
| <p>To open a {@link java.io.File} that represents the |
| external storage directory where you should save cache files, call {@link |
| android.content.Context#getExternalCacheDir()}. If the user uninstalls your |
| application, these files will be automatically deleted.</p> |
| |
| <p>Similar to {@link android.support.v4.content.ContextCompat#getExternalFilesDirs |
| ContextCompat.getExternalFilesDirs()}, mentioned above, you can also access a cache directory on |
| a secondary external storage (if available) by calling |
| {@link android.support.v4.content.ContextCompat#getExternalCacheDirs |
| ContextCompat.getExternalCacheDirs()}.</p> |
| |
| <p class="note"><strong>Tip:</strong> |
| To preserve file space and maintain your app's performance, |
| it's important that you carefully manage your cache files and remove those that aren't |
| needed anymore throughout your app's lifecycle.</p> |
| |
| |
| |
| |
| <h2 id="db">Using Databases</h2> |
| |
| <p>Android provides full support for <a href="http://www.sqlite.org/">SQLite</a> databases. |
| Any databases you create will be accessible by name to any |
| class in the application, but not outside the application.</p> |
| |
| <p>The recommended method to create a new SQLite database is to create a subclass of {@link |
| android.database.sqlite.SQLiteOpenHelper} and override the {@link |
| android.database.sqlite.SQLiteOpenHelper#onCreate(SQLiteDatabase) onCreate()} method, in which you |
| can execute a SQLite command to create tables in the database. For example:</p> |
| |
| <pre> |
| public class DictionaryOpenHelper extends SQLiteOpenHelper { |
| |
| private static final int DATABASE_VERSION = 2; |
| private static final String DICTIONARY_TABLE_NAME = "dictionary"; |
| private static final String DICTIONARY_TABLE_CREATE = |
| "CREATE TABLE " + DICTIONARY_TABLE_NAME + " (" + |
| KEY_WORD + " TEXT, " + |
| KEY_DEFINITION + " TEXT);"; |
| |
| DictionaryOpenHelper(Context context) { |
| super(context, DATABASE_NAME, null, DATABASE_VERSION); |
| } |
| |
| @Override |
| public void onCreate(SQLiteDatabase db) { |
| db.execSQL(DICTIONARY_TABLE_CREATE); |
| } |
| } |
| </pre> |
| |
| <p>You can then get an instance of your {@link android.database.sqlite.SQLiteOpenHelper} |
| implementation using the constructor you've defined. To write to and read from the database, call |
| {@link android.database.sqlite.SQLiteOpenHelper#getWritableDatabase()} and {@link |
| android.database.sqlite.SQLiteOpenHelper#getReadableDatabase()}, respectively. These both return a |
| {@link android.database.sqlite.SQLiteDatabase} object that represents the database and |
| provides methods for SQLite operations.</p> |
| |
| <div class="sidebox-wrapper"> |
| <div class="sidebox"> |
| <p>Android does not impose any limitations beyond the standard SQLite concepts. We do recommend |
| including an autoincrement value key field that can be used as a unique ID to |
| quickly find a record. This is not required for private data, but if you |
| implement a <a href="{@docRoot}guide/topics/providers/content-providers.html">content provider</a>, |
| you must include a unique ID using the {@link android.provider.BaseColumns#_ID BaseColumns._ID} |
| constant. |
| </p> |
| </div> |
| </div> |
| |
| <p>You can execute SQLite queries using the {@link android.database.sqlite.SQLiteDatabase} |
| {@link |
| android.database.sqlite.SQLiteDatabase#query(boolean,String,String[],String,String[],String,String,String,String) |
| query()} methods, which accept various query parameters, such as the table to query, |
| the projection, selection, columns, grouping, and others. For complex queries, such as |
| those that require column aliases, you should use |
| {@link android.database.sqlite.SQLiteQueryBuilder}, which provides |
| several convienent methods for building queries.</p> |
| |
| <p>Every SQLite query will return a {@link android.database.Cursor} that points to all the rows |
| found by the query. The {@link android.database.Cursor} is always the mechanism with which |
| you can navigate results from a database query and read rows and columns.</p> |
| |
| <p>For sample apps that demonstrate how to use SQLite databases in Android, see the |
| <a href="{@docRoot}resources/samples/NotePad/index.html">Note Pad</a> and |
| <a href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable Dictionary</a> |
| applications.</p> |
| |
| |
| <h3 id="dbDebugging">Database debugging</h3> |
| |
| <p>The Android SDK includes a {@code sqlite3} database tool that allows you to browse |
| table contents, run SQL commands, and perform other useful functions on SQLite |
| databases. See <a href="{@docRoot}tools/help/adb.html#sqlite">Examining sqlite3 |
| databases from a remote shell</a> to learn how to run this tool. |
| </p> |
| |
| |
| |
| |
| |
| <h2 id="netw">Using a Network Connection</h2> |
| |
| <!-- TODO MAKE THIS USEFUL!! --> |
| |
| <p>You can use the network (when it's available) to store and retrieve data on your own web-based |
| services. To do network operations, use classes in the following packages:</p> |
| |
| <ul class="no-style"> |
| <li><code>{@link java.net java.net.*}</code></li> |
| <li><code>{@link android.net android.net.*}</code></li> |
| </ul> |