Data	
  Persistence	
  in	
  Android	
  
Jussi	
  Pohjolainen	
  
Tampere	
  University	
  of	
  Applied	
  Sciences	
  
Contents	
  
•  Overview	
  
•  About	
  State	
  InformaAon	
  
•  Preferences	
  
•  Using	
  files	
  
•  Using	
  databases	
  
•  Accessing	
  Content	
  Providers	
  
Overview	
  of	
  Data	
  Storing	
  
•  App	
  data	
  is	
  private	
  to	
  the	
  applicaAon	
  
•  Several	
  mechanism	
  
–  State	
  Storage:	
  Ram	
  memory!	
  
•  Mechanism	
  for	
  saving	
  acAvity’s	
  state	
  temporarily	
  
–  Preferences	
  
•  Lightweight	
  mechanism	
  to	
  store	
  and	
  retrieve	
  key-­‐value	
  pairs	
  
–  Files	
  
•  Open	
  and	
  save	
  files	
  on	
  the	
  device	
  or	
  removable	
  storage	
  
–  SQLite	
  databases	
  
•  Databases	
  
•  Content	
  provider	
  is	
  used	
  to	
  give	
  the	
  data	
  to	
  other	
  apps	
  
AcAvity	
  State:	
  Using	
  RAM	
  
•  AcAvity’s	
  state	
  informaAon	
  can	
  be	
  lost,	
  if	
  it’s	
  
closed	
  
– When	
  acAvity	
  is	
  no	
  longer	
  on	
  the	
  screen	
  and	
  it’s	
  
closed	
  because	
  of	
  freeing	
  memory	
  
– When	
  screen	
  rota1on	
  is	
  changed,	
  the	
  acAvity	
  is	
  
destroyed	
  and	
  opened	
  again	
  
	
  
How	
  to	
  Store	
  State	
  InformaAon	
  
•  Store	
  state:	
  
– onSaveInstanceState(Bundle)
•  Read	
  state	
  
– onRestoreInstanceState(Bundle)
•  This	
  will	
  store	
  data	
  only	
  temporarily:	
  for	
  app	
  
life1me!	
  
•  Data	
  will	
  be	
  held	
  in	
  memory	
  un1l	
  the	
  app	
  is	
  
closed!	
  
Store	
  
@Override
public void onSaveInstanceState(Bundle savedInstanceState)
{
String text = tv.getText().toString();
savedInstanceState.putString("someKey", text);
super.onSaveInstanceState(savedInstanceState);
}
Load	
  
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (savedInstanceState != null)
{
String strValue = savedInstanceState.getString("someKey");
if (strValue != null)
{
textfield.setText(strValue);
}
}
}
Shared	
  Preferences:	
  Permanent	
  Storage	
  
•  Very	
  simple	
  way	
  of	
  share	
  small	
  amount	
  of	
  
data	
  between	
  acAviAes	
  
•  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	
  mulAple	
  preference	
  files	
  (idenAfied	
  by	
  name)	
  
–  getPreferences() –	
  Use	
  if	
  only	
  one	
  preferences	
  file	
  
is	
  needed	
  
•  To	
  write	
  values,	
  call	
  edit() to	
  get	
  
SharedPreferences.Editor	
  to	
  be	
  used	
  when	
  
adding	
  values	
  to	
  file.	
  
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);
      // Commit the edits!
      editor.commit();
    }
}
Files	
  
•  It's	
  possible	
  to	
  store	
  files	
  on	
  the	
  mobile	
  device	
  or	
  on	
  a	
  
removable	
  storage	
  
•  Current	
  applica1on	
  folder	
  only.	
  ExcepAon	
  thrown	
  
otherwise.	
  
–  Modes:	
  MODE_PRIVATE,	
  MODE_WORLD_READABLE,	
  
MODE_WORLD_WRITABLE	
  
•  Reading	
  
–  openFileInput()
•  WriAng	
  
–  openFileOutput()
•  Standard	
  Java	
  streams	
  aer	
  that	
  
StaAc	
  files	
  
•  You	
  can	
  save	
  staAc	
  files	
  into	
  res/raw	
  directory	
  
•  Accessing	
  using	
  
openRawResource(R.raw.<filename>)
•  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	
  file	
  
•  When	
  reading	
  public	
  file,	
  use	
  FileInputStream	
  
(vs.	
  openFileInput)	
  
•  Give	
  full	
  path:	
  /data/data/<package>/files
SQLite	
  
•  Support	
  for	
  SQlite	
  databases	
  
–  Database	
  is	
  private	
  to	
  the	
  applicaAon	
  that	
  creates	
  it	
  
•  SQLiteDatabase	
  object	
  represents	
  a	
  database	
  
•  SQLiteOpenHelper	
  –	
  wrapper	
  for	
  database	
  
acAons	
  
•  Android	
  SDK	
  has	
  a	
  tool	
  called	
  sqlite3	
  which	
  
