0% found this document useful (0 votes)
12 views

Topic 3 - Files and Databases

This document discusses files, databases, and preferences in Android mobile applications. It covers internal storage, external storage, and how to read from and write to files on both the internal and external storages. It also discusses how to use SharedPreferences to store key-value pairs and SQLite databases to store structured data in Android applications.

Uploaded by

Maricel Olaru
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views

Topic 3 - Files and Databases

This document discusses files, databases, and preferences in Android mobile applications. It covers internal storage, external storage, and how to read from and write to files on both the internal and external storages. It also discusses how to use SharedPreferences to store key-value pairs and SQLite databases to store structured data in Android applications.

Uploaded by

Maricel Olaru
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 49

Files and databases

Mobile Applications

Óscar David Sánchez

University of Valencia

Topic 3, Files and Databases 1/49


Outline

1 Introduction

2 Files

3 Preferences

4 SQLite databases

5 References

Topic 3, Files and Databases 2/49


Introduction

Índice

1 Introduction

2 Files

3 Preferences

4 SQLite databases

5 References

Topic 3, Files and Databases 3/49


Introduction

Introduction

Android devices have a file system.


From the application we can create files to store persisten information.
Devices have internal storage and can have external storage (for example
an SD card):

Internal storage (which is always there and has a fixed capacity)


External storage (which may not be available if the user extracts it,
and has a variable capacity).

Topic 3, Files and Databases 4/49


Introduction

Introduction

If we need to store key/value pairs the system offers Shared Preferences


using a higher level API (the details of input/output streams are hidden).
In this case, that information is stored in the internal storage.
Finally, the system offers a SQLite database manager in which databases
can be created to store structured information.

Topic 3, Files and Databases 5/49


Files

Índice

1 Introduction

2 Files

3 Preferences

4 SQLite databases

5 References

Topic 3, Files and Databases 6/49


Files

Files that are part of the application (resources)

In the directory res/raw we can have files and from the application we can
read them. Those files will be inside the apk file and can only be read (can
not be modified).
First we obtain an object of type Resources:
// getResource is a method declared in Context
// and Activity extends from Context
Resources r = getResources();

Next, we obtain an InputStream that allows us to read from the file:


InputStream in = r.openRawResource(R.raw.fileNameWithoutExtension);

// That reference can be passed to the constructor of a subclass


// of FilterInputStream that adds the desired functionality:
// DataInputStream: to read primitive types
// BufferedInputStream: to user a buffer (efficiency)
// ...

Topic 3, Files and Databases 7/49


Files Internal storage

Índice

2 Files
Internal storage
External storage

Topic 3, Files and Databases 8/49


Files Internal storage

Internal storage

Android creates a private directory for the app.


The path of that folder is:
/data/data/your.package.name
Within this folder, some common sub-folders may exist:

files: for files


cache: for cache files and data
shared_prefs: for your preferences
databases: for SQLite databases
lib: for libraries

Topic 3, Files and Databases 9/49


Files Internal storage

Internal storage

You can create files in internal storage as long as they are small files.
These files are private to the application and other applications do not have
access to them. When the user deletes the application, the files are also
deleted.
Internal storage directories can be obtained by calling the following
methods:

getFilesDir() returns a reference of type File to the internal


files directory of the application.
getCacheDir() returns a reference of type File to the internal
cache directory of the application. The system or the user can clear
the cache of an application.

Topic 3, Files and Databases 10/49


Files Internal storage

Internal storage in files (writing)

The method openFileOutput(.) declared in the class Context returns a


FileOutputStream that we can use to write information in the internal
directory.
The FileOutputStream can be decorated with the output classes that add
additional functionality (like BufferedOutputStream,
DataOutputStream, GZIPOutputStream, etc).

Topic 3, Files and Databases 11/49


Files Internal storage

Internal storage in files (writing)

For example:
String file = ...;
FileOutputStream out = openFileOutput(fichero, Context.MODE_PRIVATE);
// Write information
out.close();

Context.MODE_PRIVATE the data in the file can only be accessed by the


application.
Context.MODE_APPEND open the file to add information.

Topic 3, Files and Databases 12/49


