CLDC Platform and Utilities

Overview

This category contains the packages that provide core language functionality for your applications. The packages include standard packages provided in Java™ Micro Edition (Java ME) plus packages provided by RIM® that enhance the standard packages.

Note: This document contains code samples that demonstrate the use of some of the classes in this category. The code samples are simplified in order to better demonstrate the classes; for example, they have little error handling. The code samples are not meant for production use.

Standard packages [back to top]

The standard packages in the CLDC Platform and Utilities category can be divided into the following types:

CLDC 1.1 core packages

Packages: java.lang, java.lang.ref, java.util

These packages are part of JSR 139, Connected Limited Device Configuration version 1.1. These packages provide the core set of APIs for developing applications on resource-constrained wireless devices, such as BlackBerry® devices.

JSR 139 also includes java.io and javax.microedition.io, which are described in The Core I/O Connection Framework category overview.

Click for code sample: Create a Vector of Calendar objects using an Enumeration and a Long wrapper

public Vector makeCalendars(Vector dates) 
{
    if (dates == null) 
    {
        // handle null parameter here 
    }

    Vector calendars = new Vector();
    Enumeration list = dates.elements();
    Object element;
             
    while( list.hasMoreElements() )
    {
        element = list.nextElement();

        if(element instanceof Long)
        {
            long millis = ((Long)element).longValue();
            Calendar calendar = Calendar.getInstance();
            calendar.setTime( new Date( millis ) );
            calendars.addElement(calendar);
        }
    }
    return calendars;
}

java.lang.ref.WeakReference gives you the ability to access an object while still making the object eligible for garbage collection. If an object is referred to only by weak references, it is eligible for garbage collection. For an object to not be marked as eligible for garbage collection, it must be reachable from the root set by a chain of strong references.

One use for weak references is holding a reference in one application to another application. In general, you need to reference another application object only while the application it represents is running. If you hold a strong reference to the application object, the garbage collector is prevented from freeing the object’s memory (along with the many objects that it recursively references) even after the application exits (assuming you are strongly reachable from the root set). Holding a weak reference to the application object makes the application object eligible to be garbage collected when the application exits (assuming there is not a chain of strong references from the root set to the object).

Click for code sample: Use a weak reference to an application object to determine if the application is still running

import java.lang.ref.WeakReference;
import net.rim.device.api.system.Application;
import net.rim.device.api.ui.component.Dialog;
import net.rim.blackberry.api.phone.AbstractPhoneListener;
import net.rim.blackberry.api.phone.Phone;

/**
 * When a PhoneListener is registered, its registration persists even
 * after the application that registered it exits. This particular 
 * implementation uses the Application object to display a dialog when 
 * a call fails. Since nothing meaningful can be done after the 
 * application exits, a weak reference is held to the Application object, 
 * allowing it to be garbage collected after it exits. When we detect that
 * the application has exited then we also remove ourselves as a PhoneListener.
 */
public class WeakReferenceSample extends AbstractPhoneListener
{

    private final WeakReference _applicationRef;

    public WeakReferenceSample(Application application)
    {
        this._applicationRef = new WeakReference(application);
    }

    public void callFailed(int callId, int reason)
    {
        final Application application = this.getApplication();
        if (application != null)
        {
            final Runnable runnable = new ShowCallFailedDialogRunnable(reason);
            application.invokeLater(runnable);
        }
    }

    public Application getApplication()
    {
        final Application application = (Application) this._applicationRef.get();
        if (application != null && application.isAlive())
        {
            return application;
        }
        else
        {
            Phone.removePhoneListener(this);
            return null;
        }
    }

    private static class ShowCallFailedDialogRunnable implements Runnable
    {
        private final String _message;

        public ShowCallFailedDialogRunnable(int reason)
        {
            this._message = "A call just failed for reason " + reason;
        }

        public void run()
        {
            Dialog.alert(this._message);
        }
    }
}

java.util.Timer and java.util.TimerTask provide support for background processing. Each Timer object has one background thread that processes TimerTasks sequentially. These tasks can be scheduled to occur immediately, after a delay, at a particular time, or repeatedly at a given interval.

Click for code sample: Use the standard Timer and TimerTask classes in a BlackBerry application to notify an object on a non-object thread about the user clicking the trackball

public class MyScreen extends MainScreen 
{
    private Timer _timer;

    public MyScreen() 
    {
        setTitle("Timer Demo");
        _timer = new Timer();
    }

    public void onTrackballClick() 
    {
        System.out.println("The trackball was clicked.");
    }

    protected boolean navigationClick(int status, int time) 
    {
        _timer.schedule(new ClickTask(), 0);
        return super.navigationClick(status, time);
    }

    private class ClickTask extends TimerTask 
    {
        public void run() 
        {
            onTrackballClick();
        }
    }
}