enables	
  you	
  to	
  browse	
  table	
  contents	
  using	
  sql	
  
commands	
  and	
  command	
  line	
  
•  All	
  databases	
  are	
  stored	
  in	
  /data/data/
<package_name>/databases folder	
  on	
  your	
  
device.	
  
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	
  pracAce	
  pacern	
  for	
  creaAng,	
  
opening	
  and	
  upgrading	
  databases	
  
•  You	
  hide	
  the	
  logic	
  used	
  to	
  decide	
  if	
  a	
  database	
  
needs	
  to	
  be	
  created	
  or	
  upgraded	
  before	
  it's	
  
opened	
  
Recommended	
  Way:	
  SQLiteOpenHelper	
  
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);
    }
}
// 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);
}
}
}
Remote	
  Shell	
  for	
  Databases	
  
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	
  
•  NaAve	
  databases	
  available	
  as	
  Content	
  
Providers	
  
•  Publishing	
  your	
  own	
  data	
  source,	
  other	
  apps	
  
can	
  incorporate	
  your	
  database	
  
Content	
  Resolver	
  
•  ApplicaAon	
  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	
  defined	
  in	
  
manifest	
  file	
  
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>
•  Example	
  for	
  querying	
  all	
  items	
  
–  content://fi.pohjolainen_jussi.provider.myapp/items
•  Example	
  for	
  querying	
  single	
  item	
  (fih)	
  
–  content://fi.pohjolainen_jussi.provider.myapp/items/5
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>
Accessing	
  Content	
  Provider	
  
public class MyContentProvider extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ContentResolver cr = getContentResolver();
Uri uri = Uri.parse("content://fi.pohjolainen_jussi.provider.mycontentprovider");
Cursor cursor = cr.query(uri, null, null, null, null);
}
}
Extend	
  Content	
  Provider	
  
public class MyContentProvider extends ContentProvider {
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {...}
@Override
public String getType(Uri uri) {...}
@Override
public Uri insert(Uri uri, ContentValues values) {...}
@Override
public boolean onCreate() {...}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {...}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {...}
}
URLMatcher	
  
•  The	
  content	
  provider	
  can	
  give	
  different	
  results	
  
depending	
  on	
  the	
  URI:	
  
– content://
fi.pohjolainen_jussi.provider.myapp/items
– content://
fi.pohjolainen_jussi.provider.myapp/
items/5
•  Use	
  UAlity	
  class	
  URLMatcher	
  to	
  differenAate	
  
the	
  given	
  URIs	
  
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;
}
}

