This is the presentation I had at the FITC 2009 Conference in Amsterdam:
One of the main benefits for web developers who use the Adobe AIR runtime rather than Flash Player through a browser is that the security sandbox restrictions placed on the browser-based Flash Player do not exist within AIR applications.
You have now complete access to the operating system's file system and your applications have the ability to read, write, move, and delete files as well as creating and querying SQLite local databases.
In this session you'll learn how to leverage the file system's access features of the AIR APIs and how to apply advanced techniques to store data locally.
3. Agenda
1 We’ll talk about persistant local data with
AIR and ActionScritp 3
2 I’ll show AIR examples on:
Using the File class
Creating and reading local files
What we’ve learned from the File class
Creating local database
Best Practice tecniques
What we’ve learned from the SQLite classes
Different approaches to store and retrieve data
FITC 09
WWW.COMTASTE.COM
4. Local Persistent data
Adobe AIR
Adobe Integrated Runtime (AIR) is a
cross- operating system runtime that
allows developers to to deploy
desktop RIA’s.
FITC 09
WWW.COMTASTE.COM
7. Local Persistent data
Persistent data with the File class
Adobe AIR provides complete access to the host file system, allowing our
applications to use all the documents it needs to function correctly.
The flash.filesystem package, part of the Adobe AIR APIs, provides the
classes you need to work with the file system
FITC 09
WWW.COMTASTE.COM
8. Local Persistent data
Persistent data with the File class
The flash.filesystem package includes:
File
FileMode
FileStream
FITC 09
WWW.COMTASTE.COM
9. Local Persistent data
Persistent data with the File class
The File class
It is a reference to a specific file or folder on the host operating
system.
Used to identify the complete path of a file or folder, access
detailed information regarding the file or folder, or manipulate its
content.
FITC 09
WWW.COMTASTE.COM
10. Local Persistent data
Persistent data with the File class
The File class
It includes properties to point to standard folders as static constants of
the File class.
var fileObj:File = File.desktopDirectory.resolvePath(quot;readme.txtquot;);
It points to the readme.txt file on the user’s desktop using the File class
FITC 09
WWW.COMTASTE.COM
11. Local Persistent data
Persistent data with the File class
The File.userDirectory : corresponds to the user’s home folder on
Windows (C:Documents and settingsuserName) as well as on Mac
OS X (/User/userName/).
The File.documentsDirectory : is normally in the main user
folder and is meant to contain the user’s personal data and documents.
The File.applicationDirectory : is the directory where the AIR
application is installed
The File.desktopDirectory : is the active user’s desktop.
FITC 09
WWW.COMTASTE.COM
12. Local Persistent data
Persistent data with the File class
The File.applicationStorageDirectory : is a separate folder is
created by an AIR app for files containing the user’s preferences or any
partially saved documents. It is different for every user of the local
operating system.
The File.getRootDirectories(): it returns the file system root. On
Mac OS X systems, when you want to access the root of the operating
system, it always returns the reference to the only root file that’s
available: /. On Microsoft Windows systems,the system returns a list of
all the installed disks that are associated with a drive letter (e.g., C:, D:,
etc.).
DEMO
FITC 09
WWW.COMTASTE.COM
13. Local Persistent data
Persistent data with the File class
Accessing files and folders with the File class
To reach any file in the computer, the File class gives you
a few options:
The use of relative paths
The use of native paths
The use of URLs
The ability to browse and select
FITC 09
WWW.COMTASTE.COM
14. Local Persistent data
Persistent data with the File class
Accessing files and folders with the File class
Using Relative Paths: using this technique, you can start from one of
the standard folders provided by AIR and then choose the path of
your explicit destination.
var file:File = File.applicationDirectory.resolvePath(quot;readme.txtquot;);
FITC 09
WWW.COMTASTE.COM
15. Local Persistent data
Persistent data with the File class
Accessing files and folders with the File class
Using Relative Paths: you can also calculate the relative path between
two different files by using the getRelativePath()
var file1:File = File.desktopDirectory.resolvePath(
quot;my works/test/august/report.txtquot; );
var file2:File = File.desktopDirectory.resolvePath( quot;my worksquot; );
var relativePath:String = file2.getRelativePath( file1 );
// it will output: test/august/report.txt.
FITC 09
WWW.COMTASTE.COM
16. Local Persistent data
Persistent data with the File class
Accessing files and folders with the File class
Using Native Paths: corresponds to the absolute path of the file, as
defined by the local operating system.
For Windows it uses either the backslash () or the forward slash (/) as a
separator. Mac OS X systems only use the forward slash.
fileObj.nativePath = quot;/Users/Matteo/Test Folder/readme.txtquot;;
var fileObj:File = new File(quot;C:/Test Folder/readme.txtquot; );
FITC 09
WWW.COMTASTE.COM
17. Local Persistent data
Persistent data with the File class
Accessing files and folders with the File class
Using system URLs: the URLs that AIR accepts for
the file system are defined by three possible roots:
file:///, for a random path on the hosting system
app:/, for a relative path to the application installation folder
app-storage:/, for a relative path to the application data folder
FITC 09
WWW.COMTASTE.COM
18. Local Persistent data
Persistent data with the File class
Accessing files and folders with the File class
Using system URLs: the URLs that AIR accepts for
the file system are defined by three possible roots:
fileObj:File = new File(quot;file:///c:/Test Folder/readme.txtquot; );
FITC 09
WWW.COMTASTE.COM
19. Local Persistent data
Persistent data with the File class
Accessing files and folders with the File class
Browsing and selecting: opens a system dialog box.
browseForOpen() allows the user to select a single file on his computer.
It is possible to choose some filters to limit the selection to a certain
number of files.
browseForSave() allows the user to select a single file on his computer.
You can’t choose any filters—only a string to display in the title bar
of the box. DEMO
FITC 09
WWW.COMTASTE.COM
20. Local Persistent data
Persistent data with the File class
Performing operations on files
An AIR application can execute the following operations on files or
folders:
Copying (copyTo() and copyToAsync())
Moving (moveTo() and moveToAsync())
Moving to the system Recycle Bin (on Windows) or Trash (on the Mac)
(moveToTrashAsync() )
Deletion (deleteDirectory() and deleteFile())
FITC 09
WWW.COMTASTE.COM
21. Local Persistent data
Persistent data with the File class
The FileStream class
This class is responsible for accessing the content of a document and
provides various methods to write and read in the file.
It behaves very much like the ByteArray class.
You have to provide an instance of the File class to the FileStream class to
tell it which document you are interested in.
It requires to specify the access mode of the file using the FileMode.
FITC 09
WWW.COMTASTE.COM
22. Local Persistent data
Persistent data with the File class
The FileMode class
This class provides various static constants that define the possible modes
in which the FileStream class can access the binary content of any file.
Adobe AIR provides various modes that allow you to open a file in the
following modes:
• Reading: The FileStream object can read data from the file.
• Writing: The FileStream object can write data to the file.
• Creating: The FileStream object creates a nonexistent file upon opening.
• Truncate upon opening: Data in the file is deleted upon opening (before any
data is written).
• Append written data: Data is always written to the end of the file (when any
write method is called).
FITC 09
WWW.COMTASTE.COM
23. Local Persistent data
Persistent data with the File class
var stream:FileStream = new FileStream();
var fileObj:File = File.desktopDirectory.resolvePath( “readme.txt” );
stream. openAsync( file, FileMode.READ );
It opens the readme.txt file on the user’s desktop in read- only mode
DEMO
FITC 09
WWW.COMTASTE.COM
24. What we’ve learned
Persistent data with the File class
Pay attention to Microsoft Vista policy on folders.
if you use the File.applicationDirectory (and all
subdirectories)
you are not able to copy or update files.
If you’re using nested resolvePath() method you need to double
check that folders exist
File.applicationDirectory.resolvePath(quot;Preferencequot;).resolvePath
(quot;preference.txtquot;)
FITC 09
WWW.COMTASTE.COM
25. What we’ve learned
Persistent data with the File class
Using URL reference instead of nativePath makes your app
more cross platform.
If you choose synchronous operations to move files or folders,
you won’t be able to handle custom loaders.
Use FileSeparator constants instead of manually declare the separator
Don’t forget you can encrypt local data
FITC 09
WWW.COMTASTE.COM
26. Local Persistent data
Persistent data with SQLite
AIR also has an embedded version of the SQLite database engine that
makes the runtime truly complete;
SQLite gives developers the opportunity to store data locally offline and to
do it via the same language they use to store data for web applications:
SQL
FITC 09
WWW.COMTASTE.COM
27. Local Persistent data
Persistent data with SQLite
To create a database without creating a connection to it, you use the File class and
its resolvePath method to create a file with a .db file extension:
var dbRef:File;
dbRef = File.applicationStorageDirectory.resolvePath(quot;myDB.dbquot;);
DEMO
FITC 09
WWW.COMTASTE.COM
28. Local Persistent data
Persistent data with SQLite
The SQLConnection class
The class offers methods to create and connect to a database on the
local machine. It can operate in synchronous or asynchronous
execution mode.
Once a connection is established, all the operations on that connection
will use that mode.
It won’t be possible to mix the two execution modes on the same
connection.
FITC 09
WWW.COMTASTE.COM
29. Local Persistent data
Persistent data with SQLite
The SQLConnection class
If you connect to a database in synchronous mode, you have to
enclose all the SQL reading and writing operations in try...catch
constructs to intercept any execution exceptions generated by your
SQL queries.
FITC 09
WWW.COMTASTE.COM
30. Local Persistent data
Persistent data with SQLite
Create a connection to a database file using the SQLConnection class:
try
{
_dbConn.open(dbFile);
}
catch (error:SQLError)
{
trace( quot;Connection error message: quot; + error.message );
}
It creates an synchronous connection to the database. All the operations on this
database file will be executed in a synchronous mode.
DEMO
FITC 09
WWW.COMTASTE.COM
31. Local Persistent data
Persistent data with SQLite
The SQLConnection class
If you connect to a database in an asynchronous mode, you must
use either event listeners (as well as Responders) to receive the
notification that the connection has been established.
Two events will be dispatched:
SQLEvent.OPEN
SQLErrorEvent.ERROR
FITC 09
WWW.COMTASTE.COM
32. Local Persistent data
Persistent data with SQLite
Create a connection to a database file using the SQLConnection class:
private var _dbConn:SQLConnection = new SQLConnection();
_dbConn.openAsync(_myDB);
_dbConn.addEventListener(SQLEvent.OPEN, openHandler);
_dbConn.addEventListener(SQLErrorEvent.ERROR, errorHandler);
It creates an asynchronous connection to the database. All the operations on this
database file will be executed in a asynchronous mode.
FITC 09
WWW.COMTASTE.COM
33. Local Persistent data
Persistent data with SQLite
Instead of using an event listener, you can specify a Responder instance:
private var _dbConn:SQLConnection = new SQLConnection();
_dbConn.openAsync(null, SQLMode.CREATE,
new Responder(connectionHandler, connErrorHandler));
function connectionHandler (sqlEvent:SQLEvent)
{
// Connection and error handling
}
DEMO
FITC 09
WWW.COMTASTE.COM
34. Local Persistent data
Persistent data with SQLite
The SQLMode class
The SQLMode class defines the static constants corresponding to the
access privileges that you can assign to a SQL connection.
SQLMode .CREATE it indicates that you are connecting to a database
with reading and writing privileges, and that if the indicated
database doesn’t exist, it will be created upon connection.
FITC 09
WWW.COMTASTE.COM
35. Local Persistent data
Persistent data with SQLite
The SQLMode class
SQLMode.READ it indicates that you are connecting to a database with
read-only rights; if the database doesn’t exist, an error is returned.
SQLMode.UPDATE it indicates that you are connecting to a database
with reading and writing privileges; if the database doesn’t exist, an
error is returned.
FITC 09
WWW.COMTASTE.COM
36. Local Persistent data
Persistent data with SQLite
The SQLStatement class
This class is associate to a SQLConnection istance and allows to
execute query operations on the database.
The execution mode is inherited by the SQLConnection. Calling
methods on a SQLStatement will require the same programming
model as described above for a SQLConnection.
FITC 09
WWW.COMTASTE.COM
37. Local Persistent data
Persistent data with SQLite
To execute the SQL commands, you need to invoke the execute() method of the
SQLStatement class, which executes the specified SQL string in the text
property of the SQLStatement class:
var SQLStmsqlStatement:SQLStatement = new SQLStatement();
sqlStatementSQLStm.sqlConnection = conn;
var sqlText:String =
quot;CREATE TABLE IF NOT EXISTS students (quot; +
quot; studentId INTEGER PRIMARY KEY AUTOINCREMENT, quot; +
quot; firstName TEXT, quot; +
quot; lastName TEXT, quot; +
quot;)quot;;
sqlStatementSQLStm.text = sqlText;
DEMO
sqlStatementSQLStm.execute();
FITC 09
WWW.COMTASTE.COM
38. Local Persistent data
Persistent data with SQLite
The SQLResult class
The SQLResult class is used by AIR in response to any executed SQL
query.
SQL operations get a SQLResult instance from the getResult() method
of the SQLStatement class received.
The requested data is exposed through the data property. If data is
null, it means that your selection query hasn’t produced any results;
FITC 09
WWW.COMTASTE.COM
39. Local Persistent data
Persistent data with SQLite
The SQLResult class
The SQLResult class has four properties, all of which are read-
only:
complete (Boolean): indicates when all the available rows from the query have
been returned.
data (Array): contains the data returned from the SQL engine at the selection
operation. If the SQL operation isn’t a selection operation or if the selection
hasn’t produced results, this property will be null.
FITC 09
WWW.COMTASTE.COM
40. Local Persistent data
Persistent data with SQLite
The SQLResult class
The SQLResult class has four properties, all of which are read-
only:
rowsAffected: indicates the number of rows that have been edited,
deleted,or added to the SQL operation to which the SQLResult
instance refers. This property is only valid for INSERT, UPDATE, and
DELETE operations; otherwise, it is equal to 0.
DEMO
FITC 09
WWW.COMTASTE.COM
41. Local Persistent data
Persistent data with SQLite
The SQLResult class
The SQLResult class has four properties, all of which are read-
only:
DEMO
FITC 09
WWW.COMTASTE.COM
42. Local Persistent data
Persistent data with SQLite
Using Parameters for SQL queries
Parameters allow you to dynamically update parts of the SQL code at
every execution.
The parameters are defined in the string of SQL text and can be of two
types: ordinal and associated.
The parameters of a SQL query are saved in the parameters object.
FITC 09
WWW.COMTASTE.COM
43. Local Persistent data
Persistent data with SQLite
Using Parameters for SQL queries
Ordinal (unnamed) parameter means that they can be accessed by
order of insertion.
To indicate the insertion of an ordinal parameter, you use the
? character:
// create SQL statement string with unnamed parameter
statement.text = quot; SELECT * FROM ? quot;;
FITC 09
WWW.COMTASTE.COM
44. Local Persistent data
Persistent data with SQLite
Using Parameters for SQL queries
Associated (named) parameters with a label, means that they can be
accessed by name. Parameters associated with a label are defined
using the : and @ parameters, followed by the label itself
// create SQL statement string with unnamed parameter
statement.text = quot; SELECT * FROM :tableName quot;;
statement.text = quot; SELECT * FROM @tableName quot;;
FITC 09
WWW.COMTASTE.COM
45. Local Persistent data
Persistent data with SQLite
Using Parameters for SQL queries
An example of how to use parameters with an associated label:
// create SQL statement string with named parameter using quot;@quot;
statement.text = quot;SELECT * FROM friends WHERE email = @email quot;;
// access parameter and set it to a valid value
statement.parameters[ quot;@emailquot; ] = “m.casario@comtaste.comquot;;
// execute SQL statement
statement.execute();
DEMO
FITC 09
WWW.COMTASTE.COM
46. Local Persistent data
Persistent data with SQLite
Benefits of using Parameters for SQL queries
Using parameters is the only way to control the types of the values
passed to the queries.
As AS3 is a strongly typed language, it takes typed variables values and
assigns them to parameters maintaining the correct type.
Without the use of parameters, the conversion of the values passed
through the SQL query string is carried out implicitly by the SQL
engine.
FITC 09
WWW.COMTASTE.COM
47. Local Persistent data
Persistent data with SQLite
Benefits of using Parameters for SQL queries
By using parameters, you considerably limit the risk of SQL
injections, as the data inserted by the user is processed before
being used and not simply linked to the final SQL string.
FITC 09
WWW.COMTASTE.COM
48. Local Persistent data
Persistent data with SQLite
Using Transaction
What would happen if during the execution of a sequence of
operations that depend on each other, one query fails?
To face these kind of situations, the SQL languages offer “protected”
execution mechanisms called transactions.
FITC 09
WWW.COMTASTE.COM
49. Local Persistent data
Persistent data with SQLite
Using Transaction
It allows you to execute a sequence of SQL operations and, if one of
the queries fails, gives you the opportunity to restore the structure
of and data contained in the db to the state they were in before
starting the transaction.
FITC 09
WWW.COMTASTE.COM
50. Local Persistent data
Persistent data with SQLite
Using Transaction
To start a transaction, you call the begin() method of the
SQLConnection class:
sqlConnection.begin();
To restore the database to initial conditions in case of failure, you have
to call the rollback() method :
sqlConnection.rollback();
FITC 09
WWW.COMTASTE.COM
51. Local Persistent data
Persistent data with SQLite
Using Transaction
If all the operations are successful, you have to complete the
transaction by calling the commit() method of the SQLConnection
class:
// close open transaction
sqlConnection.commit();
DEMO
The SQLite implementation in AIR doesn’t currently allow you to create
nested transactions.
FITC 09
WWW.COMTASTE.COM
52. Optimization
Persistent data with SQLite
Use the autoCompact value to optimize the dimension of the
db:
// open sync connction with autoCompact active
conn.open( dbFile, SQLMode.CREATE, true );
Use the pageSize value indicates the size in bytes of the allocated
memory for the layout of the tables of the database (values from
512 to 32768);
conn.open( dbFile, SQLMode.CREATE, false, 512 );
FITC 09
WWW.COMTASTE.COM
53. What we’ve learned
Persistent data with SQLite
Open a SQLConnection at the application startup (avoid delays when
running statements)
Use only one SQLStatement (with parameters)
Execute the statements within an explicit transaction
Do not concatenate user input into statement text to secure your app
When embedding a SQLite DB into the AIR package the
ApplicationFolder is read-only. So, copy the DB in a different folder
(using the copyTo method)
FITC 09
WWW.COMTASTE.COM
54. Local Persistent data
Persistent data with SQLite
You can use 3 different approaches to access local data:
SQL inline (SQL in View)
Object-Relational Mapping (ORM)
DAO pattern
FITC 09
WWW.COMTASTE.COM
55. Local Persistent data
Persistent data with SQLite
Using the SQL inline (SQL in View) approach
This approach declares the SQL statements (insert, select, update…) as
needed in View components.
It’s a Bad practice because
> it’s not reusable: the logic and data access logic are mixed together
in the same component
> Hard to mantain if you work in team
FITC 09
WWW.COMTASTE.COM
56. Local Persistent data
Persistent data with SQLite
Using the ORM approach
This approach does not require any written SQL statements.
It requires you define a model class definition that can to generate all
the SQL statements required to persist instances of that class.
It’s highly reusable and makes your code easier to read and mantain.
It requires some additional code to write.
FITC 09
WWW.COMTASTE.COM
57. Local Persistent data
Persistent data with SQLite
Using the DAO approach
This approach uses the DAO pattern created by Sun for JEE
enviroments.
FITC 09
WWW.COMTASTE.COM
58. Local Persistent data
Persistent data with SQLite
Using the DAO approach
Data Access Object is an object that provides an abstract interface to
some type of data storage.
It encapsulates the data access logic for one entity.
It’s an ActionScript class tied to an ActionScript Value Object.
FITC 09
WWW.COMTASTE.COM
59. DAO
Persistent data with SQLite
Using the DAO approach
It provides some specific operations without exposing details of the database
public function SalesManager()
{
sqlConnection = SQLManager.getConnection(quot;flexcampquot;);
}
public function getContact(contactId:int):SalesManagerVO
{
return getItem(quot;SELECT * FROM STUDENTS WHERE CONTACT_ID=?,
studentID) as SalesManagerVO;
}
FITC 09
WWW.COMTASTE.COM
60. DAO
Persistent data with SQLite
Using the DAO approach
The benefits of using data access objects is the relatively
simple and rigorous separation between two important
parts of an application which can and should know almost
nothing of each other, and which can be expected to evolve
frequently and independently.
Changing business logic can rely on the same DAO interface,
while changes to persistence logic do not affect DAO clients
as long as the interface remains correctly implemented.
FITC 09
WWW.COMTASTE.COM
63. Local Persistent data
Pouch AIR widget
It’s based on PureMVC architecture
It stores data with SQLite
It uses the DAO approach
FITC 09
WWW.COMTASTE.COM
64. Local Persistent data
Pouch AIR widget
Pouch.mxml is the main application file.
It’s responsable for:
presenting all the Views of the application
creating the facade obj and launch the startup()
FITC 09
WWW.COMTASTE.COM
65. Local Persistent data
Pouch AIR widget
PouchFacade.as is a Singleton class.
It’s responsable for:
Initializing the Model, View and Controller Singletons
Declaring all the notifications launched by the app and
actors
Providing a single point of contact to the application for
registering Commands and notifying Observers
FITC 09
WWW.COMTASTE.COM
66. Local Persistent data
Pouch AIR widget
ModelPrepCommand.as extends a SimpleCommand
class.
It’s added by the globalApplicationStartupCommand
it invokes all the models and data handlers
it creates the PouchModelLocator to store the data in a
singleton class
it creates Proxies (classes that works with data and operations)
FITC 09
WWW.COMTASTE.COM
67. Local Persistent data
Pouch AIR widget
DatabaseStartupCommand.as extends a
SimpleCommand class.Added by the
globalApplicationStartupCommand
it initializes all the data command
each commands interact with the database
it uses the DAO approach
FITC 09
WWW.COMTASTE.COM
68. Local Persistent data
Pouch AIR widget
SQLTodoDAO.as extends the abstact DAO class
created by Eric Femminella
it points to the db and connects to it
it exposes methods to work with the db
FITC 09
WWW.COMTASTE.COM
69. Local Persistent data
Pouch AIR widget
The getTodoList() method of SQLTodoDAO class
uses the TodoSQLStatements to operate all the SQL
statements on the database.
All the SQL statements of the application are handled by the
SQLStatementConfiguration class that load SQL strings from an
external file (SQL.properties)
FITC 09
WWW.COMTASTE.COM
70. Local Persistent data
Pouch AIR widget
How do I access to the DAO object ?
5. From the DatabaseStartupCommand (called at startup)
6. The SelectTodoListCommand is invoked
7. It accesses to the DAO object (SQLTodoDAO)
8. The response data (an ArrayCollection) is put within the
global model locator
9. At the end a notification is dispatched !
FITC 09
WWW.COMTASTE.COM
72. Local Persistent data
Dao-Ext AIR Tool
DAOGen is an AIR Application that automatically
generates Actionscript VO and DAO objects.
It’s based on PureMVC architecture
It’s released as Open Source
FITC 09
WWW.COMTASTE.COM
73. Local Persistent data
Dao-Ext AIR Tool
DAOGen 0.5 allows you to:
Open a SQLite schema
Generate for each table an AS VO and DAO
DAO generated objects (as singleton classes) use the
AS VO as itemClass of the row of the table
The AS VOs are Bindlable
Export all the AS VO and DAO of the tables in a click
Show/hide a log window
Choose the folder to store the generated classes
FITC 09
WWW.COMTASTE.COM
74. Local Persistent data
Dao-Ext AIR Tool
DAOGenerator.mxml is the main application file
In the MainControls.mxml file there are
DAOGen EVENTS
In MainControls.mxml we call the DAOGen main
methods.
DAOGen Mediators sends Notifications and the
DaoGen Facade map it to the relative Command
FITC 09
WWW.COMTASTE.COM
75. Local Persistent data
Dao-Ext AIR Tool
DAOGen Model Locator reister all variabilies as
TableSchema or current selected file or properties as
namespace or fully qualified name
Finally DAOGen Proxy generate AS VO and
DAO objects.
FITC 09
WWW.COMTASTE.COM