Just An Application

March 18, 2010

MIDP 3.0 On Maemo 5: A TabbedPane And Some Lists … Again

Filed under: Java, JME, LCDUI, Maemo, MIDlets, MIDP, MIDP3, MIDP3LCDUI, Mobile Java, Qt — Tags: , , , , , , , — Simon Lewis @ 1:43 pm

It’s that MIDlet again. This time running on the Maemo5 emulator. The implementation code is identical to the Symbian version with vanilla Qt being used as the LCDUI back-end.





Copyright (c) 2010 By Simon Lewis. All Rights Reserved.

Advertisements

March 17, 2010

MIDP 3.0 On Symbian: A TabbedPane And Some Lists

Filed under: Java, JME, LCDUI, MIDP, MIDP3, MIDP3LCDUI, Nokia, Qt, Symbian — Tags: , , , , , , , — Simon Lewis @ 9:02 am

Here’s the SimpleTabbedPaneMIDlet again, this time running on the N97 emulator. The only difference between this and the Android version is that the LCDUI backend is implemented using vanilla Qt rather than Android widgets.




Copyright (c) 2010 By Simon Lewis. All Rights Reserved.

March 5, 2010

MIDP 3.0 On Android: Notifications

Filed under: Android, Java, JME, LCDUI, MIDP, MIDP3, MIDP3LCDUI — Tags: , , , , , , — Simon Lewis @ 12:04 pm

Notifications are another new feature in MIDP 3 for which there is some usefully equivalent functionality in Android, namely Notifications ! or more specifically

    android.app.Notification

and

    android.app.NotificationManager

Below is a very simplistic MIDlet which demonstrates the basic use of Notifications. Of course, in reality a MIDlet would actually be doing something which would cause it emit Notifications. In the case of the Missed Call Notification type that I am using in the example, it might be doing some actual telephony, although that is a bit unlikely since as far as I am aware neither JSR 253 nor 304 have ever been shipped. Anyway, here’s the MIDlet



import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Notification;
import javax.microedition.lcdui.NotificationListener;
import javax.microedition.lcdui.NotificationType;

import javax.microedition.midlet.MIDlet;