J2ME Web Services packages

Packages: java.rmi, javax.microedition.xml.rpc, javax.xml.namespace, javax.xml.parsers, javax.xml.rpc, org.xml.sax, org.xml.sax.helpers

These packages are part of JSR 172, J2ME Web Services Specification. These packages provide basic support for Java ME devices, such as a BlackBerry device, to act as a web service client using standard programming interfaces.

For more information about Java ME web services, see the Sun web services whitepaper.

RIM provided packages [back to top]

RIM provides APIs that complement Java Community Process APIs. Consider taking advantage of the optimizations and specializations available in the RIM provided complementary packages. For example, you can use RIM provided collection classes, such as BigVector or UnsortedReadableList, instead of the standard Vector class.

Applications that use the RIM provided APIs are not portable to devices that are not BlackBerry devices. If portability to other types of devices is important to you, use only the standard Java ME packages. Otherwise, take advantage of the functionality available in the RIM provided packages.

In some cases, RIM provides classes that exist in Java SE but are not provided (or only partially provided) in standard Java ME. For example:

The RIM provided packages in the CLDC Platform and Utilities category can be divided into the following types:

Web service and XML-related packages

These packages extend the core support for web services and XML processing.

Packages: net.rim.device.api.xml, net.rim.device.api.xml.jaxp, net.rim.device.api.xml.parsers

The net.rim.device.api.xml package provides constants for use in processing WBXML, which is a binary form of XML suitable for use in wireless applications.

The net.rim.device.api.xml.jaxp package provides support for XML processing and supplements org.xml.sax by adding extensions to the standard helper classes, adding classes for parsing WBXML, and extending the standard JSR 172 javax.xml.parsers.SAXParser with RIMSAXParser. When parsing XML using SAX, you can use the standard SAXParser class. If you want additional parsing methods, you can cast SAXParser to RIMSAXParser.

The net.rim.device.api.xml.parsers package provides support for XML parsing and supplements javax.xml.parsers by adding DocumentBuilder and DocumentBuilderFactory.

Click for code sample: Parse an XML file using DocumentBuilder

/**
 * This method parses an XML file into a tree and returns the root.
 * @param feedContents The contents of the XML file.
 * @return The root of the tree representation of the XML file.
 */
private Node openRSS(String feedContents)
{
    try
    {
        //Convert the XML string to an input stream.
        InputStream input = new ByteArrayInputStream(feedContents.getBytes("UTF-8"));

        //Build a document based on the XML file.
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document document = builder.parse(input);

        //Normalize the root element of the XML document. This ensures
        //that all Text nodes under the root node are put into a "normal"
        //form, which means that there are neither adjacent Text nodes nor
        //empty Text nodes in the document.
        //See Node.normalize().
        Element root = document.getDocumentElement();
        root.normalize();

        //Close the input stream.
        input.close();

        return root;
    }
    catch (Exception e)
    {
        System.out.println(e.toString());
        return null;
    }
}

Click for code sample: Parse an XML stream using SAX

/**
 * Parse input stream using an XMLWriter.
 * @param input the input stream
 * @return byte[] representation of XML
 */
public byte[] parseInputStream(byte[] input)
{
    ByteArrayInputStream bis = new ByteArrayInputStream(input);
    bis.reset();

    ByteArrayOutputStream xmlout = new ByteArrayOutputStream();
    SAXParserImpl saxparser = new SAXParserImpl();
    XMLWriter xmlWriter = new XMLWriter(xmlout);

    try
    {
        saxparser.parse(bis, xmlWriter);
    }
    catch(SAXException e)
    {
        Dialog.alert("Parsing exception: " + e.getMessage());
        return null;
    }
    catch(Exception e)
    {
        Dialog.alert("Exception: " + e.toString());
        return null;
    }

    return xmlout.toByteArray();
}

For a complete application that processes an XML file using DocumentBuilder, see the XMLDemo sample application that is provided with the BlackBerry® Java® Development Environment and with the BlackBerry® JDE Plug-in for Eclipse.

Collections-related packages

Packages: net.rim.device.api.collection, net.rim.device.api.collection.util, net.rim.device.api.util

Standard Java ME packages provide support for only the Hashtable, Stack, and Vector collection types. RIM provides support for additional collection types, with specific optimizations and specializations.