Android Data Persistence

  • 1.
    Data  Persistence  in  Android   Jussi  Pohjolainen   Tampere  University  of  Applied  Sciences  
  • 2.
    Contents   •  Overview   •  About  State  InformaAon   •  Preferences   •  Using  files   •  Using  databases   •  Accessing  Content  Providers  
  • 3.
    Overview  of  Data  Storing   •  App  data  is  private  to  the  applicaAon   •  Several  mechanism   –  State  Storage:  Ram  memory!   •  Mechanism  for  saving  acAvity’s  state  temporarily   –  Preferences   •  Lightweight  mechanism  to  store  and  retrieve  key-­‐value  pairs   –  Files   •  Open  and  save  files  on  the  device  or  removable  storage   –  SQLite  databases   •  Databases   •  Content  provider  is  used  to  give  the  data  to  other  apps  
  • 4.
    AcAvity  State:  Using  RAM   •  AcAvity’s  state  informaAon  can  be  lost,  if  it’s   closed   – When  acAvity  is  no  longer  on  the  screen  and  it’s   closed  because  of  freeing  memory   – When  screen  rota1on  is  changed,  the  acAvity  is   destroyed  and  opened  again    
  • 5.
    How  to  Store  State  InformaAon   •  Store  state:   – onSaveInstanceState(Bundle) •  Read  state   – onRestoreInstanceState(Bundle) •  This  will  store  data  only  temporarily:  for  app   life1me!   •  Data  will  be  held  in  memory  un1l  the  app  is   closed!  
  • 6.
    Store   @Override public voidonSaveInstanceState(Bundle savedInstanceState) { String text = tv.getText().toString(); savedInstanceState.putString("someKey", text); super.onSaveInstanceState(savedInstanceState); }
  • 7.
    Load   @Override protected voidonRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); if (savedInstanceState != null) { String strValue = savedInstanceState.getString("someKey"); if (strValue != null) { textfield.setText(strValue); } } }
  • 8.
    Shared  Preferences:  Permanent  Storage   •  Very  simple  way  of  share  small  amount  of   data  between  acAviAes   •  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)  
  • 9.
    How?   •  SharedPreferences  provides  general  framework   for  saving  and  retrieving   •  To  get  SharedPreferences,  use   –  getSharedPreferences(String name) –  Use  if  you   need  mulAple  preference  files  (idenAfied  by  name)   –  getPreferences() –  Use  if  only  one  preferences  file   is  needed   •  To  write  values,  call  edit() to  get   SharedPreferences.Editor  to  be  used  when   adding  values  to  file.  
  • 10.
    Preferences  Example   publicclass 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);       // Commit the edits!       editor.commit();     } }
  • 11.
    Files   •  It's  possible  to  store  files  on  the  mobile  device  or  on  a   removable  storage   •  Current  applica1on  folder  only.  ExcepAon  thrown   otherwise.   –  Modes:  MODE_PRIVATE,  MODE_WORLD_READABLE,   MODE_WORLD_WRITABLE   •  Reading   –  openFileInput() •  WriAng   –  openFileOutput() •  Standard  Java  streams  aer  that  
  • 12.
    StaAc  files   • You  can  save  staAc  files  into  res/raw  directory   •  Accessing  using   openRawResource(R.raw.<filename>) •  Returns  InputStream •  Cannot  write  to  data  
  • 13.
    Files   // Write StringFILENAME = "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()
  • 14.
    Reading  MODE_WORLD_READABLE  file   •  When  reading  public  file,  use  FileInputStream   (vs.  openFileInput)   •  Give  full  path:  /data/data/<package>/files
  • 15.
    SQLite   •  Support  for  SQlite  databases   –  Database  is  private  to  the  applicaAon  that  creates  it   •  SQLiteDatabase  object  represents  a  database   •  SQLiteOpenHelper  –  wrapper  for  database   acAons   •  Android  SDK  has  a  tool  called  sqlite3  which   enables  you  to  browse  table  contents  using  sql   commands  and  command  line   •  All  databases  are  stored  in  /data/data/ <package_name>/databases folder  on  your   device.  
  • 16.
    SQLiteDatabase:  Open   publicvoid openDatabase() { try { db = this.openOrCreateDatabase("MyTestDatabase.db", MODE_PRIVATE, null); db.execSQL("CREATE TABLE MYDATA(firstname TEXT, lastname TEXT)"); } catch (SQLiteException e) { e.printStackTrace(); } }
  • 17.
    SQLiteDatabase:  Insert   publicvoid insertRows() { try { db.execSQL("INSERT INTO MYDATA VALUES ('Jack', 'Smith')"); } catch (Exception e) { e.printStackTrace(); } }
  • 18.
    SQLiteDatabase:  Read   publicvoid 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(); } }
  • 19.
    SQLiteOpenHelper   •  Wraps  best  pracAce  pacern  for  creaAng,   opening  and  upgrading  databases   •  You  hide  the  logic  used  to  decide  if  a  database   needs  to  be  created  or  upgraded  before  it's   opened  
  • 20.
    Recommended  Way:  SQLiteOpenHelper   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);     } }
  • 21.
    // Example public classSQLiteExample 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); } } }
  • 22.
    Remote  Shell  for  Databases  
  • 23.
    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   •  NaAve  databases  available  as  Content   Providers   •  Publishing  your  own  data  source,  other  apps   can  incorporate  your  database  
  • 24.
    Content  Resolver   • ApplicaAon  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  defined  in   manifest  file  
  • 25.
    Usage   // Query Cursorc = getContentResolver().query(URI, ..., ... ,...); // Insert getContentResolver().insert(URI, newValues); // Delete getContentResolver().delete(URIofTheRow, ...);
  • 26.
    URIs   •  Content  URIs  must  be  unique  between   providers.   •  Use  your  package  name   •  General  form   –  content://com.<company>.provider.<app>/<data> •  Example  for  querying  all  items   –  content://fi.pohjolainen_jussi.provider.myapp/items •  Example  for  querying  single  item  (fih)   –  content://fi.pohjolainen_jussi.provider.myapp/items/5
  • 27.
    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>
  • 28.
    Accessing  Content  Provider   public class MyContentProvider extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ContentResolver cr = getContentResolver(); Uri uri = Uri.parse("content://fi.pohjolainen_jussi.provider.mycontentprovider"); Cursor cursor = cr.query(uri, null, null, null, null); } }
  • 29.
    Extend  Content  Provider   public class MyContentProvider extends ContentProvider { @Override public int delete(Uri uri, String selection, String[] selectionArgs) {...} @Override public String getType(Uri uri) {...} @Override public Uri insert(Uri uri, ContentValues values) {...} @Override public boolean onCreate() {...} @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {...} @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {...} }
  • 30.
    URLMatcher   •  The  content  provider  can  give  different  results   depending  on  the  URI:   – content:// fi.pohjolainen_jussi.provider.myapp/items – content:// fi.pohjolainen_jussi.provider.myapp/ items/5 •  Use  UAlity  class  URLMatcher  to  differenAate   the  given  URIs  
  • 31.
    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); } }
  • 32.
    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; } }