Files Internal storage

Internal storage in files (reading)

The method openFileInput(String name) of the class Context returns


a reference of type FileInputStream that allows to read the information
stored in a file.
This FileInputStream can be decorated using DataInputStream,
BufferedInputStream, GZIPInputStream, etc.
String file = ...;
FileInputStream in = openFileInput(fichero);
// Read information
in.close();

Topic 3, Files and Databases 13/49


Files Internal storage

Internal storage in the cache

It serves as temporary storage.


It is recommended to use a maximum of 1MB of space.
The following example shows how temporary information can be stored in
the cache:
String prefix = ...;
String suffix = ...;

File f = File.createTempFile (prefix, suffix, context.getCacheDir ());


FileOutputStream out = new FileOutputStream(f);
// Write information in the file
out.close();

Topic 3, Files and Databases 14/49


Files External storage

Índice

2 Files
Internal storage
External storage

Topic 3, Files and Databases 15/49


Files External storage

External storage

The information generated by an application written in the external storage


can be:

Information that has a standard format (PDF, PNG, TXT, JPG, etc).
This information can be viewed/processed with other applications.
Therefore, it should not be deleted when the application is uninstalled.
Information that has a format known by the application. This is
information can not be viewed/processed with other applications.
Therefore, it should be deleted when the application is unistalled.

To write to the external storage, the application must request the


permission android.permission.WRITE_EXTERNAL_STORAGE.
This permission must be declared in the file AndroidManifest.xml

Topic 3, Files and Databases 16/49


Files External storage

External storage: public data

The following example obtains the default public directory used to store
music:
File f = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_MUSIC);

The following statement creates a directory in the default public directory


assigned to store images (DCIM):
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "processed");

Topic 3, Files and Databases 17/49


Files External storage

External storage: app data

The external storage for an app is located in the following path:


Android/data/your.package.name/
We can use the following method to obtain the directory of the files for
the app external storage:
File f = getExternalFilesDir(null);

From that File we can create output or input streams.

Topic 3, Files and Databases 18/49


Preferences

Índice

1 Introduction

2 Files

3 Preferences

4 SQLite databases

5 References

Topic 3, Files and Databases 19/49


Preferences

Preferences

They allow to store a set of key/value pairs.


There are two possibilities to obtain an object of this type (these methods
are declared in the class Context)

getSharedPreferences (String name, int mode) this method is


used if several files are used.
getPreferences(int mode) if we have only one default preferences
file.

where mode indicates the permission that we give to the file:


MODE_PRIVATE (only the application can access the file and it is the
recommended value), MODE_WORLD_READABLE o MODE_WORLD_WRITABLE.
The last two are not recommended.

Topic 3, Files and Databases 20/49


Preferences

Preferences

Writing example:
SharedPreferences sharedPref = getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
// Use the editor to put key/value pairs
editor.putLong ("interval", 3600);
// Write the values to file
editor.commit();

http://developer.android.com/reference/android/content/
SharedPreferences.Editor.html
Reading example:
SharedPreferences sharedPref = getPreferences(Context.MODE_PRIVATE);
long default = 1800;
long interval = sharedPref.getLong("interval", default);

http://developer.android.com/reference/android/content/
SharedPreferences.html
Topic 3, Files and Databases 21/49
SQLite databases

Índice

1 Introduction

2 Files

3 Preferences

4 SQLite databases

5 References

Topic 3, Files and Databases 22/49


SQLite databases

Relational databases

To work with local databases in Android we have several options:

Work at a «low level» creating a class that offers methods in which


the queries to the BD are encapsulated.
Work with a framework such as OrmLite
http://ormlite.com/sqlite_java_android_orm.shtml

We will review the first option.


Other options: Mobile Backend as a Service
We can use also provided remote datastores like Firebase using libraries
from Google Play Services.

Topic 3, Files and Databases 23/49


SQLite databases

Data types in SQLite

The system offers a SQLite database manager in which databases can be


created to store structured information.
The types offered by SQLite are:

Type Description
NULL The value is null
INTEGER Integer value
REAL Decimal value
TEXT Text
BLOB For binary data

Topic 3, Files and Databases 24/49


