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.
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)
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:
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).
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.
ISDMPreferences.PERSISTENCE_ACCESS_CONTROL_SIGNER_IDpreference.
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.