SDMPersistence

The Persistence layer stores the application’s state and relevant data on the mobile device using the BlackBerry Persistent Store. The library exposes secure APIs, allowing encrypted data storage and decryption of data.

List of Features

SDMPersistence Public APIs

ISDMPersistence

void storeCache(final ISDMCache cache)
void storeCacheSecured(final ISDMCache cache)
void storePreferencesSecured(final ISDMPreferences preferences)
ISDMCache loadCache(ISDMCache cache, ISDMParser parser)
ISDMCache loadCacheSecured(ISDMCache cache, ISDMParser parser)
void loadPreferencesSecured(final ISDMPreferences preferences)
void storeObject(final long key, final Object object)
Object loadObject(final long key)
void clearCache()
void clearObject(final long key)

Technical Details

To persist data on the BlackBerry platform means storing objects in the storage provided by the platform (Persistent Store). Data is stored as instances of Persistent Objects. A PersistentObject can be any object that implements the Persistable interface. The Persistent Store API allows the implicit persistence of classes, so the following data types automatically implement the Persistable interface and can also be stored in the persistent store:
  • java.lang.Boolean
  • java.lang.Byte
  • java.lang.Character
  • java.lang.Integer
  • java.lang.Long
  • java.lang.Object
  • java.lang.Short
  • java.lang.String
  • java.util.Vector
  • java.util.Hashtable

The implementation only uses the above standard data types when persisting data. This approach is used as a custom persistent class cannot be used by two applications on the same device on the BlackBerry platform, and hence is not suitable for a static library component. In addition, this also avoids any limits on the number of custom persistent classes supported by the platform.

The storage for each application is distinct, because each object in the persistent store is associated with a 64-bit ID (type long). Data is stored in the Persistent Store which is a fast and optimized storage on the platform. The BlackBerry Persistent Store APIs are designed to provide a flexible and robust data storage interface. With the BlackBerry Persistent Store APIs, you can save entire Java® objects to the memory without having to serialize the data first. When the application is started, it can retrieve the Java object from the memory and process the information. No size limit exists on a persistent store; however, the limit for an individual object within the store is 64 KB.

When using standard persistent classes, each application must ensure to remove any persisted objects when the application is removed from the device. The BlackBerry OS does not automatically remove these objects in the same way as it does for custom persistent classes.

The applications have to implement the CodeModuleListener interface, which can react to module addition and removal events. Register the implementation to the CodeModuleManager with the public static void addListener(Application application, CodeModuleListener listener) method. The first parameter is the application whose event listener thread will execute the listener’s code. This means that this application process must be running when the application removal is triggered. This can be achieved by adding an automatically starting background process to the applications and register the listener there.

An alternate entry point with automatic startup has to be added to the application descriptor:

The main method of the application has to be extended with a branch for the background process, which registers itself for code module changes:
public static void main(String[] args) {
  if (args.length >= 1 && args[0].equals("autostartup")) {

  // Background startup of the application. This process registers as the listener for
  // code module life-cycle changes. This will be an always on background process, which
  // will react, when its own module is marked for deletion.
	UninstallSampleApp theApp = new UninstallSampleApp(false);
	CodeModuleManager.addListener(theApp, theApp);

	theApp.requestBackground();
	theApp.enterEventDispatcher();
  } else {
  // Normal startup procedure: create a new instance of the application which will run in
  // the foreground.
	UninstallSampleApp theApp = new UninstallSampleApp(true);
	theApp.enterEventDispatcher();
      }
}
The constructor receives a flag indicating whether it is running in the foreground, so the initialization tasks can be performed according to this information (that is, no UI is needed for the background process).
Implement the listener. It is called every time a module is about to be removed or added to the system, so the events must be filtered according to the module name.
public void moduleDeletionsPending(String[] modules) {
String currentModuleName = ApplicationDescriptor.currentApplicationDescriptor().getModuleName();
SDMConstants constants = SDMConstants.getInstance();
for (int i=0; i < modules.length; i++) {
  if (modules[i].equals(currentModuleName)) {
    PersistentStore.destroyPersistentObject(constants.getId(SDMConstants.SERVICE_DOC_KEY));
    PersistentStore.destroyPersistentObject(constants.getId(SDMConstants.METADATA_KEY));
    PersistentStore.destroyPersistentObject(constants.getId(SDMConstants.DATA_ENTRY_KEY));
    PersistentStore.destroyPersistentObject(constants.getId(SDMConstants.PREFERENCES_KEY));
    break;
    }
}
This example shows how to remove the persisted cache components and the preferences, but any persisted application data can be removed the same way.

The BlackBerry Persistent Store APIs do not provide a relational database model. The application must create an effective object model and manage the relationships between objects as necessary, using indices and hash tables. The keys used to store/load objects must always be handled by the applications. Encryption/decryption is performed with the help of the PersistentContent object. Research In Motion (RIM) must track the use of some sensitive BlackBerry APIs for security and export control reasons. To load your application on a BlackBerry smart phone, the application must be signed using a signature key (provided by RIM). The application owner must order signing keys in order to access the BlackBerry runtime, application and cryptography APIs.

If your application is only signed by RIM provided keys, your application can use the Persistent Store, but there will not be any access control to the persisted data. Any kind of application signed by RIM keys can read and replace your persisted data. If you want to protect your data from other applications, you have to use the BlackBerry Signing Authority Tool to sign the resulting cod file with your private key. If you do not have a private key for signing, you will also need to use the BlackBerry Signing Authority Admin Tool to create a public/private key pair. See the BlackBerry Signature Tool Development Guide and the BlackBerry Signing Authority Tool Administrator Guide for more information. In order for your application to access protected persistent content, the developer must set the used signerID in
ISDMPreferences.PERSISTENCE_ACCESS_CONTROL_SIGNER_ID
preference.

The encryption/decryption in the case of saving a huge number of objects or, for example, a Vector which contains thousands of items can be slow on BlackBerry phones, because the operation must be done on each field of each object. For encryption, the library uses the underlying OS encryption API, no custom API is provided for this purpose. The BlackBerry API offers the PersistentContent class for the applications, which can be used to encrypt/decrypt Strings and byte arrays.