SQLite databases

Class that encapsulates the access to the database

We will create a class that extends the class SQLiteOpenHelper.


This class will encapsulate all the accesses to the database.
We will have to provide:

The name of the database.


The name of the table(s).
The name of the columns in the table(s).
The creation of the table(s).
Methods to select, update, insert, data into the table(s).

Topic 3, Files and Databases 25/49


SQLite databases

Class that encapsulates the access to the database

Information about the name of the database, name of the table and
columns:
public class TasksDataBase extends SQLiteOpenHelper{
// Database name
private static final String DATABASE_NAME="Tasks";

// Name of the table in the database


private static final String TABLE_NAME="ToDo";

// Name of the columns in the table

// Must have a column "_id" to use custom adapters


// https://developer.android.com/reference/android/widget/CursorAdapter.html
private static final String KEY_ID="_id";

// Rest of the names of the columns


private static final String COLUMN_TODO_NAME="TODO";
private static final String COLUMN_SCHEDULED_NAME="SCHEDULED";
// etc
}

Topic 3, Files and Databases 26/49


SQLite databases

Class that encapsulates the access to the database


We add the constructor and implement the method onCreate where the
table is created:
public class TasksDataBase extends SQLiteOpenHelper{
...
// Must have a public constructor
public TasksDataBase(Context context,int version){
super(context, DATABASE_NAME, null,version);
// The third argument is of type SQLiteDatabase.CursorFactory or
// null to use the default
}

// And a method where the table is created if it does not exist


@Override
public void onCreate(SQLiteDatabase db) {
String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + "("
+ KEY_ID + " INTEGER PRIMARY KEY,"
+ COLUMN_TODO_NAME + " TEXT,"
// Rest of columns with their name and type
")";
db.execSQL(CREATE_TABLE);
}
}

Topic 3, Files and Databases 27/49


SQLite databases

Class that encapsulates the access to the database

We add a method to update the database from one version to another.


This method is called automatically when the version that appears in the
code is bigger than the version of the database.
public class TasksDataBase extends SQLiteOpenHelper{
...
// A method to update the database (due to a version change)
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// In a real scenario it would be necessary to extract the data from the BD
// Create the tables again with the new structrure
// and store the data in the new tables
}
...
}

Topic 3, Files and Databases 28/49


SQLite databases

Queries vs modifications

The API offers two two types of methods:

Query methods that do not modify the database: SELECT SQL


statements
Methods that modify the database: INSERT, UPDATE, DELETE,. . . SQL
statements

Topic 3, Files and Databases 29/49


SQLite databases

SELECT queries: Cursor


Query methods return the result in a reference of type Cursor.
Using this Cursor we can access to the data (similar to ResultSet in JDBC).
Analogy: the data structure used by a Cursor is similar to a
LinkedList<Vector<T».
Cursor offers methods to:

check its position (in the external data structrure):


isFirst(), isLast(), isBeforeFirst(), isAfterLast().
change its position (in the external data structure):
moveToFirst(), moveToLast(), moveToNext(), moveToPRevious(),
move(int n).
retrieve data (in the internal structure):
getInt(int col), getFloat(int col), getString(int col),
getBlob(int col)
get information about the schema:
getColumnName(), getColumnCount(), getColumIndex (String name),
etc.

Topic 3, Files and Databases 30/49


SQLite databases

SELECT queries

Structure of queries:
select attr1,...,attrN from table1,...,tableX
where (restrictions)
group by attr_i, ..., attr_j
having (condition)
order by attr_k,...,attr_r

There are two mechanisms to execute these types of sentences:

Raw queries: the full SELECT statement is provided.


Simple queries: you pass the parameters by parts to build a query on a
table

Topic 3, Files and Databases 31/49


SQLite databases

SELECT queries : rawQuery

Examples of raw queries:


SQLiteDatabase db = this.getReadableDatabase();
String sql = "select count(*) as total from table;";
Cursor c = db.rawQuery(sql);

String sql = "select count(*) as total from table where date>? and
score>? ";
String[] args = {’01/01/2013’,’400’}
Cursor c = db.rawQuery(sql,args);

Topic 3, Files and Databases 32/49


