Beruflich Dokumente
Kultur Dokumente
Persistence
in
Android
Jussi
Pohjolainen
Tampere
University
of
Applied
Sciences
Contents
Overview
Preferences
Using
les
Using
databases
Accessing
Content
Providers
Files
Open
and
save
les
on
the
device
or
removable
storage
SQLite
databases
Databases
Shared
Preferences
Very
simple
way
of
share
small
amount
of
data
between
acBviBes
Also
for
saving
the
state
of
the
app
Preferences
have
names,
so
apps
other
components
can
found
them
Preferences
can
be
private
or
public
(world
readable,
writeable)
How?
SharedPreferences
provides
general
framework
for
saving
and
retrieving
To
get
SharedPreferences,
use
getSharedPreferences(String
name)
Use
if
you
need
mulBple
preference
les
(idenBed
by
name)
getPreferences()
Use
if
only
one
preferences
le
is
needed
To write values, call edit() to get SharedPreferences.Editor to be used when adding values to le.
Preferences
Example
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); }
@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);
Files
It's
possible
to
store
les
on
the
mobile
device
or
on
a
removable
storage
Current
applica-on
folder
only.
ExcepBon
thrown
otherwise.
Modes:
MODE_PRIVATE,
MODE_WORLD_READABLE,
MODE_WORLD_WRITABLE
Reading
openFileInput()
WriBng
openFileOutput()
StaBc
les
You
can
save
staBc
les
into
res/raw
directory
Accessing
using
openRawResource (R.raw.<lename>)
Returns
InputStream
Cannot
write
to
data
Files
// Write String FILENAME = "hello_file"; String string = "hello world!"; FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE); fos.write(string.getBytes()); fos.close(); // Read FileInputStream fis = openFileInput(FILENAME); int byteChar; while((byteChar = fis.read()) != -1) { System.out.println((char) byteChar); } fis.close()
Reading
MODE_WORLD_READABLE
le
When
reading
public
le,
use
FileInputStream
(vs.
openFileInput)
Give
full
path:
/data/data/<package>/les
SQLite
Support
for
SQlite
databases
SQLiteDatabase
object
represents
a
database
SQLiteOpenHelper
wrapper
for
database
acBons
Android
SDK
has
a
tool
called
sqlite3
which
enables
you
to
browse
table
contens
using
sql
commands
and
command
line
All
databases
are
stored
in
/data/data/ <package_name>/databases
folder
on
your
device.
Database
is
private
to
the
applicaBon
that
creates
it
SQLiteDatabase:
Open
public void openDatabase() { try { db = this.openOrCreateDatabase("MyTestDatabase.db", MODE_PRIVATE, null); db.execSQL("CREATE TABLE MYDATA(firstname TEXT, lastname TEXT)"); } catch (SQLiteException e) { e.printStackTrace(); } }
SQLiteDatabase:
Insert
public void insertRows() { try { db.execSQL("INSERT INTO MYDATA VALUES ('Jack', 'Smith')"); } catch (Exception e) { e.printStackTrace(); } }
SQLiteDatabase:
Read
public void readRows() { try { Cursor c = db.rawQuery("SELECT * FROM MYDATA", null); String text = ""; c.moveToFirst(); for(int i=0; i<c.getCount(); i++) { text += c.getString(0) + " " + c.getString(1); c.moveToNext(); } tv.setText(text); } catch (Exception e) { e.printStackTrace(); } }
SQLiteOpenHelper
Wraps
best
pracBce
pacern
for
creaBng,
opening
and
upgrading
databases
You
hide
the
logic
used
to
decide
if
a
database
needs
to
be
created
or
upgraded
before
it's
opened
DictionaryOpenHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(DICTIONARY_TABLE_CREATE); }
// Example public class SQLiteExample extends Activity { private MyDataHelper dbhelper; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); dbhelper = new MyDataHelper(this); dbhelper.deleteAll(); dbhelper.insert("Jussi"); dbhelper.insert("Pekka"); dbhelper.insert("Tiina"); List<String> list = dbhelper.selectAll(); for(String object : list) { System.out.println(object); } } }
Content
Providers
The
recommended
way
of
sharing
data
in
Android
is
to
use
content
providers
Generic
interface
for
data
Permission
control
and
accessing
using
URI
model
NaBve
databases
available
as
Content
Providers
Publishing
your
own
data
source,
other
apps
can
incorporate
your
database
Content
Resolver
ApplicaBon
context
has
Content
Resolver
which
you
can
use
to
access
data
ContentResolver
cr
=
getContentResolver();
For accessing other databases, you need a URI URI is arbitraty String, which is dened in manifest le
Usage
// Query Cursor c = getContentResolver().query(URI, ..., ... ,...); // Insert getContentResolver().insert(URI, newValues); // Delete getContentResolver().delete(URIofTheRow, ...);
URIs
Content
URIs
must
be
unique
between
providers.
Use
your
package
name
General
form
content://com.<company>.provider.<app>/<data>
Manifest
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="fi.tamk" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".CallMe" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <provider android:name=".Data" android:authorities="fi.pohjolainen_jussi.provider.mycontentprovider"></provider> </application> <uses-sdk android:minSdkVersion="8" /> </manifest>
URLMatcher
The
content
provider
can
give
dierent
results
depending
on
the
URI:
content:// fi.pohjolainen_jussi.provider.myapp/items content:// fi.pohjolainen_jussi.provider.myapp/ items/5
Example
of
URIMatcher
public class Data extends ContentProvider { @Override public boolean onCreate() { initializeUriMatcher(); return false; } ... // Differentiate between different URI requests private static final int ALLROWS = 1; private static final int SINGLE_ROW = 2; // UriMatcher is utility class for aiding matching URIs in content providers private UriMatcher uriMatcher; private void initializeUriMatcher() { // Root node for the URI Matcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); // Add a URI to match, and the code to return when this URI is matched uriMatcher.addURI("fi.pohjolainen_jussi.provider.mycontentprovider", "items", ALLROWS); uriMatcher.addURI("fi.pohjolainen_jussi.provider.mycontentprovider", "items/#", SINGLE_ROW); } }
Example
of
URIMatcher
public class Data extends ContentProvider { @Override public boolean onCreate() { initializeUriMatcher(); return false; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { switch(uriMatcher.match(uri)) { case SINGLE_ROW: String rowNumber = uri.getPathSegments().get(1); // .. break; case ALLROWS: // break; }
return null; } }