Collection type Description
Standard collections
Hashtable collection that maps keys to values
Stack collection of objects that are accessed last-in, first-out (LIFO)
Vector growable array of objects
RIM-provided collections
IntHashtable
IntIntHashtable
IntLongHashtable
LongHashtable
LongHashtableCollection
LongIntHashtable
ToIntHashtable
ToLongHashtable
optimized hashtable implementations; these classes are in net.rim.device.api.util
LongStack stack of long values
BigVector
BigIntVector
BigLongVector
ByteVector
IntVector
LongVector
SimpleSortingIntVector
SimpleSortingVector
vectors that are optimized to support insert and delete operations
BigSortedReadableList
IntSortedReadableList
LongSortedReadableList
SortedReadableList
lists that are optimized to maintain a large collection of sorted elements
BigUnsortedReadableList
UnsortedReadableList
lists that are optimized to maintain a large collection of unsorted elements
SparseList list where the existing elements keep their assigned index

net.rim.device.api.util contains several collections for storing primitive types, such as int, byte, and long. These collections supplement the standard collections in java.util. Using the RIM provided classes to store the primitive types is faster and more memory-efficient than storing wrapper objects in standard java.util collections.

For example, net.rim.device.api.util.IntVector has the same methods as java.util.Vector but stores primitive int values instead of Object references. No conversions between int and Integer are necessary. This makes IntVector a better choice for storing int values than java.util.Vector; it is faster and uses less memory. It is also fully synchronized, like java.util.Vector. Other classes in net.rim.device.api.util include:

Click for code sample: Use IntVector to store a list of 10 high scores, with the highest scores at the lowest indices

public class HighScores 
{
    private IntVector _scores;

    public HighScores() 
    {
        _scores = new IntVector(11);  // allow for one extra in the vector
        _scores.insertElementAt(0,0); // seed the first element        
    }

    public void add(int score) 
    {
        if (_scores.contains(score)) 
        {
            return; // already there
        }

        boolean isAdded = false;
        for (int i = 0; i < _scores.size(); i++) 
        {
            if (_scores.elementAt(i) < score) 
            {
                _scores.insertElementAt(score, i);
                isAdded = true;
                break;
            }
        }

        if (!isAdded) 
        {
            _scores.addElement(score);   // if new score was not added above,
                                         // add it to the end
        }

        if (_scores.size() == 11) 
        {
            _scores.removeElementAt(10); // remove the last element because 
        }                                // it was pushed off the top 10 list
    }

    public int getHighScore() 
    {
        return _scores.firstElement();
    }

    public int[] getHighScores() 
    {
        return _scores.toArray();
    }
}

Click for code sample: Create a vector that sorts records based on date

final static class SortableVector extends SimpleSortingVector
{
    SortableVector()
    {
        setSortComparator( new Comparator() 
        {
            public int compare( Object o1, Object o2 ) 
            {
                OrderRecord r1 = (OrderRecord) o1;
                OrderRecord r2 = (OrderRecord) o2;
                
                if ( r1.getDate() < r2.getDate()) 
                {
                    return -1;
                }
                
                if ( r1.getDate() > r2.getDate()) 
                {
                    return 1;
                }
                
                return 0;
            }
        });    
    }
}

Some of the RIM provided collections are provided in net.rim.device.api.collection.util. They implement the interfaces in net.rim.device.api.collection, such as Collection and CollectionListener.

Click for code sample: Add an object to a Vector and alert Collection listeners about the addition

public void addObject(Object object) 
{
    // Add a new Object to the Vector if not null
    if (object == null) 
    {
        // handle null parameter here 
    }
    _vector.addElement(object);
	
    // We want to let collection listeners know 
    // that the collection has changed
    int numListeners = _listeners.size();
	
    CollectionListener cl;
    for (int i=0; i<numListeners; i++)
    {
        cl = (CollectionListener)_listeners.elementAt(i);
        cl.elementAdded(this, object);
    }
}

Math and other utilities

Packages: net.rim.device.api.math, net.rim.device.api.util

These packages extend the core Java ME language.

The net.rim.device.api.math package consists of two classes (Fixed32 and VecMath) that provide fixed-point math routines that enhance standard math support, including matrix manipulation, trigonometric, and numeric conversion methods.

In addition to providing collection classes (described above), the net.rim.device.api.util package provides other utility methods and interfaces that can be useful in BlackBerry device applications. Included is support for type-length encoded files, enumerations, comparison methods for collection objects, string manipulations, and basic numeric operations.

Click for code sample: Use net.rim.device.api.util.StringUtilities.append() to append a String and a StringBuffer to a StringBuffer

public StringBuffer fullName(StringBuffer firstName, StringBuffer lastName) 
{
    firstName = StringUtilities.append(firstName, " ", 0, 1);
    return StringUtilities.append(firstName, lastName);
}

Copyright 1999-2010 Research In Motion Limited. 295 Phillip Street, Waterloo, Ontario, Canada, N2L 3W8. All Rights Reserved.
Copyright 1993-2003 Sun Microsystems, Inc. 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
Copyright 2002-2003 Nokia Corporation All Rights Reserved.
Java is a trademark or registered trademark of Sun Microsystems, Inc. in the US and other countries.