Android: Data Storage F. Mallet Frederic.Mallet@unice.fr Université Nice Sophia Antipolis
Outline Data Storage Shared Preferences Internal Storage External Storage SQLite Databases Network Connection F. Mallet http://developer.android.com/guide/topics/data/data-storage.html 2
Shared Preferences SharedPreferences gives a framework To save and retrieve persistent key-value pairs Only for primitive data types: boolean, floats, ints, longs, strings Will persist across sessions even if the application is killed API getpreferences(int mode) Only one preference file for one activity MODE_PRIVATE: all the applications sharing the same user ID MODE_WORLD_READABLE: deprecated in API 17 => ContentProvider MODE_WORLD_WRITABLE: deprecated in API 17 => ContentProvider getsharedpreferences(string name, int mode) Multiple preferences files for one activity or shared among activities F. Mallet 3 http://developer.android.com/reference/android/content/sharedpreferences.html
Shared Preferences SharedPreferences gives a framework To save and retrieve persistent key-value pairs Only for primitive data types: boolean, floats, ints, longs, strings Will persist across sessions even if the application is killed API getpreferences(int mode) Calls getsharedpreferences( application name, mode); getsharedpreferences(string name, int mode) Multiple preferences files for one activity or shared among activities If it does not exist, will be created F. Mallet 4
Reading values from a key boolean contains(string key) Map<String,?> getall() boolean getboolean(string key, boolean defvalue) float getfloat(string key, float defvalue) int getint(string key, int defvalue) long getlong(string key, long defvalue) String getstring(string key, String defvalue) Writing values SharedPreferences.Editor edit() Atomic changes to be committed SharedPreferences F. Mallet 5
Atomic changes to preferences void apply() boolean commit() SharedPreferences.Editor SharedPreferences.Editor clear() SharedPreferences.Editor remove(string key) SharedPreferences.Editor putboolean(string key, boolean value) SharedPreferences.Editor putfloat(string key, float value) SharedPreferences.Editor putint(string key, int value) SharedPreferences.Editor putlong(string key, long value) SharedPreferences.Editor putstring(string key, String value) F. Mallet 6
Internal Storage Open or create a file private to an application Removed when the application is uninstalled Class android.content.context FileOutputStream openfileoutput (String name, int mode) MODE_PRIVATE (Default) MODE_APPEND MODE_WORLD_READABLE, MODE_WORLD_WRITEABLE FileInputStream openfileinput (String name) String[] filelist () boolean deletefile (String name) File getfilesdir () File getdir (String name, int mode) (creates if does not exist) File getcachedir () F. Mallet 7
Same as standard JDK Use BufferedInputStream with FileInputStream Use FileReader for flows of characters Use BufferedOutputStream with FileOutputStream Use FileWriter for flows of characters Use File: (mkdirs(), exists(), ) Do not forget to close the streams Example: String FILENAME = "hello_file"; String string = "hello world!"; FileOutputStream fos = openfileoutput(filename, Context.MODE_PRIVATE); fos.write(string.getbytes()); fos.close(); Package java.io F. Mallet 8
External Storage Removable storage media (SD card) or internal storage Data are world_readable Accessible through USB mass storage Need permissions From Android 4.4 (API 18) Permissions are not required to access private directories Read only <manifest...> <uses-permission android:name="android.permission.read_external_storage" />... </manifest> Write (and read) <manifest...> <uses-permission android:name="android.permission.write_external_storage" />... </manifest> F. Mallet 9
Checking media availability Check Read Access public boolean isexternalstoragereadable() { String state = Environment.getExternalStorageState(); return (Environment.MEDIA_MOUNTED.equals(state) Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)); Check Write Access public boolean isexternalstoragewritable() { String state = Environment.getExternalStorageState(); return (Environment.MEDIA_MOUNTED.equals(state); F. Mallet 10
class android.content.environment Public shared directory: File getexternalstoragepublicdirectory (String type) Private external directory: File getexternalfilesdir (String type) Types External Directories String DIRECTORY_ALARMS Standard directory for any audio files that should be in the list of alarms that the user can select (not as regular music). String DIRECTORY_DCIM Pictures and videos when mounting the device as a camera. String DIRECTORY_DOCUMENTS Documents created by the user. String DIRECTORY_DOWNLOADS files downloaded by the user. F. Mallet 11
More Types External Directories String DIRECTORY_MOVIES movies available to the user. String DIRECTORY_MUSIC Any audio files in the regular list of music for the user. String DIRECTORY_NOTIFICATIONS Any audio files in the list of notifications that the user can select (not as regular music). String DIRECTORY_PICTURES Pictures available to the user. String DIRECTORY_PODCASTS Qny audio files in the list of podcasts that the user can select (not as regular music). String DIRECTORY_RINGTONES Any audio files in the list of ringtones that the user can select (not as regular music). F. Mallet 12
Using DataBases Extend an helper class: SQLiteOpenHelper Use its oncreate method to create tables Call SQLiteDatabase getwritabledatabase() to get write access Call SQLiteDatabase getreadabledatabase() to get read access Use the query() method of SQLiteDatabase Example: public class DictionaryOpenHelper extends SQLiteOpenHelper { 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, 1 /* version */); @Override public void oncreate(sqlitedatabase db) { db.execsql(dictionary_table_create); F. Mallet http://www.sqlite.org/lang_createtable.html 13
Schema and Contract Schema: declaration of how the database is organized Contract class: (recommended) Companion class to reflect the schema (CONSTANTS) Global definitions, Inner classes for each table Inherit from BaseColums to get an _ID (used by Cursor) Example: public final class ExampleContract { public static final String DATABASE_NAME = exampledb"; private ExampleContract() { /* NOBODY CAN INSTANTIATE */ public static abstract class ExampleEntry implements BaseColumns { public static final String TABLE_NAME = mytable"; public static final String COLUMN_NAME_CATEGORY = category"; public static final String COLUMN_NAME_WORD = word"; public static final String SQL_CREATE = "CREATE TABLE " + TABLE_NAME + "( " + _ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + COLUMN_NAME_CATEGORY + " TEXT, " + COLUMN_NAME_WORD + " TEXT);"; F. Mallet.. 14
Using DataBases Extend an helper class: SQLiteOpenHelper Example: public class DictionaryOpenHelper extends SQLiteOpenHelper { DictionaryOpenHelper(Context context) { super(context, ExampleContract.DATABASE_NAME, null, 1 /* version */); @Override public void oncreate(sqlitedatabase db) { db.execsql(examplecontract.exampleentry.sql_create); @Override public void onupgrade(sqlitedatabase db, int oldversion, int newversion) { db.execsql(tablecontract.wordcontract.sql_delete); oncreate(db); @Override public void ondowngrade(sqlitedatabase db, int oldversion, int newversion) { onupgrade(db, oldversion, newversion); F. Mallet 15
Method insert of SQliteDatabase Use ContentValues Example SQLiteDatabase db = helper.getwritabledatabase(); Adding a row in a table ContentValues values = new ContentValues(); values.put(examplecontract.exampleentry.column_name_category,category); values.put(examplecontract.exampleentry.column_name_word, word); long newrowid = db.insert(examplecontract.exampleentry.table_name, null, // name of columns that can be null values); F. Mallet 16
Deleting a row Method insert of SQliteDatabase Make a SQLite query for deletion Example (in Contract) public static final String DELETE_ROW = COLUMN_NAME_WORD + " =?"; Example (to delete the row) SQLiteDatabase db = helper.getwritabledatabase(); int nb = db.delete(examplecontract.exampleentry.table_name, ExampleContract.ExampleEntry.DELETE_ROW, new String[]{word); F. Mallet 17
Selecting rows Use Query method in SQLiteDatabase public Cursor query (String table, String[] columns, String selection, String[] selectionargs, String groupby, String having, String orderby) Use the Cursor to iterate through the result Example SQLiteDatabase db = helper.getreadabledatabase(); Cursor c = db.query(examplecontract.exampleentry.table_name, null, null, null, null, null, ExampleContract.ExampleEntry.COLUMN_NAME_CATEGORY); List<DBLine> mylist = new ArrayList<>(); while (c.movetonext()) { mylist.add(new DBLine(c.getString(1), c.getstring(2))); F. Mallet 18
References Android Developers http://developer.android.com/training/index.html Other lectures at UNS P. Renevier E. Amosse Books Beginning Android, M. L. Murphy, APress Android Programming: The Big Nerd Ranch Guide, B. Phillips, B. Hardy, http://www.bignerdranch.com F. Mallet 19