SQLite databases

SELECT queries: rawQuery

Example of query method with rawQuery:


public class TasksDataBase extends SQLiteOpenHelper{
...
public Cursor getAllData() {
String selectQuery = "SELECT * FROM " + TABLE_NAME +" order by "+
COLUMN_FECHA_NAME + " DESC";

// Request an instance that does not modify the database


SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);

return cursor;
}
...
}

Topic 3, Files and Databases 33/49


SQLite databases

SELECT queries: query


Can be used to perform queries on a single table
The select statement is given in parts:
query(String table,
String[] attrs,
String selection,
String[] seleccionArgs,
String groupby,
String having,
String orderby)

Example:
String table=TScores""
String [] columns = {"date", "name", "score"};
String[] seleccionArgs={"07/12/2017"};
String orderby="date";

Cursor c = db.query (table,


columns,
"date>?",
seleccionArgs,
null,
null,
orderby);

Topic 3, Files and Databases 34/49


SQLite databases

Modification sentences

The method execSQL(String sql) of the class SQLiteDatabase is used


to create, insert, update or delete tables and data.
Let’s suppose that we have the following table:
// Request an instance to modify the data
SQLiteDatabase db = this.getWritableDatabase();
db.execSQL("create table TScores (
_id integer PRIMARY KEY autoincrement,
date text,
name text,
score integer);"
);

We could insert a new record with the following sentences:


// Request an instance to modify the data
SQLiteDatabase db = this.getWritableDatabase();
db.execSQL ("insert in TScores (date, name, score) values (’09/10/2017’,
’Juan’,’4102’);");

Topic 3, Files and Databases 35/49


SQLite databases

Modification sentences

We can also use more specific methods like insert o update:


// Request an instance to modify the data
SQLiteDatabase db = this.getWritableDatabase();

ContentValues cv = new ContentValues();


cv.put ("date", "09/10/2017");
cv.put ("name", "Juan");
cv.put ("score","4102");
db.insert("TScore",null,cv);

// The second argument sets the name(s) of the column that can be null
// if we do not give the value for it (in the third argument)
// If we do not use this functionality, we pass null as the second argument

Topic 3, Files and Databases 36/49


SQLite databases

Class that encapsulates the access to the database

Method to add a record to the table:


public class TasksDataBase extends SQLiteOpenHelper{
...
// Insert a new record in the table. I assume that the new data
// record are encapsulated in a JavaBean object of type Todo
public void insertTodo(Todo d) {
// We request an instance to modify the BD
SQLiteDatabase db = this.getWritableDatabase();

ContentValues values = new ContentValues();


values.put (COLUMN_TODO_NAME,d.getTodo());
// Put values for the other columns

db.insert(TABLE_NAME,null,values);
}
...
}

Topic 3, Files and Databases 37/49


SQLite databases Use of the class that provides access to the database

Índice

4 SQLite databases
Use of the class that provides access to the database
Create an custom adapter using the Cursor

Topic 3, Files and Databases 38/49


SQLite databases Use of the class that provides access to the database

Use of this class in an Activity and a CursorAdapter I

class Ventana extends ListActivity{


private TasksDataBase refBD;
private SimpleCursorAdapter cursorAdapter;
private int version;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
refBD = new TasksDataBase(getApplicationContext(),version);
Cursor cursor = refBD.getAllData();

// Mapping columns in the table to views


String[] from_columns = { TasksDataBase.COLUMN_TODO_NAME,
TasksDataBase.COLUMN_SCHEDULED_NAME,... };
int[] to_views = { R.id.view1, R.id.view2,... };

// Adapter that obtains and shows the data from a Cursor. Arguments:
// 1- The context
// 2- The layout of each item
// 3- The cursor that contains the data to be displayed
// 4- An array of String with the names of the columns to extract data
// 5- An array of int with the id of the views where the

Topic 3, Files and Databases 39/49


SQLite databases Use of the class that provides access to the database

Use of this class in an Activity and a CursorAdapter II

// data should be shown


// 6- A flag
cursorAdapter = new SimpleCursorAdapter(getApplicationContext(),
R.layout.item, cursor, from_columns, to_views,
CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);

// Set the adapter to the list


setListAdapter(cursorAdapter);

// Create listeners to respond to events


// Use TasksDataBase methods to insert, delete, update elements
}

