Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Data Storage
Version: 6.0
Development Guide
Published: 2010-11-30
SWD-1232721-1130030151-001
Contents
1 Data storage overview................................................................................................................................................................ 4
Data storage features..................................................................................................................................................................... 4
Considerations for choosing a data storage approach...................................................................................................... 5
Storage locations............................................................................................................................................................................ 5
Access to memory................................................................................................................................................................... 6
7 Managing data............................................................................................................................................................................. 58
Best practice: Minimizing memory use........................................................................................................................................ 58
Removing sensitive data................................................................................................................................................................ 58
Using the Garbage Collector......................................................................................................................................................... 59
Full garbage collection on a BlackBerry device.................................................................................................................. 59
Managing low memory................................................................................................................................................................... 60
Identifying low memory availability on a BlackBerry device............................................................................................. 60
Backing up data.............................................................................................................................................................................. 60
9 Provide feedback......................................................................................................................................................................... 63
10 Glossary......................................................................................................................................................................................... 64
12 Legal notice.................................................................................................................................................................................. 66
Development Guide Data storage overview
Features File system SQLite Persistent store Runtime store Record store
database
Data format Any Relational Java® object Java object Serialized
database file
Storage locations Application External Application Application Application
storage, external media card, storage storage storage
media card, built- built-in media
in media storage storage
Maximum storage limit Size of partitions Size of Available Available Differs according
the user has partitions the application application to BlackBerry®
access to user has storage storage Device Software
access to version
BlackBerry Device 4.2 or later 5.0 or later All 3.6 or later All
Software support (FileConnection
API)
Persists across device Yes Yes Yes No Yes
restarts
4
Development Guide Storage locations
Features File system SQLite Persistent store Runtime store Record store
database
Applications can share Yes Yes Yes Yes Yes
data
Storage locations
Different BlackBerry® devices support different places to store data. The following storage locations are available, depending
on the BlackBerry device model:
Application storage This storage location is internal to the BlackBerry device. It contains the operating system, the
BlackBerry® Java® Virtual Machine, and an internal file system. Application storage is also called
flash memory and on-board memory. Application storage is the only place on a BlackBerry device
from which applications can be run. All BlackBerry devices have application storage.
External media card This storage location is a microSD card that BlackBerry device users can insert to extend the amount
storage of storage on their devices. It is optional and removable. A FAT file system is mounted on the media
card. MicroSD cards are supported on all devices running BlackBerry® Device Software 4.2 or later,
with the exception of the BlackBerry® 8700 Series.
Built-in media storage This storage location is an embedded multimedia card called eMMC. It is not removable. A FAT
file system is mounted on the built-in media card. Built-in media storage is also called internal
media memory and on-board device memory. Built-in media storage is included on some
BlackBerry device models.
5
Development Guide Storage locations
Access to memory
The BlackBerry® Java® environment is designed to prevent applications from causing problems accidentally or maliciously in
other applications or on the BlackBerry device. Applications can write only to the BlackBerry device memory that the BlackBerry®
Java® Virtual Machine uses; they cannot access the virtual memory or the persistent storage of other applications (unless they
are specifically granted access to do so). Custom applications can only access persistent storage or user data, or communicate
with other applications, through specific APIs. Research In Motion must digitally sign applications that use certain BlackBerry
APIs to provide an audit trail of applications that use sensitive APIs.
6
Development Guide Storing files in the file system
You can access the file system on internal storage and external media card storage:
Internal storage Internal storage is application storage or built-in media storage. All devices have internal storage. To
access internal storage, use the path file:///store. For example,
FileConnection fc = (FileConnection)Connector.open("file:///Store")
External storage You can access external media card storage only on devices with microSD cards. To access external media
card storage, use the path file:///SDCard. For example,
FileConnection fc = (FileConnection)Connector.open("file:///SDCard")
Files created by your application are not automatically deleted when your application is uninstalled.
Devices that have built-in media storage have a file system partition called System. In BlackBerry Device Software 5.0 and later,
the system partition is reserved for system use and is read-only. In BlackBerry Device Software versions earlier than 5.0, the
system partition is read/write. You can access this partition with the path file:///system.
7
Development Guide Code sample: Creating a file
{
public static void main(String[] args)
{
CreateFolderApp app = new CreateFolderApp();
app.setAcceptEvents(false);
try
{ // the final slash in the folder path is required
FileConnection fc = (FileConnection)Connector.open("file:///SDCard/
testfolder/");
// If no exception is thrown, the URI is valid but the folder may not exist.
if (!fc.exists())
{
fc.mkdir(); // create the folder if it doesn't exist
}
fc.close();
}
catch (IOException ioe)
{
System.out.println(ioe.getMessage() );
}
}
}
8
Development Guide Code sample: Writing text to a file
{
System.out.println(ioe.getMessage() );
}
}
}
9
Development Guide Code sample: Reading sections of a binary file
import net.rim.device.api.ui.*;
import net.rim.device.api.io.*;
import javax.microedition.io.file.*;
import javax.microedition.io.*;
import java.io.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
public HomeScreen()
{
setTitle("Random File Access Sample");
try
{
FileConnection fc = (FileConnection)Connector.open("file:///SDCard/
test.gif");
boolean bFileExists = fc.exists();
if (!bFileExists)
{
Dialog.alert("Cannot find specified GIF file.");
System.exit(0);
}
DataInputStream in = fc.openDataInputStream();
byte[] widthBytes = new byte[2];
byte[] heightBytes = new byte[2];
if ( in instanceof Seekable )
{
((Seekable) in).setPosition(6);
in.read(widthBytes,0,2);
((Seekable) in).setPosition(8);
in.read(heightBytes,0,2);
}
10
Development Guide Code sample: Displaying the path to the video folder using System.getProperty()
in.close();
fc.close();
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
public GetVidDir()
{
HomeScreen hs = new HomeScreen();
pushScreen(hs);
}
}
11
Development Guide Code sample: Retrieving a list of mounted roots
public ListMountedRoots()
{
pushScreen(new HomeScreen());
}
}
12
Development Guide Storing data in SQLite databases
Note: There are other ways to use SQLite databases on a BlackBerry device. They are BlackBerry® WebWorks™ applications,
HTML5, and Google® Gears™. For more information, see docs.blackberry.com.
13
Development Guide Security of SQLite databases
14
Development Guide Security of SQLite databases
You can also use the code signing key to share access to the database with other specific applications. When multiple applications
are signed with the same key, they all have access to the database.
To specify that a database is encrypted and signed, you have a choice of two identical constructors. The following code sample
encrypts and protects an existing database. First, the code sample retrieves the code signing key from a file called XYZ. It then
encrypts and signs the database. If the database is already encrypted, the method exits gracefully.
CodeSigningKey codeSigningKey =
CodeSigningKey.get(CodeModuleManager.getModuleHandle( "SQLiteDemo" ), "XYZ");
try
{
DatabaseFactory.encrypt(uri, new DatabaseSecurityOptions(codeSigningKey));
}
catch(DatabaseException dbe)
{
errorDialog("Encryption failed - " + dbe.toString());
}
public CreateEncryptedDatabase()
{
pushScreen(new CreateEncryptedDatabaseScreen());
}
}
15
Development Guide Performance of SQLite databases
setTitle(title);
add(new RichTextField("Creating an encrypted database called " +
"MyEncryptedDatabase.db on the SDCard."));
try
{
URI myURI = URI.create("file:///SDCard/Databases/SQLite_Guide/" +
"MyEncryptedDatabase.db");
DatabaseSecurityOptions dbso = new DatabaseSecurityOptions(true);
d = DatabaseFactory.create(myURI,dbso);
d.close();
}
catch ( Exception e )
{
System.out.println( e.getMessage() );
e.printStackTrace();
}
}
}
16
Development Guide Performance of SQLite databases
17
Development Guide Creating and deleting SQLite databases
Character encoding
The Database API uses UTF-8 character encoding. Java® stores strings internally in UTF-8, so you don't need to do any encoding
or conversion.
The SQLite statement PRAGMA is not supported in the Database API, so you can't use PRAGMA ENCODING to set another
encoding. You must use UTF-8 supported characters in your SQLite database.
18
Development Guide Creating and deleting SQLite databases
public CreateDatabase()
{
pushScreen(new CreateDatabaseScreen());
}
}
3. Create the screen for the application by extending the MainScreen class. Provide a constructor for the new class. In the
constructor, create the title for the screen with a LabelField object and display it by invoking the setTitle() method.
Invoke the add() method to display a text field on the screen.
class CreateDatabaseScreen extends MainScreen
{
public CreateDatabaseScreen()
{
LabelField title = new LabelField("SQLite Create Database Sample",
LabelField.ELLIPSIS |
LabelField.USE_ALL_WIDTH);
setTitle(title);
add(new RichTextField("Creating a database called " +
"MyTestDatabase.db on the SDCard."));
}
}
19
Development Guide Creating and deleting SQLite databases
4. Create a URI that represents the database file by invoking the static create() method of the URI class. Invoke the
create() method of the DatabaseFactory class to create the database that corresponds to the URI that you created.
This creates an SQLite® database on the microSD card of the BlackBerry® device. If you do not specify a full path, the
database is created in a folder named after your application.
try
{
URI myURI = URI.create("file:///SDCard/Databases/SQLite_Guide/" +
"MyTestDatabase.db");
Database db = DatabaseFactory.create(myURI);
}
catch ( Exception e )
{
System.out.println( e.getMessage() );
e.printStackTrace();
}
5. When you are finished using the database, it is good practice to close it.
db.close();
public CreateDatabase()
{
pushScreen(new CreateDatabaseScreen());
20
Development Guide Creating and deleting SQLite databases
}
}
public CreateDatabaseSchema()
{
pushScreen(new CreateDatabaseSchemaScreen());
}
}
21
Development Guide Creating and deleting SQLite databases
st.prepare();
st.execute();
st.close();
d.close();
}
catch ( Exception e )
{
System.out.println( e.getMessage() );
e.printStackTrace();
}
}
}
22
Development Guide Working with SQLite databases
public DeleteDatabase()
{
pushScreen(new DeleteDatabaseScreen());
}
}
23
Development Guide Working with SQLite databases
4. If the statement returns a result set, retrieve the result set by iterating over the returned cursor row by row. Do this using
the Cursor class, which works in all circumstances but is forward-only. For birectional cursor movement, but only for small
result sets, use BufferedCursor.
Using transactions
SQLite® statements always run in transactions. If the statement runs successfully, the transaction is automatically committed.
If the statement fails, the transaction is rolled back.
By default, a separate transaction is created for each SQLite statement, which is less efficient than running multiple statements
in one transaction. You can usually improve performance by explicitly specifying transactions for groups of statements. You can
run multiple statements in one transaction using Database.beginTransaction() and
Database.commitTransaction() around groups of statements.
}
}
24
Development Guide Working with SQLite databases
try
{
URI myURI = URI.create("file:///SDCard/Databases/SQLite_Guide/" +
"MyTestDatabase.db");
d = DatabaseFactory.open(myURI);
d.beginTransaction();
Statement st = d.createStatement("UPDATE People SET Age=7 " +
"WHERE Name='Sophie'");
st.prepare();
st.execute();
st.reset();
st = d.createStatement("UPDATE People SET Age=4 " +
"WHERE Name='Karen'");
st.prepare();
st.execute();
d.commitTransaction();
st.close();
d.close();
}
catch ( Exception e )
{
System.out.println( e.getMessage() );
e.printStackTrace();
}
}
}
25
Development Guide Working with SQLite databases
Here's an example of the same statement, except that explicit numbers are specified for the parameters:
The getFormalName() method converts a parameter index to an SQL parameter name. For getFormalName() to be able
to return the parameter name, you must provide a name in the query. For example, when you call getFormalName(1), the
statement "SELECT * FROM T WHERE a = :a" returns :a. When parameters such as a question mark (?) are used as placeholders,
getFormalName() cannot return a parameter name. For example, getFormalName(1) will not return the name for the
parameter in this statement: "SELECT * FROM T WHERE a = ?"
26
Development Guide Working with SQLite databases
setTitle(title);
while (names.hasMoreElements())
{
Integer iAge = (Integer)ages.nextElement();
String strName = (String)names.nextElement();
st.bind(1,iAge.intValue());
st.bind(2,strName);
st.execute();
st.reset();
}
st.close();
d.close();
}
catch ( Exception e )
{
System.out.println( e.getMessage() );
e.printStackTrace();
}
}
}
27
Development Guide Working with SQLite databases
{
public static void main(String[] args)
{
ParameterizedInsert theApp = new ParameterizedInsert();
theApp.enterEventDispatcher();
}
public ParameterizedInsert()
{
pushScreen(new ParameterizedInsertScreen());
}
}
class ParameterizedInsertScreen extends MainScreen
{
Database d;
public ParameterizedInsertScreen()
{
LabelField title = new LabelField("SQLite Insert Data " +
"Schema Sample",
LabelField.ELLIPSIS |
LabelField.USE_ALL_WIDTH);
setTitle(title);
add(new RichTextField("Attempting to insert data into " +
"MyTestDatabase.db on the SDCard."));
try
{
URI myURI = URI.create("file:///SDCard/Databases/SQLite_Guide/" +
"MyTestDatabase.db");
d = DatabaseFactory.open(myURI);
while (names.hasMoreElements())
{
String strName = (String)names.nextElement();
Integer iAge = (Integer)ages.nextElement();
st.bind(1,strName);
st.bind(2,iAge.intValue());
st.execute();
st.reset();
}
28
Development Guide Working with SQLite databases
st.close();
d.close();
}
catch ( Exception e )
{
System.out.println( e.getMessage() );
e.printStackTrace();
}
}
}
public InsertData()
29
Development Guide Working with SQLite databases
{
pushScreen(new InsertDataScreen());
}
}
}
catch ( Exception e )
{
System.out.println( e.getMessage() );
e.printStackTrace();
}
}
}
30
Development Guide Working with SQLite databases
public ReadData()
{
pushScreen(new ReadDataScreen());
}
}
st.prepare();
net.rim.device.api.database.Cursor c = st.getCursor();
Row r;
int i = 0;
while(c.next())
{
r = c.getRow();
i++;
add(new RichTextField(i + ". Name = " + r.getString(0) +
" , " +
"Age = " + r.getInteger(1)));
}
if (i==0)
{
add(new RichTextField("No data in the People table."));
}
st.close();
d.close();
31
Development Guide Working with SQLite databases
catch ( Exception e )
{
System.out.println( e.getMessage() );
e.printStackTrace();
}
}
}
public DeleteData()
{
pushScreen(new DeleteDataScreen());
}
}
32
Development Guide Working with SQLite databases
}
catch ( Exception e )
{
System.out.println( e.getMessage() );
e.printStackTrace();
}
}
}
public UpdateData()
{
pushScreen(new UpdateDataScreen());
}
}
33
Development Guide Working with SQLite databases
}
catch ( Exception e )
{
System.out.println( e.getMessage() );
e.printStackTrace();
}
}
}
public ListTables()
{
pushScreen(new ListTablesScreen());
}
}
34
Development Guide
LabelField.USE_ALL_WIDTH);
setTitle(title);
add(new RichTextField("Attempting to list tables in " +
"MyTestDatabase.db on the SDCard."));
try
{
URI myURI = URI.create("file:///SDCard/Databases/SQLite_Guide/" +
"MyTestDatabase.db");
d = DatabaseFactory.open(myURI);
Statement st = d.createStatement("SELECT name FROM " +
" sqlite_master " +
"WHERE type='table'" +
"ORDER BY name");
st.prepare();
net.rim.device.api.database.Cursor c = st.getCursor();
Row r;
int i = 0;
while(c.next())
{
r = c.getRow();
i++;
add(new RichTextField(i + ". Table: " + r.getString(0)));
}
if (i==0)
{
add(new RichTextField("There are no tables " +
" in the MyTestDatabase database."));
}
st.close();
d.close();
}
catch ( Exception e )
{
System.out.println( e.getMessage() );
e.printStackTrace();
}
}
}
35
Development Guide SQLite sample application
Overview
The SQLite® database sample application demonstrates how to create a persistent relational database that is stored on the
BlackBerry® device and how to change the entries in the database.
The database contains two tables that are called Category and DirectoryItems. The DirectoryItems table contains
items that simulate entries in a business directory list. Each DirectoryItem entry also contains a CategoryID field that
must match a category_id entry in the Category table (for instance, Category.category_id is a foreign key for
DirectoryItem.categoryID).
The sample application displays the entries in the tables as a collapsible tree structure with Category entries as parent nodes
and DirectoryItem entries as child nodes of the Category nodes that they are associated with. The sample application
provides menu items for adding a new category or directory item and for changing or deleting the directory item.
This sample application uses APIs that are designed to be secure.The application must be signed before it can be run. For more
information about code signing, see the BlackBerry Signing Authority Tool Administration Guide.
36
Development Guide SQLite sample application
Featured interfaces
net.rim.device.api.Database
The Database interface represents the database. This interface provides methods for changing a database on the BlackBerry
device, including methods for creating SQL statements to add, delete, or update records in the database and methods for
committing and canceling transactions in the database. This interface also provides methods for setting and retrieving the
database's metadata.
To create the database, you can use one of the methods of the DatabaseFactory class.
The sample application uses this interface to create statements to insert, delete, and update records in the database.
net.rim.device.api.Statement
The Statement interface represents an SQL statement. You can use the Statement interface to retrieve, add, delete, or
change entries in the database.
net.rim.device.api.Cursor
The Cursor interface provides methods for traversing a result set that is retrieved using the Statement object. A
Statement object creates the Cursor object using the Statement.getCursor() method as part of its query process.
Therefore, a Cursor is always associated with a specific query.
Featured classes
net.rim.device.api.database.Row
37
Development Guide SQLite sample application
The Row class represents a row in a result set that a SELECT query returns.
This class provides methods for retrieving column indices in the Row object and the values stored in the Row object's columns.
You create this class using the Cursor.getRow() method.
net.rim.device.api.database.DatabaseFactory
The DatabaseFactory class provides methods for creating, opening, configuring, and deleting a new or existing
Database. Configuration options include persistent or nonpersistent storage and encryption.
To create a new database, you must use the DatabaseFactory.openOrCreate() method or the
DatabaseFactory.create() method. If you have already created the database, the
DatabaseFactory.openOrCreate() method returns a reference to the database.
Create the database on a media card instead of in device memory. Only certain BlackBerry® devices support storing an SQLite
database in device memory.
38
Development Guide Storing objects persistently
The storage for each application is distinct because each object in the persistent store is associated with a 64-bit ID (type long).
39
Development Guide Performance of the persistent store
40
Development Guide Performance of the persistent store
41
Development Guide Creating a persistent store
42
Development Guide Working with the persistent store
import net.rim.device.api.system.PersistentObject;
import net.rim.device.api.system.PersistentStore;
2. Invoke setContents() on a PersistentObject. This method replaces the existing content with the new content.
3. To save the new content to the persistent store, invoke commit().
String[] userinfo = {username, password};
synchronized(store) {
store.setContents(userinfo);
store.commit();
}
4. To use a batch transaction to commit objects to the persistent store, invoke PersistentStore.getSynchObject
(). This method retrieves the persistent store monitor that locks the object.
a. Synchronize on the object.
b. Invoke commit() as necessary. If any commit in the batch fails, the entire batch transaction fails.
5. To commit a monitor object separately from a batch transaction, invoke forceCommit() while synchronizing the monitor
object.
43
Development Guide Working with the persistent store
synchronized(store) {
String[] currentinfo = (String[])store.getContents();
if(currentinfo == null) {
Dialog.alert(_resources.getString(APP_ERROR));
}
else {
currentusernamefield.setText(currentinfo[0]);
currentpasswordfield.setText(currentinfo[1]);
}
}
44
Development Guide Working with the persistent store
45
Development Guide Storing objects nonpersistently
Share data between two For example, an application suite could be made up of multiple applications, all of which use
applications data that is pushed to the device. One of the applications receives all the push data and
shares it with the other applications by temporarily storing the data in the runtime store.
The runtime store could also be used to set up communication between a listener (such as
a PushListener) and a running application.
Store a reference to an object For example, an application that allows a BlackBerry device user to add and remove an
for later use ApplicationMenuItem could use the runtime store to store a reference to an
ApplicationMenuItem it has registered. After the application is closed and re-opened,
the ApplicationMenuItem can be accessed and unregistered.
Implement system-wide An application might require one or more singleton objects to be accessed from within the
singletons application itself or by other applications.
46
Development Guide Add an object to the runtime store
47
Development Guide Retrieve the runtime store
48
Development Guide Code sample: Storing a String in the runtime store
public RuntimeSet()
{
RuntimeStore rts = RuntimeStore.getRuntimeStore();
long ID = 0x60ac754bc0867248L; //just a unique ID - generate any way you want
rts.put(ID, "Shared Message");
}
}
public RuntimeGet()
{
RuntimeStore rts = RuntimeStore.getRuntimeStore();
long ID = 0x60ac754bc0867248L; //just a unique ID - generate any way you want
String msg = (String)rts.get(ID);
pushScreen(new HomeScreen(msg));
49
Development Guide Code sample: Creating a singleton using the RuntimeStore API
class MySingleton {
private static MySingleton _instance;
private static final long GUID = 0xab4dd61c5d004c18L;
// constructor
MySingleton() {}
RuntimeStore.getRuntimeStore().put(GUID, singleton);
_instance = singleton;
}
}
return _instance;
}
}
50
Development Guide Storing data in the record store
BlackBerry® Device Software version Maximum individual record store size Maximum total record store size
(cumulative for all applications)
Earlier than 4.1 64 KB 64 KB
4.1 to 4.5 64 KB Available device memory
4.6 or later 512 KB Available device memory
51
Development Guide Retrieve a record from a record store
2. Invoke addRecord().
int id = store.addRecord(_data.getBytes(), 0, _data.length());
52
Development Guide Code sample: Storing and retrieving data with the record store
Code sample: Storing and retrieving data with the record store
This example uses the RMS API to store and retrieve high scores for a game. In the example, high scores are stored in separate
records, and sorted when necessary using a RecordEnumeration.
import javax.microedition.rms.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
/**
* A class used for storing and showing game scores.
*/
public class RMSGameScores
implements RecordFilter, RecordComparator
{
/*
* The RecordStore used for storing the game scores.
*/
private RecordStore recordStore = null;
/*
* The player name to use when filtering.
*/
public static String playerNameFilter = null;
/*
* Part of the RecordFilter interface.
*/
public boolean matches(byte[] candidate)
throws IllegalArgumentException
{
// If no filter set, nothing can match it.
if (this.playerNameFilter == null) {
return false;
53
Development Guide Code sample: Storing and retrieving data with the record store
try {
int score = inputStream.readInt();
name = inputStream.readUTF();
}
catch (EOFException eofe) {
System.out.println(eofe);
eofe.printStackTrace();
}
catch (IOException eofe) {
System.out.println(eofe);
eofe.printStackTrace();
}
return (this.playerNameFilter.equals(name));
}
/*
* Part of the RecordComparator interface.
*/
public int compare(byte[] rec1, byte[] rec2)
{
// Construct DataInputStreams for extracting the scores from
// the records.
ByteArrayInputStream bais1 = new ByteArrayInputStream(rec1);
DataInputStream inputStream1 = new DataInputStream(bais1);
ByteArrayInputStream bais2 = new ByteArrayInputStream(rec2);
DataInputStream inputStream2 = new DataInputStream(bais2);
int score1 = 0;
int score2 = 0;
try {
// Extract the scores.
score1 = inputStream1.readInt();
score2 = inputStream2.readInt();
}
catch (EOFException eofe) {
System.out.println(eofe);
eofe.printStackTrace();
}
catch (IOException eofe) {
System.out.println(eofe);
eofe.printStackTrace();
}
// Sort by score
if (score1 < score2) {
return RecordComparator.PRECEDES;
}
54
Development Guide Code sample: Storing and retrieving data with the record store
/**
* The constructor opens the underlying record store,
* creating it if necessary.
*/
public RMSGameScores()
{
//
// Create a new record store for this example
//
try {
recordStore = RecordStore.openRecordStore("scores", true);
}
catch (RecordStoreException rse) {
System.out.println(rse);
rse.printStackTrace();
}
}
/**
* Add a new score to the storage.
*
* @param score the score to store.
* @param playerName the name of the play achieving this score.
*/
public void addScore(int score, String playerName)
{
//
// Each score is stored in a separate record, formatted with
// the score, followed by the player name.
//
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream outputStream = new DataOutputStream(baos);
try {
// Push the score into a byte array.
outputStream.writeInt(score);
// Then push the player name.
outputStream.writeUTF(playerName);
}
catch (IOException ioe) {
System.out.println(ioe);
ioe.printStackTrace();
}
55
Development Guide Code sample: Storing and retrieving data with the record store
byte[] b = baos.toByteArray();
// Add it to the record store
try {
recordStore.addRecord(b, 0, b.length);
}
catch (RecordStoreException rse) {
System.out.println(rse);
rse.printStackTrace();
}
}
/**
* A helper method for the printScores methods.
*/
private void printScoresHelper(RecordEnumeration re)
{
try {
while(re.hasNextElement()) {
int id = re.nextRecordId();
ByteArrayInputStream bais = new ByteArrayInputStream
(recordStore.getRecord(id));
DataInputStream inputStream = new DataInputStream(bais);
try {
int score = inputStream.readInt();
String playerName = inputStream.readUTF();
System.out.println(playerName + " = " + score);
}
catch (EOFException eofe) {
System.out.println(eofe);
eofe.printStackTrace();
}
}
}
catch (RecordStoreException rse) {
System.out.println(rse);
rse.printStackTrace();
}
catch (IOException ioe) {
System.out.println(ioe);
ioe.printStackTrace();
}
}
/**
* This method prints all of the scores sorted by game score.
*/
public void printScores()
{
try {
// Enumerate the records using the comparator implemented
// above to sort by game score.
RecordEnumeration re = recordStore.enumerateRecords(null, this,
56
Development Guide Code sample: Storing and retrieving data with the record store
true);
printScoresHelper(re);
}
catch (RecordStoreException rse) {
System.out.println(rse);
rse.printStackTrace();
}
}
/**
* This method prints all of the scores for a given player,
* sorted by game score.
*/
public void printScores(String playerName)
{
try {
// Enumerate the records using the comparator and filter
// implemented above to sort by game score.
RecordEnumeration re = recordStore.enumerateRecords(this, this,
true);
printScoresHelper(re);
}
catch (RecordStoreException rse) {
System.out.println(rse);
rse.printStackTrace();
}
}
57
Development Guide Managing data
Managing data 7
The BlackBerry® Java® Virtual Machine manages memory usage on the BlackBerry device. The BlackBerry JVM allocates memory,
performs garbage collection, and automatically swaps data between random access memory and application storage.
BlackBerry® Device Software provides a number of tools to help you manage data in your applications. These tools provide ways
to back up data, remove sensitive data, remove data that is no longer needed, and free up memory when needed.
The MemoryCleanerListener interface has two methods, cleanNow() and getDescription(). The cleanNow() method
is invoked by the memory cleaner when a user configurable event occurs. The memory cleaner passes an event parameter when
it calls cleanNow() to indicate the event that initiated the memory clean request. The getDescription() method is
invoked by the memory cleaner if the memory cleaner must display information about the applications that are registered cleaners.
This functionality is required, for example, on the Memory Cleaning option screen.
58
Development Guide Using the Garbage Collector
59
Development Guide Managing low memory
Backing up data
The BlackBerry® Device Manager provides a backup and restore tool that a BlackBerry device user can use to save BlackBerry
device data to a file on a computer and to restore data to the BlackBerry device.
With the Synchronization API, you can create applications that integrate with the BlackBerry® Desktop Manager or BlackBerry®
Enterprise Server to back up data from a BlackBerry device.
The Synchronization API is implemented in the net.rim.device.api.synchronization package.
When an application uses the Synchronization API, the BlackBerry Desktop Manager can back up and restore the application
database at the same time as other BlackBerry device databases. You can use the Synchronization API to create data archives
or to populate application databases the first time the BlackBerry device connects to the BlackBerry device user's computer.
60
Development Guide Backing up data
To synchronize data to remote data sources, you must build the synchronization logic into your application. Most applications
send data to a server-side application using standard HTTP or TCP/IP protocols over the wireless network and the Internet or
an intranet. You can use XML APIs to generate and parse XML-formatted data to send and receive over the wireless network.
However, your client-side and server-side applications must read and write the data properly and acknowledge successful
transmission of the data.
Your BlackBerry device application might connect to an application on a computer to send the data over a USB connection with
the Synchronization API and the BlackBerry Desktop Manager. In this case, the desktop application must be able to read the
data from your BlackBerry device application through an add-in task for the BlackBerry Desktop Manager. The BlackBerry device
user must manually execute the synchronization by running the BlackBerry Desktop Manager add-in, which notifies the
application on the BlackBerry device to send the data to the computer application. You can also write data to the desktop
application using the native USB protocols.
To enable an application to back up data, you can implement the following Synchronization interfaces and use the
SyncManager class to register your application for synchronization.
Interface Description
SyncConverter Converts data between the SyncObject format that is required on the BlackBerry device
and the serialized format that is required on the computer.
SyncCollection Represents the collection of synchronization objects for an application.
SyncObject Represents an object that can be backed up and restored.
The following sample applications are included with the BlackBerry® Java® Development Environment: SyncDemo,
OTASyncDemo, and OTABackupRestoreDemo.
To back up and restore a small amount of data such as application configuration options, you do not have to implement all of
these interfaces. Instead, you can extend the SyncItem class and implement its abstract methods. The SyncItem class
implements the SyncCollection, SyncConverter, and SyncObject interfaces for you. For more information, see Backup
and restore small amounts of data using SyncItem.
61
Development Guide Find more information
62
Development Guide Provide feedback
Provide feedback 9
To provide feedback on this deliverable, visit www.blackberry.com/docsfeedback.
63
Development Guide Glossary
Glossary 10
application storage
Application storage is internal to the BlackBerry device. It contains the operating system, BlackBerry® JVM, and an internal
file system. Application storage is also known as flash memory and onboard memory. Applications on a BlackBerry device
can be run only from the application storage. All BlackBerry devices have application storage.
eMMC
embedded MultiMediaCard
FAT
File Allocation Table
flash memory
The flash memory is an internal file system on a BlackBerry device that stores application data and user data.
JSR
Java® Specification Request
MIDP
Mobile Information Device Profile
SQL
Structured Query Language
UTF-8
8-bit UCS/Unicode Transformation Format
64
Development Guide Document revision history
Date Description
29 November 2010 Added topic: Using foreign key constraints
26 November 2010 Widespread edits
16 August 2010 Initial version
65
Development Guide Legal notice
Legal notice 12
©2010 Research In Motion Limited. All rights reserved. BlackBerry®, RIM®, Research In Motion®, and related trademarks, names,
and logos are the property of Research In Motion Limited and are registered and/or used in the U.S. and countries around the
world.
Java is a trademark of Oracle America, Inc. SQLite is a trademark of Hipp, Wyrick & Company, Inc. All other trademarks are the
property of their respective owners.
This documentation including all documentation incorporated by reference herein such as documentation provided or made
available at www.blackberry.com/go/docs is provided or made accessible "AS IS" and "AS AVAILABLE" and without condition,
endorsement, guarantee, representation, or warranty of any kind by Research In Motion Limited and its affiliated companies
("RIM") and RIM assumes no responsibility for any typographical, technical, or other inaccuracies, errors, or omissions in this
documentation. In order to protect RIM proprietary and confidential information and/or trade secrets, this documentation may
describe some aspects of RIM technology in generalized terms. RIM reserves the right to periodically change information that
is contained in this documentation; however, RIM makes no commitment to provide any such changes, updates, enhancements,
or other additions to this documentation to you in a timely manner or at all.
This documentation might contain references to third-party sources of information, hardware or software, products or services
including components and content such as content protected by copyright and/or third-party web sites (collectively the "Third
Party Products and Services"). RIM does not control, and is not responsible for, any Third Party Products and Services including,
without limitation the content, accuracy, copyright compliance, compatibility, performance, trustworthiness, legality, decency,
links, or any other aspect of Third Party Products and Services. The inclusion of a reference to Third Party Products and Services
in this documentation does not imply endorsement by RIM of the Third Party Products and Services or the third party in any way.
EXCEPT TO THE EXTENT SPECIFICALLY PROHIBITED BY APPLICABLE LAW IN YOUR JURISDICTION, ALL CONDITIONS,
ENDORSEMENTS, GUARANTEES, REPRESENTATIONS, OR WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
WITHOUT LIMITATION, ANY CONDITIONS, ENDORSEMENTS, GUARANTEES, REPRESENTATIONS OR WARRANTIES OF
DURABILITY, FITNESS FOR A PARTICULAR PURPOSE OR USE, MERCHANTABILITY, MERCHANTABLE QUALITY, NON-
INFRINGEMENT, SATISFACTORY QUALITY, OR TITLE, OR ARISING FROM A STATUTE OR CUSTOM OR A COURSE OF DEALING
OR USAGE OF TRADE, OR RELATED TO THE DOCUMENTATION OR ITS USE, OR PERFORMANCE OR NON-PERFORMANCE
OF ANY SOFTWARE, HARDWARE, SERVICE, OR ANY THIRD PARTY PRODUCTS AND SERVICES REFERENCED HEREIN, ARE
HEREBY EXCLUDED. YOU MAY ALSO HAVE OTHER RIGHTS THAT VARY BY STATE OR PROVINCE. SOME JURISDICTIONS
MAY NOT ALLOW THE EXCLUSION OR LIMITATION OF IMPLIED WARRANTIES AND CONDITIONS. TO THE EXTENT
PERMITTED BY LAW, ANY IMPLIED WARRANTIES OR CONDITIONS RELATING TO THE DOCUMENTATION TO THE EXTENT
THEY CANNOT BE EXCLUDED AS SET OUT ABOVE, BUT CAN BE LIMITED, ARE HEREBY LIMITED TO NINETY (90) DAYS FROM
THE DATE YOU FIRST ACQUIRED THE DOCUMENTATION OR THE ITEM THAT IS THE SUBJECT OF THE CLAIM.
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW IN YOUR JURISDICTION, IN NO EVENT SHALL RIM BE LIABLE
FOR ANY TYPE OF DAMAGES RELATED TO THIS DOCUMENTATION OR ITS USE, OR PERFORMANCE OR NON-
PERFORMANCE OF ANY SOFTWARE, HARDWARE, SERVICE, OR ANY THIRD PARTY PRODUCTS AND SERVICES REFERENCED
HEREIN INCLUDING WITHOUT LIMITATION ANY OF THE FOLLOWING DAMAGES: DIRECT, CONSEQUENTIAL, EXEMPLARY,
INCIDENTAL, INDIRECT, SPECIAL, PUNITIVE, OR AGGRAVATED DAMAGES, DAMAGES FOR LOSS OF PROFITS OR REVENUES,
FAILURE TO REALIZE ANY EXPECTED SAVINGS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, LOSS OF
BUSINESS OPPORTUNITY, OR CORRUPTION OR LOSS OF DATA, FAILURES TO TRANSMIT OR RECEIVE ANY DATA, PROBLEMS
66
Development Guide Legal notice
ASSOCIATED WITH ANY APPLICATIONS USED IN CONJUNCTION WITH RIM PRODUCTS OR SERVICES, DOWNTIME COSTS,
LOSS OF THE USE OF RIM PRODUCTS OR SERVICES OR ANY PORTION THEREOF OR OF ANY AIRTIME SERVICES, COST OF
SUBSTITUTE GOODS, COSTS OF COVER, FACILITIES OR SERVICES, COST OF CAPITAL, OR OTHER SIMILAR PECUNIARY
LOSSES, WHETHER OR NOT SUCH DAMAGES WERE FORESEEN OR UNFORESEEN, AND EVEN IF RIM HAS BEEN ADVISED
OF THE POSSIBILITY OF SUCH DAMAGES.
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW IN YOUR JURISDICTION, RIM SHALL HAVE NO OTHER
OBLIGATION, DUTY, OR LIABILITY WHATSOEVER IN CONTRACT, TORT, OR OTHERWISE TO YOU INCLUDING ANY LIABILITY
FOR NEGLIGENCE OR STRICT LIABILITY.
THE LIMITATIONS, EXCLUSIONS, AND DISCLAIMERS HEREIN SHALL APPLY: (A) IRRESPECTIVE OF THE NATURE OF THE
CAUSE OF ACTION, DEMAND, OR ACTION BY YOU INCLUDING BUT NOT LIMITED TO BREACH OF CONTRACT, NEGLIGENCE,
TORT, STRICT LIABILITY OR ANY OTHER LEGAL THEORY AND SHALL SURVIVE A FUNDAMENTAL BREACH OR BREACHES
OR THE FAILURE OF THE ESSENTIAL PURPOSE OF THIS AGREEMENT OR OF ANY REMEDY CONTAINED HEREIN; AND (B)
TO RIM AND ITS AFFILIATED COMPANIES, THEIR SUCCESSORS, ASSIGNS, AGENTS, SUPPLIERS (INCLUDING AIRTIME
SERVICE PROVIDERS), AUTHORIZED RIM DISTRIBUTORS (ALSO INCLUDING AIRTIME SERVICE PROVIDERS) AND THEIR
RESPECTIVE DIRECTORS, EMPLOYEES, AND INDEPENDENT CONTRACTORS.
IN ADDITION TO THE LIMITATIONS AND EXCLUSIONS SET OUT ABOVE, IN NO EVENT SHALL ANY DIRECTOR, EMPLOYEE,
AGENT, DISTRIBUTOR, SUPPLIER, INDEPENDENT CONTRACTOR OF RIM OR ANY AFFILIATES OF RIM HAVE ANY LIABILITY
ARISING FROM OR RELATED TO THE DOCUMENTATION.
Prior to subscribing for, installing, or using any Third Party Products and Services, it is your responsibility to ensure that your
airtime service provider has agreed to support all of their features. Some airtime service providers might not offer Internet browsing
functionality with a subscription to the BlackBerry® Internet Service. Check with your service provider for availability, roaming
arrangements, service plans and features. Installation or use of Third Party Products and Services with RIM's products and services
may require one or more patent, trademark, copyright, or other licenses in order to avoid infringement or violation of third party
rights. You are solely responsible for determining whether to use Third Party Products and Services and if any third party licenses
are required to do so. If required you are responsible for acquiring them. You should not install or use Third Party Products and
Services until all necessary licenses have been acquired. Any Third Party Products and Services that are provided with RIM's
products and services are provided as a convenience to you and are provided "AS IS" with no express or implied conditions,
endorsements, guarantees, representations, or warranties of any kind by RIM and RIM assumes no liability whatsoever, in relation
thereto. Your use of Third Party Products and Services shall be governed by and subject to you agreeing to the terms of separate
licenses and other agreements applicable thereto with third parties, except to the extent expressly covered by a license or other
agreement with RIM.
Certain features outlined in this documentation require a minimum version of BlackBerry® Enterprise Server, BlackBerry® Desktop
Software, and/or BlackBerry® Device Software.
The terms of use of any RIM product or service are set out in a separate license or other agreement with RIM applicable thereto.
NOTHING IN THIS DOCUMENTATION IS INTENDED TO SUPERSEDE ANY EXPRESS WRITTEN AGREEMENTS OR WARRANTIES
PROVIDED BY RIM FOR PORTIONS OF ANY RIM PRODUCT OR SERVICE OTHER THAN THIS DOCUMENTATION.
67
Development Guide Legal notice
Canada
Published in Canada
68