Академический Документы
Профессиональный Документы
Культура Документы
Plan
Data Storage on Mobile Devices
Data Storage in Android
Content Providers
Processes and Multithreading
Databases
Used in Palm OS, Java ME
Data hold in memory-backed RAM permanent data structure
Record structure defined by the application, fixed for a given database all records have the same structure
Other applications dont know how to read the database
No SQL in Palm OS/Java ME (database is rather like a single table)
Require little processing power to handle the database
Android uses SQLite, databases are not the lowest-level data storage
Files
Used in EPOC/Symbian OS, Maemo, iOS, Windows CE/Phone
Various filesystems (FAT, ext3, HFS+, NTFS)
Familiar API
High-level
SQL database using files as backend
Limited user-access to the file-system; concept of file absent from iOS UI
MW/2011/TIES425/Data Storage
Storage Facilities
Shared preferences
Internal storage
External storage
SQLite database
Shared Preferences
MW/2011/TIES425/Data Storage
File Access
Two types of files:
Application-specific: meaningful only to the application (e.g., game scores, application preferences)
Shared: used by several different applications (e.g., pictures, sound clips, videos)
Application-specific data are hidden from other applications and from the user
Shared files must be accessible to all (also through USB mass-storage)
Internal Storage
Storage space by default private to the application
The user cannot access it
Cleared when the application is removed
Used for shared preferences
Default location, relative to the application no need to worry about absolute path or actual location on the
file system
Use this for large amounts of data
File Example
String FILENAME = " hello_file " ;
String string = " hello world ! " ;
FileOutputStream fos = openFileOutput ( FILENAME , Context . MODE_PRIVATE );
fos . write ( string . getBytes ());
fos . close ();
...
byte [] buffer = new byte [ BUFFER_SIZE ];
FileInputStream fis = openFineInput ( FILENAME );
if ( fis . read ( buffer ) > -1) {
...
}
fis . close ()
Temporary Files
Context.getCacheDir() returns a File object representing the application-specific cache directory for
temporary files
Use File.createTempFile(...) to create a temporary file
Temporary files are removed automatically when storage space runs out, but do not rely on the system for
removing those, manage them yourself
MW/2011/TIES425/Data Storage
External Storage
Removable or non-removable flash memory, depending on the device
World-readable files (FAT has no permission)
May be temporarily inaccessible (mounted as USB mass-storage, or removed from the device) always check
for availability before accessing it
Mounting a Filesystem
Unix concept
Plug the content of a filesystem B into a directory of another filesystem A
For the user, files of B look like files of A
Shared Files
Files in Android/data/<package_name>/... are deleted when the application is removed
Files shared between applications should be put in one of the following directories: Music, Podcasts,
Ringtones, Alarms, Notifications, Pictures, Movies, Download
The path must be built by hand in Android < 2.2, but you can use
Environment.getExternalStoragePublicDirectory(type) in Android 2.2+
MW/2011/TIES425/Data Storage
Using Databases
Support for SQLite in Android
SQLite: SQL database, stored in a single file
File stored as a private file of the application
APIs
SQLiteDatabase class allows to run SQL queries on a database
Provides convenience methods for common operations (insert/update/delete a row, make a query)
Queries return a Cursor object
Cursors allow to travel a list of rows and get values from the columns in the row
SQLiteOpenHelper
A class that handles creating/opening/updating a database
getWritableDatabase()/getReadableDatabase() methods
Creates the database if it doesnt exist
Opens an existing database (possibly just created)
Updates the content of the database if a new version of the application uses a new schema
SQLiteOpenHelper Example
public class DictionaryOpenHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 2;
private static final String DI CTIO NARY _TABL E_NA ME = " dictionary " ;
private static final String DI C TI ON A RY _ TA BL E _C R EA TE =
" CREATE TABLE " + DICT IONA RY_T ABLE_ NAME + " ( " +
KEY_WORD + " TEXT , " + KEY_DEFINITION + " TEXT ); " ;
D i c t i o n a r y OpenHelper ( Context context ) {
super ( context , DATABASE_NAME , null , DATABASE_VERSION );
}
@Override
public void onCreate ( SQLiteDatabase db ) {
db . execSQL ( DI C TI ON A RY _ TA BL E _C R EA T E );
}
@Override
public void onUpgrade ( SQLiteDatabase db , int oldVersion , int newVersion ) {
db . execSQL ( " DROP TABLE " + D ICTIO NARY _TAB LE_NA ME + " ; " );
onCreate ( db );
}
}
MW/2011/TIES425/Data Storage
Content Providers
Content Provider
Allows to share data between any application
Data server accessible using RPC
Application component, declared in AndroidManifest.xml
Examples: contacts, browser bookmarks/history, phone call log, media store, global user settings
Data Model
Content providers return data as tables
Handled through a Cursor
Every record in the table includes a numeric _ID field; can be used to match two rows in related tables
URIs
Data sets are identified with URIs starting with content://
System content provider classes contain constants holding the URI e.g.,
ContactsContract.Contacts.CONTENT_URI
Record ID can be appended to the URI to refer to that specific record:
Uri myPerson = ContentUris . withAppendedId ( People . CONTENT_URI , 23); // int
OR
Uri myPerson = Uri . withAppendedPath ( People . CONTENT_URI , " 23 " ); // String
A subtable name can appended after a record with ID, e.g., .../people/42/phones/3 is the 3rd record in
subtable phone of 42nd record in table people
Query Parameters
URI
Column names (array of String)
SQL WHERE clause (to filter the rows), or null
Argument for the WHERE clause, or null
SQL ORDER BY clause, or null
MW/2011/TIES425/Data Storage
Query Example
import android . provider . Contacts . People ;
import android . database . Cursor ;
// Form an array specifying which columns to return .
String [] projection = new String [] {
People . _ID ,
People . _COUNT , // fake column , generated
People . NAME ,
People . NUMBER
};
// Get the base URI for the People table in the Contacts content provider .
Uri contacts = People . CONTENT_URI ;
// Make the query .
Cursor managedCursor = managedQuery ( contacts ,
projection , // Which columns to return
null ,
// Which rows to return ( all rows )
null ,
// Selection arguments ( none )
// Put the results in ascending order by name
People . NAME + " ASC " );
Large Data
Reasonably small data (< 50 kB or so) can be stored as a blob in a database retrieve them with
Cursor.getBlob()
Large data are stored as files and the database contains a URI retrieve them with
ContentResolver.openInputStream(uri)
Adding Records
Find to which table the data must be added
Put key/value pairs in a ContentValues object
Call ContentResolver.insert(uri, content_values)
It returns a URI to the new record
Once a record is created in the main table, other records can be added to the subtables (append the subtables
name to the main records URI)
MW/2011/TIES425/Data Storage
Other Operations
Batch update with ContentResolver.update()
Delete records with ContentResolver.delete()
URI for a specific record delete this record
Base URI and SQL WHERE clause delete all matching records
MW/2011/TIES425/Data Storage
Foreground Process
Hosting a running activity
Hosting a service that is
bound to a running activity
running in the foreground
executing one of the lifecycle callbacks (onCreate(), onStart(), onDestroy())
Hosting a broadcast receiver executing onReceive()
Visible Process
No foreground component, but can still affect whats on screen
Hosting a paused activity
Hosting a service bound to a visible or foreground activity
Service Process
Doing work in the background (playing music, downloading a file)
Hosting a service started with startService()
Doesnt belong to one of the above categories
Backgound Process
Hosting a stopped activity
Process has no impact on user experience
Kept in a Last-Recently Used list, the most recently used process is the last killed
Killing it has no effect on user experience if it saves its state properly
Empty Process
Hosts no active application component
Kept for being reused for other components faster startup time
Threads
Android applications are event-driven, normally run in a single thread (called main or UI thread)
New components (e.g., services) are run in the same thread by default
Main thread blocked for more than 5 seconds application not responding dialog appears
Do not block the UI thread
Android UI toolkit is not thread-safe do not access UI components from another thread
MW/2011/TIES425/Data Storage
Helper Methods
View.post() and View.postDelay() take a Runnable as argument and append it to the event queue of the
UI thread executing in the UI thread (with a delay for the second method)
Activity.runOnUiThread() takes a runnable and
runs it in the current thread if it is the UI thread
posts the runnable to the event queue of the UI thread otherwise
Using AsyncTask
Hides all the boilerplate code (creating a runnable, a thread and posting the result to the UI thread)
Subclass AsyncTask as an inner class
Implement its doInBackground() (run in the worker thread)
Implement its onPostExecute() (run in the UI thread)
AsyncTask Example
public void onClick ( View v ) {
new Dow nloadImageTask (). execute ( " http :// example . com / image . png " );
}
private class DownloadImageTask extends AsyncTask < String , Void , Bitmap > {
// Receives parameters from execute ()
protected Bitmap doInBackground ( String ... urls ) {
return l oadImageFromNetwork ( urls [0]);
}
// Receives the value returned by doInBackground ()
protected void onPostExecute ( Bitmap result ) {
mImageView . setImageBitmap ( result );
}
}
Conclusion
Modern mobile devices tend to hide files from users
Data storage in Android can be made in several different manners
Content providers hide the implementation of the storage to activities
Content providers can be shared across many applications
Multithreading is advised when doing I/O
MW/2011/TIES425/Data Storage
10