public final class SimpleNotificationMIDlet
                   extends
                       MIDlet
                   implements
                       NotificationListener,
                       Runnable
{
    public void destroyApp(boolean ignore)
    {
    }
	
    public void startApp()
    {
        primaryDisplay = Display.getDisplays(0)[0];
        new Thread(this).start();
    }
	
    //
	
    public void notificationDismissed(Notification theNotification)
    {
        primaryDisplay.setCurrent(new Alert("Notification Dismissed", null, null, AlertType.INFO));
    }
	
    public void notificationSelected(Notification theNotification)
    {
        primaryDisplay.setCurrent(new Alert("Notification Selected", null, null, AlertType.INFO));
    }
	
    public void notificationTimeout(Notification theNotification)
    {
        primaryDisplay.setCurrent(new Alert("Notification Timeout", null, null, AlertType.INFO));
    }
	
    public void run()
    {
        try
        {
            missedCall("+44 1234567890");
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
	
    private void missedCall(String theCaller)
    {
        Notification n = new Notification(NotificationType.CALL);
		
        n.setListener(this);
        n.setLabel("Missed call from " + theCaller);
        n.post(true, 60000);
    }
	
    //
	
    private Display	primaryDisplay;
}


Here’s the Notification immediately after it has been posted. For a couple of seconds it takes over the entire status bar.

Here’s the Notification once the status bar re-appears. For the misleadingly named Call NotificationType, which is actually the Missed Call NotificationType, I am using the generic Missed Call icon as shipped with Android.

Here’s the expanded view which is shown when the status bar is pulled down

And that’s it really. At this point the user can either click on the Notification or ignore it, and a MIDlet can either update the Notification or remove it.

In the example MIDlet, if you select the Notification in the expanded view, this happens

If you hit the clear button in the expanded view, this happens

If you just sit and wait then eventually this happens.

There is one feature of Android Notifications which is not demonstrated above, and that is the ability to associate a number with a Notification, in which case you get this

There is no API for doing this in MIDP 3, but the specification does explicitly permit an implementation to group together Notifications of the same type. so in theory a single Android Notification could be used to represent a number of MIDP 3 Notifications, with the number of Notifications being displayed in the icon, as above.

In practice there is no way for the implementation to know the intended semantics of any single MIDP 3 Notification and consequently whether it would be appropriate to group it with other Notifications of ostensibly the same type, or whether doing so is simply going to end-up badly confusing the user. There is also an issue with how to handle the display of a group of MIDP 3 Notifications in the expanded view of a single Android Notification. Although the view is customizable this is done using something RemoteViews which have fairly circumscribed functionality.


Copyright (c) 2010 By Simon Lewis. All Rights Reserved.

March 1, 2010

MIDP 3.0 On Android: A TabbedPane And Some Lists

Filed under: Android, Java, JME, LCDUI, MIDP, MIDP3 — Tags: , , , , , , — Simon Lewis @ 11:59 am

I first wrote about running MIDlets on Android a bit over two years ago (see here). At that point there was one fairly fundamental obstacle to running MIDlets on Android which I didn’t mention at the time, which was the presence in Android of stubbed out versions of some javax.lcdui classes. As there were also no publicly available functioning ClassLoaders the only way to get a MIDlet using LCDUI to run was to modify it at the source level to use a shadow version of LCDUI. That is what I did, but it is also why I didn’t do anything more.

Since then the mysterious javax.lcdui class stubs have disappeared and publicly available ClassLoaders have appeared. Although these implementation level obstacles have been removed, there are still some impedance mismatches between MIDP and Android. At a high-level there are differences in the provisioning, security, and application models. At a very low-level there is the use of Dex and Dalvik. At an intermediate level there is, for example, the contrast between the use of static resources to build Android application UIs and the more or less dynamic construction of UI elements using LCDUI.

Having said that, if you have a 99.9% pure Java MIDP 3 implementation, which happily I do, it is possible to get MIDP 3 MIDlets running on Android 2.1, albeit with a judicious amount of hacking,

This is a very simple MIDlet which uses the new MIDP 3 TabbedPane


import javax.microedition.lcdui.Choice;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.List;
import javax.microedition.lcdui.TabbedPane;

import javax.microedition.midlet.MIDlet;

public final class SimpleTabbedPaneMIDlet
                   extends
                       MIDlet
                   implements
                       CommandListener
{
    public void destroyApp(boolean ignore)
    {
    }
	
    public void startApp()
    {
        List exclusive = new List(
                                 "Exclusive", 
                                 Choice.EXCLUSIVE, 
                                 new String[] { "One", "Two", "Three", "Four", "Five" }, 
                                 null);
        List implicit   = new List(
                                  "Implicit",  
                                  Choice.IMPLICIT,  
                                  new String[] { "Foo", "Bar", "Baz" }, 
                                  null);
        List multiple  = new List(
                                  "Multiple",  
                                  Choice.MULTIPLE,  
                                  new String[] { "Up", "Down", "Left", "Right" }, 
                                  null);
		
       exclusive.setCommandListener(this);
       implicit.setCommandListener(this);
       multiple.setCommandListener(this);
		
       TabbedPane tp = new TabbedPane("TabbedPane", true, false);
		
       tp.addTab(exclusive, null);
       tp.addTab(implicit, null);
       tp.addTab(multiple, null);
       Display.getDisplays(0)[0].setCurrent(tp);
    }
	
    //
	
    public void commandAction(Command theCommand, Displayable theDisplayable)
    {
        System.out.println("SimpleTabbedPaneMIDlet.commandAction(" + theCommand + ", " + theDisplayable + ")" );
    }
}


and this is what it looks like running on the emulator.



This MIDlet illustrates quite nicely the difference between constructing a UI in Android and in MIDP. At first glance it looks as though the class

       android.widget.TabHost

is a straight correlate of

    javax.microedition.lcdui.TabbedPane

However, if you simply construct an instance of TabHost programatically using the one arg constructor, and then and start trying to add tabs to it, it doesn’t work. You get some helpful exceptions, and once you’ve worked out how to fix those, a very unhelpful NullPointerException, at which point there is nothing for it except to resort to the source code of TabHost.

It turns out that it is possible to create a functioning instance of TabHost programatically, see above, but the expectation is that it will actually be created by inflating it from a layout resource, which is fair enough, it is certainly a lot easier to do it that way.


Copyright (c) 2010 By Simon Lewis. All Rights Reserved.

December 16, 2009

What’s New In MIDP 3.0: Redux – LCDUI – Command Layout

Filed under: Java, JME, LCDUI, MIDP, MIDP3, MIDP3Issues, MIDP3LCDUI — Tags: , , , , , , — Simon Lewis @ 10:49 am

Original Post

Changes Since Proposed Final Draft

javax.microedition.lcdui.Display

The following has been added to the end of the Exact Placement of Commands section
of the Display class documentation.

On each callback of CommandLayoutPolicy.onCommandLayout(Displayable), implementation MUST first disassociate Command and Menu
with their respective previous placements. At the beginning of each callback of CommandLayoutPolicy.onCommandLayout(Displayable) method,
Displayable.getCommand(int) or Displayable.getMenu(int) will return null for every placement.

As I said in my original post

  1. The specification does not contain an explicit definition of the state of a Display’s placements when the onLayout(Displayable)[sic] method is called, that is, whether Commands and/or Menus previously placed on the current Display by the Displayable are still present or whether all Commands and/or Menus must be explicitly placed each time the method is called. This makes implementing the method perhaps more interesting than it ought to be.

Well now it does. Every time you layout a Displayable’s Commands you start with a clean slate.

javax.microedition.lcdui.Displayable

The setCommand(Command,int) method no longer throws an IllegalArgumentException when the placement

is associated with a placement that does not support commands

possibly because it is actually not possible for a placement not to support Commands.

It is hard to be sure because the Item.setCommand(Command,int) method will apparently still throw an IllegalArgumentException when the placement

is associated with a placement that does not support commands

The CommandLayoutPolicy Example

The CommandLayoutPolicy now looks like this. Actually it doesn’t because I have re-formatted it. In Chrome, Firefox and Safari the formatting is all over the place, as it is in the PDF version.


class MyCanvas extends Canvas implements CommandLayoutPolicy {
    MyCanvas() {
        setCommandLayoutPolicy(this);
    }

    void sort(Command[] commands, int[] positions) {
        // sort the commands in the correct order depending on the positions available.
        // Implementation can use Display's getCommandPreferredPlacements to get the recommended 
        // placement for each Command.
    }
 
    public void onCommandLayout(Displayable displayable) {
        Display display = displayable.getCurrentDisplay();
      
        final int border = Display.SOFTKEY_BOTTOM;
     
        int[] positions = display.getExactPlacementPositions(border);
     
        int numOfPositions = positions.length;
           
        Command[] cmd = displayable.getCommands();
     
        sort(cmd, positions);
     
        if (cmd.length <= numOfPositions) {
            for (int i = 0; i < cmd.length; ++i) {
                displayable.setCommand(cmd[i], positions[i]);
            }
        } else {
            for (int i = 0; i < numOfPositions ; ++i) {
                displayable.setCommand(cmd[i], positions[i]);
            }
       
            int[] menuSupportedPlmts = display.getMenuSupportedPlacements();
            if( menuSupportedPlmts != null ) {
                Menu options = new Menu("More", null, null);
                // first add the remaining commands in the Menu
                for (int i = numOfPositions; i < cmd.length; ++i) {
                    options.append(cmd[i]);
                }
                // Get the first preferred placement of Menu
                int menuPlmt = menuSupportedPlmts[0];
                // check if this placement already occupied by Command
                if( displayable.getCommand(menuPlmt) != null ) {
                    //add the existing Command in Menu, otherwise the existing
                    // Command will be removed from the Displayable according to
                    //setMenu() method
                    //
                    options.append(displayable.getCommand(menuPlmt));
                }
                displayable.setMenu(options, menuPlmt);                    
            }
        }    
    }
 }

This is an improvement on the previous version which was flat-out broken. Note that it still doesn’t check the return value of the call to Display.getExactPlacementPositions(int).

Issues

The changes above are the only ones that I have found. Of the original issues I raised they address two if you are being charitable.

  1. What is the state of the Displayable with respect to Command layout when the CommandLayoutPolicy.onCommandLayout(Displayable) method is invoked ? It is a clean slate

  2. Can there be placements which do not support Commands ? Probably not.

Everything else is still up for grabs. Developers, assuming there are going to be any, are going to have to try it and see what happens, and then hope it happens the same way everywhere, which is the past has not been a guaranteed recipe for success.

Possibly if somebody had attempted to write a real-world example for the specification the Command layout feature itself would have been better specified. The example provided effectively does no more than provide the existing default behaviour.


Copyright (c) 2009 By Simon Lewis. All Rights Reserved.

July 23, 2009

What’s New In MIDP 3.0 ? Part 33: LCDUI – KeyListener

Filed under: Java, JME, LCDUI, MIDP, MIDP3, MIDP3LCDUI — Tags: , , , , , , — Simon Lewis @ 7:19 am

The KeyListener interface enables an object to listen for key events associated with a Canvas, CustomItem, or IdleItem

When a key is pressed, released or repeated the listening object is notified with the key code and modifiers.

The KeyListener of a Canvas or Custom Item can be set using their respective

	public void setKeyListener(KeyListener listener)

methods.

In each case passing null as the listener argument will result in the current KeyListener, if any, being removed.

For both a Canvas and a CustemItem having a KeyListener does not affect the


    protected void keyPressed(int keyCode)
	
    protected void keyReleased(int keyCode)
	
    protected void keyRepeated(int keyCode)

and they will continue to be called.


Copyright (c) 2009 By Simon Lewis. All Rights Reserved

What’s New In MIDP 3.0 ? Part 32: LCDUI – TextEditor

Filed under: Java, JME, LCDUI, MIDP, MIDP3, MIDP3LCDUI — Tags: , , , , , , — Simon Lewis @ 7:14 am

1. TextEditor

A TextEditor is a UI element which can be used in conjunction with a Canvas, CustomItem, or IdleItem to display and obtain text input from the user.

A TextEditor is the Canvas/CustomItem equivalent of a TextField and supports the same input constraints and modes as a TextField.

A TextEditor can only be associated with a single Canvas or CustomItem, but a Canvas or CustomItem may have multiple TextEditors associated with it.

The implementation is only responsible for the visual representation of the cursor and text. All other visual aspects of a TextEditor, for example, scroll bars if required, are the responsibility of the MIDlet.

2. TextEditorChangeListener

The TextEditorChangeListener enables an object to listen for the TextEditor events.

The listening object is notified when

  • the caret moves

  • the text changes

  • the current input language changes

  • the current input method changes

  • the direction of the writing language changes

  • the user traverses away from the TextEditor


Copyright (c) 2009 By Simon Lewis. All Rights Reserved

July 22, 2009

What’s New In MIDP 3.0 ? Part 31: LCDUI – Text

Filed under: Java, JME, LCDUI, MIDP, MIDP3, MIDP3LCDUI — Tags: , , , , , , — Simon Lewis @ 8:59 pm

A Text object is a mutable text container with the ability to layout it’s contents.

In addition to the text it contains, it has the following attributes, all of which can be set by a MIDlet as required.

  • the width and height of the rectangle within which to layout it’s contents

  • the initial text layout direction

  • the text alignment

  • the paragraph start indentation level

  • the space in pixels above each line of text

  • the space in pixels below each line of text

  • the background colour

  • the default foreground colour

  • the default Font

  • the position and length of the currently highlighted text, if any

  • the current position, if any, of the caret</p

The colour and Font used to render text can also be set on a section by section basis if required.

The contents of a Text object can be rendered to a Graphics object which means that it can be used in conjunction with a Canvas, CustomItem, IdleItem or mutable Image.


Copyright (c) 2009 By Simon Lewis. All Rights Reserved

What’s New In MIDP 3.0 ? Part 29: LCDUI – AnimatedImage

Filed under: Java, JME, LCDUI, MIDP, MIDP3, MIDP3LCDUI — Tags: , , , , , , — Simon Lewis @ 9:07 am

1. AnimatedImage

The AnimatedImage class is a sub-class of the Image class.

An AnimatedImage is a composite Image which comprises a sequence of Images. It is displayed by displaying the individual Images within the sequence one after another, each Image being replaced by its successor after a specified period of time.

An AnimatedImage may be used anywhere an Image can be used, but an implementation may not necessarily render the AnimatedImage exactly as specified. It may render it statically using the first Image in the sequence, or animate it only for a period of time.

2. Terminology

2.1 Frame

A frame is an individual Image within the sequence of Image’s that comprise the AnimatedImage.

2.2 Frame Count

The frame count is the number of Image’s in the sequence of Image’s that comprise the AnimatedImage.

2.2 Frame Delay

The frame delay is the amount of time, in milliseconds, for which a given frame will be displayed

2.3 Frame Index

The index of a given frame is it’s position within the sequence of Image’s that comprise the AnimatedImage.

Frames are indexed from zero so a valid frame index must be greater than or equal to zero and less than the frame count.

2.3 Loop Count

The loop count is the number of times the AnimatedImage’s frame sequence will be repeated after it has been shown for the first time.

3. Creating An AnimatedImage

An AnimatedImage can be created from data in the GIF89a format using any of the following Image method’s


    public static Image createImage(java.io.InputStream stream)
                        throws 
                            java.io.IOException

    public static Image createImage(String name)
                        throws 
                            java.io.IOException
						 
    public static Image createImage(byte[] imageData, int imageOffset, int imageLength)

In each case the resulting Image can then be cast to an AnimatedImage.

Whether the resulting Image is in fact an AnimatedImage can be determined by calling the Image’s isAnimated() method.

4. Getting The Frame Count

The frame count of an AnimatedImage can be obtained by calling it’s

    public int getFrameCount()

method.

5. Getting The Loop Count

The loop count of an AnimatedImage can be obtained by calling it’s

	public int getLoopCount()

method.

The method will return -1 if the frame sequence will be repeated indefitely.

6. Getting A Specific Frame

A specific frame of an AnimatedImage can be obtained by calling it’s

    public Image getFrame(int index)

method

It is an error if the index argument does not specify a valid frame index and an IndexOutOfBoundsException will e thrown.

The method will return an immutable Image representing the specified frame.

7. Getting The Delay For A Specific Frame

The delay for a specific Frame of an AnimatedImage by calling it’s

	public int getFrameDelay(int index)

method.

It is an error if the index argument does not specify a valid frame index and an IndexOutOfBoundsException will e thrown.


Copyright (c) 2009 By Simon Lewis. All Rights Reserved.

What’s New In MIDP 3.0 ? Part 28: LCDUI – Images

Filed under: Java, LCDUI, MIDP, MIDP3, MIDP3LCDUI — Tags: , , , , , — Simon Lewis @ 7:31 am

1. Creating Images

1.1 Creating A Mutable Image With An Alpha Channel

A mutable Image with an alpha channel by calling the Image method

    public static Image createImage(
                            int     width,
                            int     height,
                            boolean withAlpha,
                            int     fillColor)

It is an error if either the x or y arguments is less than one and an IllegalArgumentException will be thrown.

The fillColor argument specifies the initial value of each pixel of the created Image.

If the withAlpha argument is true then the fillColor argument is interpreted as a value of the form 0xAARRGGBB, otherwise as a value of the form 0x00RRGGBB

1.2 Creating An Image By Scaling And Transforming An Existing Image

An Image can be created by scaling and transforming all or part of an existing Image by calling the Image method

    public static Image createImage(
                            Image image,
                            int   x,
                            int   y,
                            int   width,
                            int   height,
                            int   transform,
                            int   img_width,
                            int   img_height)

The x, y, width, and height specify the region of the existing Image to use.

It is an error if the specified region is not entirely within the bounds of the source Image, or if the region’s width or height is less than one and an IllegalArgumentException will be thrown.

The transform argument specifies the transform to apply as defined in the Sprite class. It is an error if the specified transform is invalid and an IllegalArgumentException will be thrown.

The img_width and img_height arguments specify the size of the new Image. It is an error if the specified width or height is less than one and an IllegalArgumentException will be thrown.

2. Getting Image Data In 16-bit Formats

A MIDlet can get Image data in 16-bit RGB format by calling the Image’s

    public void getRGB16(
                    short[] rgbData,
                    int     offset,
                    int     scanlength,
                    int     x,
                    int     y,
                    int     width,
                    int     height)

method, and in 16-bit ARGB format by calling the Image’s

    public void getARGB16(
                    short[] rgbData,
                    int     offset,
                    int     scanlength,
                    int     x,
                    int     y,
                    int     width,
                    int     height)

method.

3. Predicate Methods

3.1 Does An Image Have An Alpha Channel ?

A MIDlet can determine whether an Image has an alpha channel by calling it’s

    public boolean hasAlpha()

method.

3.2 Is An Image Animated ?

A MIDlet can determine whether an Image is an instance of the sub-class AnimatedImage by calling the Image’s

    public boolean isAnimated()

method.

3.3 Is An Image Scalable ?

A MIDlet can determine whether an Image is an instance of the sub-class ScalableImage by calling the Image’s

    public boolean isScalable()

method.


Copyright (c) 2009 By Simon Lewis. All Rights Reserved.

Older Posts »

Blog at WordPress.com.

%d bloggers like this: