Skip to main content
Create Account Login Help

Main Menu

  • Home
  • Projects
  • Forums
  • People
  • Java User Groups
  • JCP
Mobile Aerith

Mobile Aerith Demo


This is a photo management demo, where the content to be shown is decided at run time. When an "album" is chosen, thumbnails of the photos in the album are shown. When a thumbnail is chosen, the bigger image is shown. A "camera capture" screen is also available, which simulates taking a picture with phone camera.

In the "Album" screen, click anywhere on it to give it focus. Then use the up or down arrow keys for navigation and the "enter" key for selection. In the "thumbnail" screen, use the arrow keys for navigation and "enter" key for selection. You can click on the "camera" icon in the lower left to go to the "photo capture" screen, where you can click on the "camera" icon in the bottom center to take a picture or the "left arrow" icon to go back to the thumbnail screen. In the thumbnail screen, if you select a thumbnail, you will go to the "image viewing" screen, where you can click on the "left arrow" icon in the lower left to go back to the thumbnail screen.
Note: The midlet code in the DemoBox directory shows a different video in the Camera Capture screen. In the same screen, when a photo is snapped, the midlet code shows the correct image in the lower right corner, whereas here the same image is shown all the time.


JSR 226 Usage

The createImage method of the javax.microedition.m2g.SVGImage class is used to load the svg file. Some of the image resources are loaded from a jar file, using an ExternalResourceHandler. The ExternalResourceHandler interface is implemented when the loading of an external resource, referenced in an SVG document, needs to be customized. The correct URIs of the images to be loaded are not known ahead of time. The image elements in the svg file, have an "xlink:href" attribute defined, with a place holder URI. The correct image name is determined at run time and the ExternalResourceHandler computes the rigth URI and uses ScalableImage's requestCompleted method to load the images.

Animations are defined in the svg file, but are activated programmatically, using the beginElementAt() method of the org.w3c.dom.svg.SVGAnimationElement class. For example as you navigate the "select album" screen, items gain and lose focus. For items gaining focus, animations are declaratively defined that increase font size, scale up images and surrounding rectangles, to give the item more prominence. For items losing focus, the reverse animations are defined, i.e. font sizes decreased, images and rectangles scaled down. Knowing their id, these animations are accessed using org.w3c.dom.Document's getElementById method and then activated.

Many intercative screens are presented, most using elements from the same svg file. Most of the elements in the svg file, have the display attribute set to none, and hence are not rendered. Most screen objects like, ImageViewScreen and ThumbnailsScreen, have methods transitionIn and transitionOut. In the transitionIn, method many svg elements are accessed using org.w3c.dom.Document's getElementById method. Some of these elements from the previous screen, have their "display" attribute set to "none", thus causing them to disappear. Some new elements have their "display" attribute set to "inline", causing them to appear. All this is achieved using the setTrait("display", "none") or setTrait("display", "inline") method of the org.w3c.dom.svg.SVGElement class. Similarly in the transitionOut method, some elements are made to disappear and some screen ending animations are started.

SVG file snippets

    <!-- image element with place holder href attribute -->
    <image id="imageViewImage" width="240" height="230" 
        xlink:class="" display="none"/>
    <!-- focusIn animation, "select album" screen, item: San Francisco ->-
    <!-- increase font size ->-
    <animate id="focusInAnim_menuItem_sanFrancisco" xlink:class="#menuItem_sanFrancisco_text" attributeName="font-size" 
                      values="20;25" begin="2s" dur="0.25s" fill="freeze" />
    <!-- magnify image ->-
    <animateTransform xlink:class="#sanFranciscoImage" attributeName="transform" type="scale" values="1;1.3" 
                      begin="focusInAnim_menuItem_sanFrancisco.begin" dur="0.25s" fill="freeze" />

    <!-- move border rectangle outward ->-
    <animateTransform xlink:class="#albumPrompt" attributeName="transform" type="translate" 
                      values="20,80;20,80" begin="focusInAnim_menuItem_sanFrancisco.begin" dur="0.25s" fill="freeze" />

    <!-- focusOut animation, "select album" screen, item: San Francisco ->-
    <!-- decrease font size ->-
    <animate id="focusOutAnim_menuItem_sanFrancisco"  xlink:class="#menuItem_sanFrancisco_text" attributeName="font-size" 
                      values="25;20" begin="indefinite" dur="0.25s" fill="freeze" />
    <!-- minify image ->-
    <animateTransform xlink:class="#sanFranciscoImage" attributeName="transform" type="scale" values="1.3;1" 
                      begin="focusOutAnim_menuItem_sanFrancisco.begin" dur="0.25s" fill="freeze" />

    <!-- display set to none. Turned on programmatically -->
    <g id="thumbHighlight" transform="translate(600, 73.75)" display="none">

JSR 226 Java code snippets

// =========================================================================
// ExternalResourceHandler implementation (from
// =========================================================================
 * In this implementation of requestResource, we assume that all resources
 * are embedded into the jar file, so we simply do a getResourceAsStream.
 * @param scalableImage the image referencing the requested resource.
 * @param uri the uri for the requested resource.
public void requestResource(final ScalableImage scalableImage, final String uri) {
// Compute correct URI
String trimmedURItmp = uri;
String prefix = "";
if (uri != null && uri.startsWith(prefix)) {
    trimmedURItmp = uri.substring(prefix.length());
final String trimmedURI = trimmedURItmp;
// Inputstream obtained from modified URI and matched with original URI
// The stream is consumed asynchronously
scalableImage.requestCompleted(uri, MobileAerith.class.getResourceAsStream
                                                       ("/" + trimmedURI));

// Snippets from
 * Called to transition the screen out of the scene.
 * @return the time, in seconds, which the out transition takes.
public float transitionOut() {
    // Animation accessed knowing id
    SVGAnimationElement transitionOut =
        (SVGAnimationElement) getElementById(THUMBS_VIEW_ID_ANIM_END);
    // animation started
    return 0.5f;
 * Called to transition the screen into the scene.
 * @param delay before the transition should start.
public void transitionIn(final float delay) {
    // Animation accessed knowing id
    SVGAnimationElement transitionIn =
        (SVGAnimationElement) getElementById(THUMBS_VIEW_ID_ANIM_BEGIN);
    // animation started

// Snippets from
 * Called to transition the screen into the scene.
 * @param delay before the transition should start.
public void transitionIn(float delay) {
    // Access elements of interest from document, using their id
    SVGAnimationElement transition = (SVGAnimationElement) getElementById(IMAGE_VIEW_ID_ANIM_BEGIN);
    SVGElement titleText = getElementById(IMAGE_VIEW_ID_TITLE);
    SVGElement image = getElementById(IMAGE_VIEW_ID_IMAGE);
    SVGAnimationElement loadingAnim = (SVGAnimationElement) getElementById(IMAGE_VIEW_ID_LOADING_ANIM);
    SVGElement loading = getElementById(IMAGE_VIEW_ID_LOADING_GRAPHICS);
    SVGElement uploading = getElementById(IMAGE_VIEW_ID_UPLOADING);
    SVGElement networkingStatus = getElementById(IMAGE_VIEW_ID_NETWORKING_STATUS);
    SVGElement rightIcon = getElementById(IMAGE_VIEW_ID_RIGHT_ICON);
    SVGElement leftIcon = getElementById(IMAGE_VIEW_ID_LEFT_ICON);
    // Do not render rightIcon
    rightIcon.setTrait("display", "none");
    // but render left icon
    leftIcon.setTrait("display", "inline");
    // set title text
    titleText.setTrait("#text", title);
    // set image attributes
    width = image.getFloatTrait("width");
    height = image.getFloatTrait("height");
    x = image.getFloatTrait("x");
    y = image.getFloatTrait("y");
    // do not display image now
    image.setTrait("display", "none");
    // start loading animation
    // render loading icon
    loading.setTrait("display", "inline");
    // but, do not render uploading icon
    uploading.setTrait("display", "none");
    // but render network status icon
    networkingStatus.setTrait("display", "inline");
    // delayed beginning of transition animation

            // get image and render it
 * Called to transition the screen out of the scene.
 * @return the time, in seconds, which the out transition takes.
public float transitionOut() {
    // Access screen ending animation element
    SVGAnimationElement transition = (SVGAnimationElement) getElementById(IMAGE_VIEW_ID_ANIM_END);
    // Trigger animation
    // Restore image attributes
    SVGElement image = getElementById(IMAGE_VIEW_ID_IMAGE);
    image.setFloatTrait("width", width);
    image.setFloatTrait("height", height);
    image.setFloatTrait("x", x);
    image.setFloatTrait("y", y);
    return 0f;

Source files

All the sources and resource files for the MobileAerith demo are available within the DemoBox project under the MobileAerith directory. The SVG directory contains the relevant svg files and Netbeans directory contains the relevant netbeans project files.

Note: When running the MobileAerith midlet in WTK or Netbeans, set the Java Heap to be atleast 4M, in order to avoid OutOfMemory exceptions. Here are instructions on how to set this in Netbeans or WTK. is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.