@Override
protected void onDestroy() {
super.onDestroy ();
dbReg.close();
}
}

Topic 3, Files and Databases 40/49


SQLite databases Use of the class that provides access to the database

Update CursorAdapter if data in the DB is modified

If our database access class provides methods that modify the data then we
must inform the list that the data has changed.
One possibility is to obtain the Cursor again and set it to the adapter:
// Obtain data (from an Activity, from an HTTP call, etc)
// Create a JavaBean with that information
// Pass that JavaBean to a method of our database class
Todo d = new Todo(...);
refBD.insertTodo(d);

// Change the Cursor in the adapter


cursorAdapter.swapCursor(refBD.getAllData ());
// When the cursor is changed, the view is automatically updated

Topic 3, Files and Databases 41/49


SQLite databases Create an custom adapter using the Cursor

Índice

4 SQLite databases
Use of the class that provides access to the database
Create an custom adapter using the Cursor

Topic 3, Files and Databases 42/49


SQLite databases Create an custom adapter using the Cursor

Custom adapter

In some scenarios the SimpleCursorAdapter is not appropriate.


Examples:

One of the columns in the table is the path where an image is stored
(for instance in the SD card). We want to show this information not
as a String but as an ImageView.
One of the columns in the table is an integer that can have two
values: 0 or 1, thus representing a boolean. We want to show this
information as a CheckBox.

Topic 3, Files and Databases 43/49


SQLite databases Create an custom adapter using the Cursor

Adapter that creates the views from the data in the Cursor I

Declare a class that extends CursorAdapter and implement newView and


bindView methods.
public class TasksCursorAdapter extends CursorAdapter{
...
// https://developer.android.com/training/improving-layouts/smooth-scrolling.
html
// Holder that contains references to the views of an item in the list
class ViewHolder{
TextView tvTodo;
...
}

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater li = (LayoutInflater)context.getSystemService(Service.
LAYOUT_INFLATER_SERVICE);
View view = li.inflate(R.layout.item_registro_layout, null);
fillView(view, cursor);
return view;

Topic 3, Files and Databases 44/49


SQLite databases Create an custom adapter using the Cursor

Adapter that creates the views from the data in the Cursor II
}

@Override
public void bindView(View view, Context context, Cursor cursor) {
fillView(view, cursor);
}

private void fillView(View view, Cursor cursor){


// Get information from the cursor
String todo = cursor.getString(cursor.getColumnIndex(TasksDataBase.
COLUMN_TODO_NAME));
...

// Try to obtain the ViewHolder from the view


ViewHolder holder = view.getTag();
TextView tvTodo;
...

// If it is not null obtain the views from the ViewHolder


if (holder != null){
tvTodo = holder.tvTodo;
...

Topic 3, Files and Databases 45/49


SQLite databases Create an custom adapter using the Cursor

Adapter that creates the views from the data in the Cursor III

}else{
// If it is null obtain the views and assign them to the ViewHolder
tvTodo = (TextView)view.findViewById(R.id.textView1);
...
ViewHolder holder = new ViewHolder();
holder.tvTodo = tvTodo;
...
view.setTag (holder);
}

// and assign the information


tvTodo.setText(todo);
...
}
}

Topic 3, Files and Databases 46/49


SQLite databases Create an custom adapter using the Cursor

Using the adapter

class Ventana extends ListActivity{


private TasksDataBase refBD;
private MiAdaptador cursorAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
...
refBD = new TasksDataBase(getApplicationContext(), version);
Cursor c = refBD.getAllData();
cursorAdapter = new TaskCursorAdapter(getApplicationContext(), c);
setListAdapter(cursorAdapter);
...
}
...
}

Topic 3, Files and Databases 47/49


References

Índice

1 Introduction

2 Files

3 Preferences

4 SQLite databases

5 References

Topic 3, Files and Databases 48/49


References

References

http://developer.android.com/training/basics/data-storage/index.html

Topic 3, Files and Databases 49/49

You might also like