Just An Application

June 29, 2009

What’s New In MIDP 3.0 ? Part 21: LCDUI – Command Layout

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

1. The Command Layout Model

  • a MIDlet may explicitly control how a Displayable’s Commands are presented to the user when that Displayable is visible on a Display.

  • a MIDlet may choose to present a Displayable’s Commands individually or grouped into Menus.

  • a placement is a Display specific position which identifies a key, soft-key, or other interaction mechanism
    with which a Command or Menu may be associated.

  • a Display may have zero or more associated placements

  • the layout of a Displayable’s Commands requires the mapping of those Commands to a Display’s available placements, either directly or grouped into a Menu or Menus.

  • the explicit layout of a Displayable’s Commands is performed by an object which implements the CommandLayoutPolicy interface

  • any Displayable, except for instances of FileSelector, may have an associated CommandLayoutPolicy object

  • any Display may have an associated CommandLayoutPolicy object

  • the layout of a Displayable’s Commands is only performed when a Displayable is associated with a Display

  • the layout of a Displayable’s Commands is only required when the current Command layout is invalid. This can occur, for example

    • if the Displayable has not previously been visible on a given Display

    • if the orientation of a Display changes while the Displayable is visible

    • if one or more placements associated with a Display become invalid while the Displayable is visible

    • if the Command layout has been explicitly invalidated

  • when layout of a Displayable’s Commands is required then

    1. if the Displayable has an associated CommandLayoutPolicy object it will be used. If not then

    2. if the Display has an associated CommandLayoutPolicy object it will be used. If not then

    3. an implementation specific layout mechanism will be used.

  • if an Exception occurs during the use of a Displayable’s CommandLayoutPolicy object then

    1. if the Display has an associated CommandLayoutPolicy object it will be used. If not then

    2. an implementation specific layout mechanism will be used.

  • if an Exception occurs during the use of a Display’s CommandLayoutPolicy object then an
    implementation specific layout mechanism will be used.

  • a CommandLayoutPolicy object is responsible for the layout of all a Displayable’s Commands.

    • a Command will not be available to the user unless it is mapped to a placement or is a member of a Menu which itself is available to the user.

    • a Menu will not be available to the user unless it is mapped to a placement or is a sub-menu of a Menu which is itself available to the user.

  • if the Displayable is a Form then the Commands to be laid out can include those associated with Items in the Form.

  • if the Displayable is a TabbedPane then the Commands to be laid out can include those of the List or Form of the current Tab.


2. CommandLayoutPolicy

The CommandLayoutPolicy defines a single method.

    public void onCommandLayout(Displayable displayable)

A CommandLayoutPolicy object’s onCommandLayout(Displayable) method will be called with the Displayable whose Commands are to be laid out.

Notes

  1. The specification does not contain an explicit list of the circumstances under which this method will be called for a given Displayable, nor when it will be called relative to other events. For example, if an onLayout(Displayable) method is called as the result of an orienatation change, when it is called relative to the Display orientation change event.

  2. The specification does not contain an explicit definition of the state of a Display’s placements when the onLayout(Displayable) 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.

    The specification does say

    Any Command or Menu not explicitly set at a placement (via Displayable.setCommand(Command, int), Displayable.setMenu(Menu, int), or Item.setCommand(Command, int))
    in the CommandLayoutPolicy implementation will be ignored and not displayed.

    but omits to say when they have to have been explicitly set.

    On the other hand, the example code in the CommandLayoutPolicy class documentation, although somewhat broken, see below, explictly clears unused placements

        
    ...
    
        for (int i = cmd.length; i < positions.length; ++i) {
             //clear all non-used placements
             displayable.removeCommandOrMenu(border + positions[i]);
        }
    
    ...
  3. Currently the example code in the CommandLayoutPolicy class is broken and should not be used as an example of how to implement an onLayout method. See here.

3. Placements

For all Displays

  • a placement may be located on any one of the four borders

    • top,
    • bottom,
    • left,
    • right

    of the Display, or offscreen

  • each placement has an associated index
  • indices run from 1 to the maximum number of Commands possible at any location which is fifteen
  • for the horizontal borders, top and bottom, indices run from to left to right
  • for the vertical borders, left and right, indices run from top to bottom
  • the borders and directions are relative to the current orientation of the Display

For a given Display

  • there may be a set of preferred placements for a given Command type.
  • only a sub-set of the possible placements may support Menus.
  • there may be a set of preferred placements for Menus.

The set of possible placements is Display specific.

3.1 Runtime Constants

The possible locations are represented by the following constants defined in the Display class.

  • SOFTKEY_TOP
  • SOFTKEY_BOTTOM
  • SOFTKEY_LEFT
  • SOFTKEY_RIGHT
  • SOFTKEY_OFFSCREEN

3.2 Runtime Representation

At runtime a placement is represented by the integer which is the sum of the constant specifying its location and its index.


4. Layout Only Methods

The following Displayable methods can only be called during the layout of a Displayable’s Commands

In each case the method must only be called directly, or indirectly, from the onLayout(Displayable) method of a CommandLayoutPolicy object.

The Displayable the method is invoked on must either be

  • the Displayable that was passed to the onLayout(Displayable) method
  • or the Form or List of the current Tab, if the Displayable passed to the onLayout(Displayable) method is a TabbedPane

It is an error if these constraints are not met and an IllegalStateException will be thrown.

Item has a single method which can only be called during the layout of a Displayable’s Commands

The method must only be called directly, or indirectly, from the onLayout(Displayable) method of a CommandLayoutPolicy object.

The item that the method is invoked on must be contained within a Form which is either

  • the Displayable that was passed to the onLayout(Displayable) method, or
  • the current Tab of a TabbedPane that was passed to the onLayout(Displayable) method

It is an error if these constraints are not met and an IllegalStateException will be thrown.

5. Display CommandLayout Support

5.1 Getting The Current ComandLayoutPolicy

The current CommandLayoutPolicy object of a Display can be obtained by calling it’s

    public CommandLayoutPolicy getCommandLayoutPolicy()

method.

5.2 Setting The Current ComandLayoutPolicy

The current CommandLayoutPolicy object of a Display can be set by calling it’s

    public void setCommandLayoutPolicy(CommandLayoutPolicy policy)

method.

The specified CommandLayoutPolicy object will be used to perform the layout of the Commands of any Displayable which becomes current on this Display and which does not have an associated CommandLayoutPolicy object. If null was specified then a platform specific mechanism will be used.

5.3 Getting The Available Placements

The placements available on a given border of a Display, or offscreen, can be accessed using the Display’s

    public int[] getExactPlacementPositions(int border)

method.

The border argument must one of the runtime constants listed above.

The method returns the placements at the specified location, or null if there are no placements at that location.

Note

  • Despite being location specific the returned values are placements not indices.

5.4 Getting The Preferred Placements For A Command Type

The preferred placements for a given Command type can be obtained by using the Display’s

    public int[] getCommandPreferredPlacements(int commandType)

method.

It is an error if the commandType argument is not one of the runtime constants defined in the Command class which represent Command types.

The method returns null if there are no preferred placements for the given Command type.

5.5 Getting The Placements That Support Menus

The placements that support Menus can be obtained by using the Display’s

    public int[] getMenuSupportedPlacements()

method.

The method returns null if there are no placements that support Menus.

5.6 Getting The Preferred Placements For Menus

The preferred placements for Menus can be obtained by using the Display’s

    public int[] getMenuPreferredPlacements()

method.

The method returns null if there are no preferred placements for Menus.

6. Displayable Command Layout Support

6.1 Getting The Current Display

The Display, if any, with which the Displayable is currently associated can be obtained by calling the Displayable’s

    public Display getCurrentDisplay()

method.

The method will return null if the Displayable is not currently associated with a Display.

6.2 Getting The Current CommandLayoutPolicy

The current CommandLayoutPolicy object of a Displayable can be obtained by calling its

    public CommandLayoutPolicy getCommandLayoutPolicy()

method.

6.3 Setting The Current CommandLayoutPolicy

The CommandLayoutPolicy object responsible for laying out a Displayable’s Commands can be specified using it’s

    public void setCommandLayoutPolicy(CommandLayoutPolicy policy))

method.

6.4 Invalidating The Current Command Layout

The current Command layout of a Displayable can be invalidated by calling the Displayable’s

    public void invalidateCommandLayout()

method.

Note

  • The specification is not very forthcoming on what this method actually does.

    The full method documentation reads

    Request an update of the layout policy. If this displayable is not current on its display, or doesn’t have focus the request will be ignored.

    Presumably if the Displayable is current on its Display and the Display is in the Foreground state and the Displayable or the Display has an associated CommandLayoutPolicy object then, at some point the onLayout(Displayable) method of that object will be called.


6.5 Getting The Displayable’s Commands

The set of Commands that have been added to a Displayable can be obtained by calling it’s

    public Command[] getCommands()

method.

Note

  • See here for a discussion on what the return value of this method might actually contain.

6.6 Getting The Command At A Specific Placement

The Command associated with a specific placement of the Displayble’s current Display can be obtained by calling the Displayable’s

    public Command getCommand(int placement)

method.

It is an error if the placement argument is not valid and an IllegalArgumentException will be thrown.

Note

  • It is not clear when a placement is valid in this context, nor what will happen if this method is called when the Displayable is not associated with a Display. An answer to the first issue may resolve the second.

    There are two possible ways in which a placement may not be valid.

    1. It may not be well-formed, that is the location is not one of the runtime constants listed above, or the index is not between one and fifteen inclusive.

    2. It may be well-formed but not correspond to an actual placement on a given Display at a given time.

    If being valid means being well-formed then the method could simply return null when the Displayable has no current Display.

    If being valid means being well-formed and corresponding to an actual placement on a given Display then the method should throw an IllegalArgumentException if the Displayable does not have a current Display.

6.7 Placing A Command

During Command layout a Command can be associated with a specific placement using the Displayable’s

    public void setCommand(Command cmd, int placement)

This is a layout only method.

It is an error if the current Display of the Displayable does not support Commands and a DisplayCapabilityException will be thrown.

It is an error if the specified placement is not valid and an IllegalArgumentException will be thrown.

If the specified Command is currently associated with another placement of the Display it will be removed from that placement.

If there is a Command or Menu associated with the specified placement will be removed from the Displayable or Item which owns it.

Notes

  1. See here for a discussion of the issues surrounding some aspects of the semantics of this method.

  2. It is difficult to see under what circumstances a DisplayCapabilityException could be thrown by this method.

    If the current Display does not support Commands then

    1. if the Displayable had Commands when it was passed to the Display’s setCurrent(Displayable) method a DisplayCapabilityException would heve been thrown.

    2. if an attempt was made to add a Command to the Displayable once it was current on Display that did not support Commands then a DisplayCapabilityException would heve been thrown.

    To get to the point where it could happen the implementation would have had to deliberately call the onLayout(Displayable) method of the CommandLayoutPolicy object responsible for the Displayable knowing that

    1. the Display did not support Commands

    2. the Displayable did not have any associated Commands

    but this may actually be an implicit requirement

  3. The specification states that an IllegalArgumentException will be thrown if the placement argument

    is associated with a placement that does not support commands

    This and the documentation for Item.setCommand(Command, int) are the only places in the specification where it is suggested that a placement may not support Commands.

  4. The specification does not explicitly forbid the use of a Command which is also in a Menu.

6.8 Getting The Menu At A Specific Placement

The Menu associated with a specific placement can be obtained by calling a Displayable’s

    public Menu getMenu(int placement)

method.

It is an error if the specified placement is not valid and an IllegalArgumentException will be thrown.

If there is no Menu associated with the placement null will be returned.

Note

See the Note for the getCommand(int) method above


6.9 Placing A Menu

During the layout of a Displayable’s Commands a Menu can be associated with a specific placement using the Displayable’s

    public void setMenu(Menu menu, int placement)

method.

This is a layout only method.

It is an error if the current Display of the Displayable does not support Menus and a DisplayCapabilityException will be thrown.

It is an error if the specified placement is not valid or it does not support Menus and an IllegalArgumentException will be thrown.

The Command or Menu, if any, currently associated with the specified placement will be removed.

If the specified Menu is currently associated with another placement it will be removed from that placement.

Notes

  1. See here for a discussion of the issues surrounding some aspects of the semantics of this method.

  2. Presumably in the case of a Display which does not support Menus the DisplayCapabilityException will be thrown in preference to the IllegalArgumentException.

  3. The specification does not explictly preclude the use of a Menu which is a sub-Menu.


6.10 Removing A Command Or Menu From A Placement

During the layout of a Displayable’s Commands, a Command or Menu can be removed from a specific placement by calling the Displayable’s

    public void removeCommandOrMenu(int placement)

method.

This is a layout only method.

It is an error if the specified placement is not valid and an IllegalArgumentException will be thrown.

Note

  1. It is not clear from the specification what it means for a placement to be valid in this context. I would assume that it means that it must be an actual placement associated with the Displayable’s current Display.

  2. The behaviour if there is neither a Command or a Menu associated with the placement is not specified, but presumably it is a no-op, and this is certainly what the CommandLayoutPolicy example assumes.

7. Item Command Layout Support

7.1 Getting An Item’s Commands

The Commands currently associated with a Item can be obtained by calling the Item’s

    public Command[] getCommands()

method.

Note

  • The method documentation states that this method returns

    An array containing all commands added to the item via addCommand()

    If this is literally true then this method is going to return all the Commands ever added to the Item which is novel but pointless.

    Item also has a removeCommand(Command) method so we might hope that the effects of that might be taken into account as well.

    However, Item also has a setCommand(Command, int) method (see below) which

    Adds or sets a Command to the Item at the given placement.

    [emphasis added].

    In addition the documentation for both this method and the equivalent Displayable method
    states

    any Menu or Command already occupying the given placement will be removed from the associated Item or Displayable.

    If the set of Commands returned from the getCommands() method really is just the Commands added via addCommand(Command) and not subsequently removed via removeCommand(Command), then it still does not actually reflect the current state of the Item’s commands and it is effectively useless.

    This is especially true if we assume that one possible client of this method is a CommandLayoutPolicy object which wishes to obtain a list of the Item’s Commands that is is responsible for laying out. If it cannot obtain an accurate list using this method then it is going to have keep track of each Item’s Commands itself.

    In short, the getCommands() method is either not very useful or seriously underspecified.

7.2 Placing A Command

During the layout of a Displayable’s Commands an Item’s Command can be associated with a specific placement using the
Item’s

    public void setCommand(Command cmd, int placement)

method.

This is a layout only method.

A DisplayCapabilityException is throw in the current Display does not support Commands.

It is an error if the placement is not valid or it does not support Commands and an IllegalArgumentException will be thrown.

If the specified Command is currently associated with another placement it will be removed from that placement.

The Command or Menu, if any, currently associated with the specified placement will be removed from the Displayable or Item that owns it.

Notes

  1. As noted in the setCommand(Command,int) case these are the only two places in the specification where it is suggested that a placement might not support Commands

  2. As also noted in the setCommand(Command,int) case the possibility of a
    DisplayableCapabilityException is difficult to explain. In this case how does the Form containing the item can end up on a Displayable that does not support Commands if it contains Items that have Commands ?

8. Command Layout Issues

8.1 Lack Of An Explicit Model

Arguably the basic issue and the one from which the others follow is that there is no explict model of Command Layout and how it should work. Instead information is scattered through class and method documentation. This constitutes an implicit model of Command Layout but it is not an adequate substitute for a systematic definition of the concepts and functionality involved.

8.2 Adding And Removing Commands From A Displayable, Or What Exactly Does Displayable.getCommands() Return And Why ?

The single largest issue with the implicit model is the lack of a clear definition of what now constitutes the addition of a Command to, or the removal of a Command from, a Displayable.

Originally, pre MIDP 3, it was reasonably simple.

The Displayable.addCommand(Command) method documentation begins

Adds a command to the Displayable.

The Displayable.removeCommand(Command) method documentation begins

Removes a command from the Displayable.

That was it, ignoring the idiosyncracies of Alert. That was all it was possible to do. It wasn’t event possible to query the Displayable for it’s Commands.

In MIDP 3 there are new Displayable methods which also seem to add and remove Commands.

The Displayable.setCommand(Command, int) method

Adds or sets a Command to the Displayable at the given placement.

[Emphasis added]

and in doing so

any Menu or Command already occupying the given placement will be removed from the associated Item or Displayable.

[Emphasis added]

Then there is the Displayable.setMenu(Menu, int) method which

Adds or sets a menu to the Displayable at the given placement.

[Emphasis added].

and, just like the setCommand(Command, int) method

any Menu or Command already occupying the given placement will be removed from the associated Item or Displayable.

[Emphasis added].

There is also a new Item method setCommand(Command, int) which does not add a Command to a Displayable but like, Dispayable.setCommand(Command, int), and
Displayable.setMenu(Menu, int) it seems that it gets to remove them

any Menu or Command already occupying the given placement will be removed from the associated Item or Displayable.

[Emphasis added]

On that basis of the method documentation cited it is possible to construct reasonably plausible models of Displayables and Commands, and Displayables and Menus.

7.2.1 Displayables And Commands: A Model

  • a Displayable has a set of Commands, which may be empty

  • membership of a Displayable’s set of Commands is object identity based

  • a Command will be added to a Displayable’s set of Commands if it is not already a member, and it is either

    • passed as an argument to the Displayable’s addCommand(Command) method, or

    • passed as an argument to a valid call to the Displayable’s setCommand(Command, int) method with a valid placement

  • a Command will be removed from a Displayable’s set of Commands if it is currently a member, and it is either

    • passed as as an argument to the Displayable’s removeCommand(Command) method, or

    • currently associated with a placement, and that placement passed as an argument to a valid call to either

      • the Displayable’s setCommand(Command, int) method with a different Command

      • the Displayable’s setMenu(Menu, int) method

      or,

    • if the Displayable is a Form, and the Command is currently associated with a placement, and that placement is passed as
      an argument to a valid call to the setCommand(Command, int) method of an Item contained in the Form, or

    • if the Displayable is a TabbedPane, and the Command is currently associated with a placement, and that placement is either

      • passed to the current Tab’s setCommand(Command, int) method with a different Command, or

      • passed to the current Tab’s setMenu(Menu, int) method, or

      • passed to setCommand(Command, int) of an Item contained in the Form which is the current Tab, with a different Command
  • a Command cannot be added to a Displayable’s set of Commands if the Displayable’s current Display does not support Commands

  • a Displayable with a non-empty set of Commands cannot become current on a Display that does not support Commands

  • the Displayable.getCommands() method will return the Dispayable’s set of Commands

Note

  • the model does not include the special case behaviour for Alerts and FileSelectors

7.2.2 A Displayable Menus Model

  • a Displayable has a set of Menus, which may be empty

  • membership of a Displayable’s set of Menus is object identity based

  • a Menu will be added to a Displayable’s set of Menus if it is not already a member, and it passed as an argument to the
    Displayable’s setMenu(Menu, int) method with a valid placement

  • a Menu will be removed from a Displayable’s set of Menus is it is a member, and it is currently associated with a placement,
    and that placement is either

    • currently associated with a placement, and that placement passed as an argument to a valid call to either

      • the Displayable’s setCommand(Command, int) method with a different Command

      • the Displayable’s setMenu(Menu, int) method

      or,

    • if the Displayable is a Form, and the Menu is currently associated with a placement, and that placement is passed as
      an argument to a valid call to the setCommand(Command, int) method of an Item contained in the Form, or

    • if the Displayable is a TabbedPane, and the Menu is currently associated with a placement, and that placement is either

      • passed to the current Tab’s setCommand(Command, int) method with a different Command, or

      • passed to the current Tab’s setMenu(Menu, int) method, or

      • passed to setCommand(Command, int) of an Item contained in the Form which is the current Tab, with a different Command
  • a Menu cannot be added to a Displayable’s set of Menus if the Displayable’s current Display does not support Menus

  • a Displayable with a non-empty set of Menus cannot become current on a Display that does not support Menus

  • there is no way to programatically obtain the Dispayable’s set of Menus

Note

  • the model does not include the special case behaviour for FileSelectors

7.3 Other Issues

  • under what circumstances can a CommandLayoutPolicy object’s onLayout(Displayable) method get called for a given Displayable ?

  • when does Command layout occur relative to other Displayable and Display events ?

  • what state are a Display’s placements in when an onLayout(Displayable) method is called ?</p

  • are there any circumstances when an implememntation does not have to layout the Command’s of a Displayable that is current or about to become current on a Display

  • can a placement only support Menus ?

Appendix: Issues With The CommandLayoutPolicy Example

The following example (line numbers added) appears in the CommandLayoutPolicy class documentation.

1  class MyCanvas extends Canvas implements CommandLayoutPolicy {
2     MyCanvas() {
3       setCommandLayoutPolicy(this);
4     }
5
6     void sort(Command[] commands, int[] positions) {
7       // sort the commands in the correct order depending on the positions available.
8       // Implementation can use Display's getCommandPlacements to get the recommended 
9       // placement for each Command.
10    }
11 
12    public boolean onCommandLayout(Displayable displayable) {
13      Display display = displayable.getCurrentDisplay();
14      
15      final int border = Display.SOFTKEY_BOTTOM;
16     
17      int[] positions = display.getExactPlacementPositions(border);
18     
19      Command[] cmd = displayable.getCommands();
20     
21      sort(cmd, positions);
22     
23      if (cmd.length <= positions.length) {
24       
25        for (int i = 0; i < cmd.length; ++i) {
26          displayable.setCommand(cmd[i], border + positions[i]);
27        }
28        for (int i = cmd.length; i < positions.length; ++i) {
29          //clear all non-used placements
30          displayable.removeCommandOrMenu(border + positions[i]);
31        }
32      } else {
33       
34        for (int i = 0; i < positions.length - 1; ++i) {
35          displayable.setCommand(cmd[i], border + positions[i]);
36        }
37       
38        Menu options = new Menu("More", null, null);
39        for (int i = positions.length; i < cmd.length; ++i) {
40          options.append(cmd[i]);
41        }
42        displayable.setMenu(options, positions[positions.length-1]);
43      }    
44    }
45  }

At line 17 the return value of a call to the method Display.getExactPlacementPositions() is assigned to the variable positions. The method may return null. This is not tested for. If non-null then the return value is an array of placements, not indices. At lines 26, 30, and 35, the value of an element in positions is added to the value of border which is actually the constant Display.SOFTKEY_BOTTOM, and the result is then passed as a placement. In each case the placement will be invalid but only the first use at line 26 will be reached as an exception will then be thrown.

At line 42 an element of positions is passed directly as a placement to the method Display.setMenu(Menu,int) which is correct. However, calling the method without first checking whether the placement supports Menus is not.

And pedantically, at line 8 the comment mentions Display’s getCommandPlacements [method]. This should be Display’s getCommandPreferredPlacements method. And even more pedantically if the method is going to call a method on the current Display it will need to be passed either the Display or the Displayable.

Appendix: Working With Placements At Runtime

Obtaining the location or index of a placement requires the use of bit-wise AND and the constant SOFTKEY_INDEX_MASK
which is defined in the Display class.

Example

import javax.microedition.lcdui.Display;

...

    int placement = ...;
    int location  = placement & ~Display.SOFTKEY_INDEX_MASK;
    int index     = placement &  Display.SOFTKEY_INDEX_MASK;
	
...

Appendix: Placements And Display Orientation

Placements are relative to the current orientation of the Display which means that Command layout following an orientation change could be quite an interesting challenge.

Example

Assume a Display, initially in Portrait orientation, with two placements A and B on the left border and two placements, C and D, on the bottom border.

Example Placements: Portrait Orientation

In this orientation the available placements are

ID Border Index Placement
A Left 1 821
B Left 2 822
C Bottom 1 801
D Bottom 2 802

and Display.getExactPlacementPositions(int) returns

Border Return Value
SOFTKEY_TOP null
SOFTKEY_BOTTOM int[] { 801, 802 }
SOFTKEY_LEFT int[] { 821, 822 }
SOFTKEY_RIGHT null

Example Placements: Landscape Orientation

In this orientation the available placements are

ID Border Index Placement
A Top 2 842
B Top 1 841
C Left 1 821
D Left 2 822

and Display.getExactPlacementPositions(int) returns

Border Return Value
SOFTKEY_TOP int[] { 841, 842 }
SOFTKEY_BOTTOM null
SOFTKEY_LEFT int[] { 821, 822 }
SOFTKEY_RIGHT null

Example Placements: Portrait 180 Orientation

In this orientation the available placements are

ID Border Index Placement
A Right 2 862
B Right 1 861
C Top 2 842
D Top 1 841

and Display.getExactPlacementPositions(int) returns

Border Return Value
SOFTKEY_TOP int[] { 841, 842 }
SOFTKEY_BOTTOM null
SOFTKEY_LEFT null
SOFTKEY_RIGHT int[] { 861, 862 }

Example Placements: Landscape 180 Orientation

In this orientation the available placements are

<td2

ID Border Index Placement
A Bottom 1 801
B Bottom 2 802
C Right 2 862
D Right 1 861

and Display.getExactPlacementPositions(int) returns

Border Return Value
SOFTKEY_TOP null
SOFTKEY_BOTTOM int[] { 801, 802 }
SOFTKEY_LEFT null
SOFTKEY_RIGHT int[] { 861, 862 }

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

Advertisements

June 27, 2009

What’s New In MIDP 3.0 ? Part 20: LCDUI – Menus

Filed under: Java, JME, LCDUI, MIDP, MIDP3, MIDP3Issues, MIDP3LCDUI — Tags: , , , , , , — Simon Lewis @ 7:09 pm

1. The Menu Model

  • a Menu is a container for a group of items, where an item is either a Command or a Menu

    • a Command cannot be present in a Menu more than once

  • a Menu has a label which will be displayed to the user

  • a Menu’s label is mutable

  • a Menu may have a long label

  • a Menu may have an associated Image which may be displayed to the user

  • a Menu may have an associated Font which may be used to render the label of the Menu itself, but it will not be used to render the labels of its items

  • a Menu may be disabled or enabled

    • if a Menu is disabled then its items are not available for selection by the user

  • a Menu may be a sub-menu of another Menu

    • a Menu may only be the sub-menu of one other Menu

    • a Menu may not be a sub-menu of itself either directly or indirectly

  • there is a device specific limit on the maximum depth of a Menu tree

    • this will always be at least five

  • a Menu can be added to more than one Displayable

  • a Menu is visible if the labels of its items are visible to the user, or if if the labels of its items are visible to the user and one of its sub-Menus is also visible.

  • a Menu can only be visible on a single Display at a time

2. Attributes

A Menu has the same attributes as a Command, namely

  • a label
  • a long label (optional)
  • a font (optional)
  • an image (optional)

They have the same semantics and accessors as those in a Command.

3. Items

A Menu item can be either a Command or a Menu.

Neither a Command or a Menu can be present in a given Menu more than once. A Command can, however, be present in more than one Menu.

A Menu’s items can be considered to be a list, indexed from 0.

An item, subject to the constraints above, can be

  • appended to the list
  • inserted into the list at a specific index
  • removed from the list

When a Command in a Menu is selected the Menu is associated directly or indirectly with a Displayable, and the commandAction(Command, Displayable) method of the CommandListener, if any, associated with that Displayable will be invoked.

The implementation is responsible for handling the user selection of a sub-Menu.

Note

  • There are two things to consider when deciding whether to add an instance of Command to more than one Menu

    1. Commands are now mutable. Changes to a Command will be visible in each Menu
      in which it appears.

    2. When a Command is selected the only information available is the Displayable and the Command.
      There is no other context.

4. Functionality

4.1 Creating A Menu

An empty Menu can be created using the

    public Menu(String label, String longLabel, Image image)

constructor.

It is an error if the label argument is null and a NullPointerException will be thrown.

4.2 Disabling/Enabling A Menu

A Menu can be disabled/enabled by calling it’s

    public void setEnabled(boolean isEnabled)

passing false/true respectively.

4.3 Is A Menu Enabled ?

Whether a Menu is currently enabled can be determined by calling its

    public boolean isEnabled()

method.

4.4 Is A Menu Visible ?

Whether a Menu is currently visible can be determined by calling its

    public boolean isVisible()

method.

4.5 Item Access

4.5.1 Getting The Number Of Items In A Menu

The number of items in a Menu can be obtained calling the Menu’s

    public int size()

method.

4.5.2 Getting The Item At A Specific Index

The Command or Menu at a specific index in a Menu’s item list can be obtained by calling the Menu’s

    public Command getCommand(int index)

or

    public Menu getMenu(int index)

method respectively.

It is an error if index is less than 0, or greater than or equal to the number of items in the Menu and an IndexOutOfBoundsException will be thrown.

It is an error if the item at the specified index is not a Command or Menu respectively, and an IllegalArgumentException will be thrown.

4.5.3 Is The Item At A Specific Index A Command ?

Whether the item at a specific index in a Menu is a Command can be determined by calling the Menu’s

    public boolean isCommand(int index)

It is an error if index is less than 0, or greater than or equal to the number of items in the Menu and an IndexOutOfBoundsException will be thrown.

4.5.4 Appending An Item To A Menu

A Command or sub-Menu can be appended to a Menu by calling it’s

    public int append(Command cmd)

or

    public int append(Menu menu)

method respectively.

It is an error if the Command being appended is already present in the Menu and an IllegalArgumentException will be thrown.

It is an error if the Menu being appended is already a sub-Menu of a Menu, or if it is the root Menu of the tree containing this Menu.

It is an error if appending a Menu would result in the depth of the Menu tree exceeding the supported maximum depth, and an IllegalStateException will be thrown.

The item is added to the end of the list of items and its index is returned.

4.5.5 Inserting An Item Into A Menu At A Specific Index

A Command or Menu can be inserted into a Menu at a specific index by calling the Menu’s

    public void insert(int index, Command cmd)

or

    public void insert(int index, Menu menu)

method.

It is an error if index is negative or greater than the number of items in the Menu.

It is an error if the Command being inserted is already present in the Menu and an IllegalArgumentException will be thrown.

It is an error if Menu being inserted is already a sub-Menu of a Menu, or if it is the root Menu of the tree containing this Menu.

It is an error if inserting a Menu would result in the depth of the Menu tree exceeding the supported maximum depth, and an IllegalStateException will be thrown.

If index is less than the number of items in the Menu then the item will be inserted at that index, otherwise it will be appended to the Menu.

4.5.6 Removing An Item From A Menu

A Command or Menu can be removed from a Menu by calling its

    public void remove(Command cmd)

or

    public public void remove(Menu menu)

method repectively.

It is an error if the item is not present in the Menu and an IllegalArgumentException will be thrown.

4.5.7 Iterating Over The Items In A Menu

The Menu class does not provide a method for obtaining an Enumeration of a Menu’s items, but iterating over a Menu’s items is simple nonetheless.

Code Fragment


	...

    int nItems = menu.size();
	
    for (int i = 0; i < nItems; i++)
    {
        if (menu.isCommand(i))
        {
           Command c = menu.getCommand(i);
		   
           ...
        }
        else
        {
            Menu m = menu.getMenu(i);
         
            ...
        }
   }
   
   ...

4.6 Getting The Maximum Menu Tree Depth

The maximum supported Menu tree depth can be obtained by calling the Menu method

    public static int getMaxMenuDepth()

5. Issues

5.1 Menu Depth

At the moment the specification of Menu depth is inconsistent and either ambiguous or incomplete.

In the ‘Menu Creation and Population’ section of the Menu class documentation it says

The present depth of a menu, with the menu closest to the Displayable having depth 1, may be retrieved by the getMenuDepth() method.

In the Menu.getMenuDepth() method documentation it says

Returns this menu’s depth within its menu tree. The top menu is of depth 0, the menus attached to it are of depth 1, 2, etc. The top menu is the menu in the menu tree that has [been ?] attached to a Displayable. The depth of a non-anchored menu will be -1.

Assuming it is the latter that is correct, and putting aside the somewhat mangled wording, I think what this says is

  1. the depth of a Menu directly attached to one or more Displayables is 0 (zero), and the depth of a sub-menu in this Menu tree is the parent’s depth plus one ?

  2. the depth of a Menu that is not directly attached (non-anchored ?) to any Displayable, and is not a sub-Menu of another Menu, is -1 (minus one) ?

It is not clear from the documentation what the depth of a sub-Menu in the second Menu tree is.

For this to work, assuming that you wanted it to, a Menu cannot be attached to a Displayable and be a sub-Menu of another Menu, otherwise it would theoretically have two depths. There are two ways that this could happen.

  1. if a sub-Menu is added directly to a Displayable, or

  2. if a Menu that has been added directly to a Displayable, is then added as a sub-Menu of a completely unrelated Menu

The documentation for the Displayable.setMenu(Menu,int) does not place any restrictions on the Menu to be added at all, so the first should be posssible.

The methods Menu.append(Menu) and Menu.insert(int, Menu) will both throw an IllegalArgumentException, if

if the menu already has a parent menu or if it is the top menu in this menu’s tree.

but that would not apply to a root Menu that has been added to a Displayable, so the second should be possible as well.

Things would arguably be a lot simpler if the depth of a Menu was simply its distance from the root as is more usual.

If there really is a need to be able to determine whether a Menu has been attached to one or more Displayables it would be better if there was a separate method. The information will have to be available to the implementation for it to make the proposed depth scheme work, so why not make it directly available ?

5.2 The onParentEnabled Method

The Menu class defines the method

    public void onParentEnabled(boolean enabled)

The method documentation states

Informs the menu of a change in its parent’s enabled value. The application must itself decide how the Menu should handle this information. The default is to do nothing.

To make use of this method it would be necessary to define a sub-class of the Menu class and then over-ride the implementation in Menu, but it is not clear why this would actually be useful.

Unlike a Command, a Menu can only have one parent since a Menu may only be a sub-Menu of one other Menu, so we can assume that this method would be called when the Menu containing the sub-Menu was disabled/enabled, and that is about all.

It would be useful if the specification supplied a use-case of some sorts for this method. Either that or it should be removed. At the moment an implementation is responsible for calling this method as appropriate which is fairly pointless unless there is some particularly good reason for it to exist.


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

June 25, 2009

What’s New In MIDP 3.0 ? Part 19: LCDUI – Commands

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

1. Changes To The Command Class

  • Commands are partially mutable. It is possible to set a Command’s

    • label
    • long label
  • A Command can have an associated Image which can be used in conjunction with the label. The implementation can choose to ignore the Image.

  • A Command can have an associated Font. If a Command has a Font it may be used to render the Command’s text, but an implementation may choose to ignore it.

  • A Command can be disabled or enabled. If a Command is disabled then it is not available to the user and its appearance will reflect this.

2. New Functionality

2.1 Constructing A Command With An Image

A Command can be constructed with an image using the

    public Command(
               String shortLabel,
               String longLabel,
               Image  image,
               int    commandType,
               int    priority)

constructor.

The image argument may be immutable or mutable. If the Image is mutable then as is conventional an immutable copy will be used.

The other arguments are the same as for the existing constructors.

2.2 Disabling And Enabling A Command

A Command can be disabled/enabled by calling it’s

    public void setEnabled(boolean enabled)

method with an argument of false/true respectively.

2.3 Is A Command Enabled ?

Whether a Command is enabled can be determined by calling it’s

    public boolean getEnabled()

method.

Note

  • Standard naming conventions would require that this method be called isEnabled which might be better

2.4 Getting The Font

The Font, if any, associated with a Command can be obtained by calling it’s

    public Font getFont()

method.

2.5 Setting The Font

The Font associated with a Command can be set by calling it’s

    public void setFont(Font font)

method.

2.6 Getting The Image

The Image, if any, associated with a Command can be obtained by calling it’s

    public Image getImage()

method.

2.7 Setting The Image

The Image associated with a Command can be set calling it’s

    public void setImage(Image image)

method.

The Image may be immutable or mutable. If the Image is mutable then as is conventional an immutable copy will be used.

2.8 Setting The Label

The label of a Command can be set by calling it’s

    public void setLabel(String label)

method.

It is an error if label is null and a NullPointerException will be thrown.

2.9 Setting The Long Label

The long label of a Command can be set by calling it’s

    public void setLongLabel(String longLabel)

method.

3. Notes

  1. There are number of Commands defined as class constants which are now presumably mutable. For example,

    • Alert.DISMISS_COMMAND
    • List.SELECT_COMMAND

    A MIDlet could disable the Alert.DISMISS_COMMAND if it chose to. Its not clear why it would want to, and any adverse effects are entirely self-inflicted, but nonetheless it is now possible for it to do so. Caveat implementor.

  2. A Command now has an onParentEnabled(boolean) method. The method documentation says

    Informs the command of a change in its parent’s enabled value. The application must itself decide how the Command should handle this information, the default is to do nothing.

    Unfortunately that is all it says.

    Presumably it is intended that it be over-ridden in sub-classes of Command. Its just not clear why.


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

June 23, 2009

What’s New In MIDP 3.0 ? Part 18: LCDUI – Displays

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

1. The Display Model

  • A device has one or more physical displays.

  • Each physical display may support sharable and non-sharable functionality.

  • The supported functionality may differ between physical displays.

  • A Display gives a MIDlet access to a fixed set of the functionality of a corresponding physical display.

  • A MIDlet will always have access to a primary display corresponding to the main physical display of the device.

  • If a device has additional physical displays a MIDlet will have access to corresponding secondary Displays.

  • If a physical display has two or more operating modes each with a discrete set of functionality a MIDlet will have access to those
    modes via two or more Displays.

2. Display Characteristics

2.1 Getting The Display’s Height

A Display’s height in pixels can be obtained by calling its

    public int getHeight()

method.

The value returned is the maximum height available for the display of a Displayable including its Title, Ticker, Commands and Menus, if present.

2.2 Getting The Display’s Width

A Display’s width in pixels can be obtained by calling its

    public int getWidth()

method.

The value returned is the maximum width available for the display of a Displayable including its Title, Ticker, Commands and Menus, if present.

2.3 Getting The Display’s Dot Pitch

A Display’s dot pitch can be obtained by calling its

    public int getDotPitch()

method.

The value returned is the distance between adjacent pixels in micrometers (1 x 10-6m).

2.4 Does The Display Support Pointer Events ?

Whether or not a Display supports Pointer events can be determined by calling its

    public boolean hasPointerEvents()

method.

The method returns true if the Display is capable of reporting Pointer pressed and released events.

Notes

  1. This method effectively supercedes the Canvas.hasPointerEvents() method. Whether Pointer events are supported by a Canvas is actually dependent upon the Display on which the Canvas is currently visible.
  2. It is not clear why, other than for convenience, this functionality is not implemented using the capabilites mechanism.

2.5 Does The Display Support Pointer Motion Events ?

Whether or not a Display supports Pointer Motion events can be determined by calling its

    public boolean hasPointerMotionEvents()

method.

The method returns true if the Display is capable of reporting Pointer motion eventst.

Note

  1. This method effectively supercedes the Canvas.hasPointerMotionEvents() method. Whether Pointer motion events are supported by a Canvas is actually dependent upon the Display on which the Canvas is
    currently visible.
  2. It is not clear why, other than for convenience, this functionality is not implemented using the capabilites mechanism.

2.6 Is The Display Built-in ?

Whether or not the corresponding physical of a Display is built-in can be determined by calling its

    public boolean isBuiltIn()

method.

The method returns true if the corresponding physical display is built-in, that is, if it is an integral part of the device. If it is then the corresponding Display will never become unusable as the result of the removal of the corresponding physical display.

3. Display Capabilities

The functionality supported by a given Display is specified at runtime using capabilities, where a capability typically represents a discrete LCDUI feature.

The following capabilities are defined as constants in the Display class.

  • SUPPORTS_ALERTS
  • SUPPORTS_COMMANDS
  • SUPPORTS_FILESELECTORS
  • SUPPORTS_FORMS
  • SUPPORTS_IDLEITEM
  • SUPPORTS_INPUT_EVENTS
  • SUPPORTS_LISTS
  • SUPPORTS_MENUS
  • SUPPORTS_ORIENTATION_LANDSCAPE
  • SUPPORTS_ORIENTATION_LANDSCAPE180
  • SUPPORTS_ORIENTATION_PORTRAIT
  • SUPPORTS_ORIENTATION_PORTRAIT180
  • SUPPORTS_TABBEDPANES
  • SUPPORTS_TEXTBOXES
  • SUPPORTS_TICKER
  • SUPPORTS_TITLE

The constants are bit-flags and can be combined using bit-wise OR.

A MIDlet’s primary Display will support all LCDUI features but a secondary Display may not.

All Displays provides basic Canvas support.

The capabilities of a Display are fixed.

3.1 Getting A Display’s Capabilities

A Display’s capabilities can be obtained using its

 public int getCapabilities()

method.

The return value will either be the bit-wise OR’ed combination of the supported capabilities, or 0 indicating that the Display only provides basic Canvas support.

3.2 DisplayCapabilityException

A DisplayCapabilityException is thrown when an attempt is made to perform an operation which directly or indirectly involves a Display which does not support the functionality required for the operation. For example, passing an instance of Form to the setCurrent() method of a Display which does not support Forms.

4. Display State

A Display can be in one of three states

  • Foreground,
  • Background, or
  • Visible

depending upon its current level of access to the functionality of the corresponding physical display.

4.1 Foreground

If a Display is in the Foreground state then it currently has exclusive access to all non-sharable functionality of the corresponding physical display, and first-call on any sharable functionality.

4.2 Background

If a Display is in the Background state then it currently has no access to the functionality of the corresponding physical display.

4.3 Visible

If a Display is in the Visible state then it has access to at least one pixel of the corresponding physical display, but it has no access to any of the non-sharable functionality.

4.4 Runtime Constants

The possible display states are represented by the following constants defined in the Display class

  • STATE_BACKGROUND
  • STATE_FOREGROUND
  • STATE_VISIBLE

4.5 Getting The Current Display State

The current state of the Display can be obtained using the Display’s

    public int getDisplayState()

method which will return one of the constants listed above.

5. Hardware State

The hardware state of a Display is equivalent to the state of the corresponding physical display.
The physical display may be

  • Enabled,
  • Disabled, or
  • Absent

The hardware state of a MIDlet’s primary display will never be Absent.

5.1 Enabled

If the hardware state of a Display is Enabled then the functionality of the corresponding physical display is available to the Display.

5.2 Disabled

If the hardware state of a Display is Disabled then the functionality of the corresponding physical display is not available to the Display.

5.3 Absent

If the hardware state of a Display is Absent then the corresponding physical display is no longer available and the Display itself is no longer usable.

5.4 Runtime Constants

The possible hardware states are represented by the following constants defined in the Display class

  • DISPLAY_HARDWARE_ABSENT
  • DISPLAY_HARDWARE_DISABLED
  • DISPLAY_HARDWARE_ENABLED

5.5 Getting The Current Hardware State

The current hardware state of a given Display can be obtained used the Display’s

    public int getHardwareState()

method which will return one of the constants listed above.

6. Activity Mode

The activity mode of a Display may be either Normal or Active.

If a Display is in the Foreground state and its activity mode is Normal then the corresponding physical display may enter a reduced functionality power-saving state if the current power management policies of the device allow it.

If a Display is in the Foreground state and its activity mode is Active then the corresponding physical display should remain in a fully functional state.

If a Display in the Foreground state changes its activity mode from Normal to Active and the corresponding physical display is in a power-saving state it should return to a fully functional state.

The possible activity modes are represented by the following constants defined in the Display class.

  • MODE_ACTIVE
  • MODE_NORMAL

6.1 Getting The Current Activity Mode

The current activity mode of a Display can be obtained by calling it’s

    public int getActivityMode()

method which will return one of the runtime constants listed above.

6.2 Setting The Current Activity Mode

The current activity mode of a Display can be set by calling it’s

    public void setActivityMode(int mode)

method.

The mode argument must be one of the constants listed above.

7. Display Orientation

A Display may support more than one orientation.

Possible orientations are

Landscape Display’s width is greater than its height
Landscape 180 Landscape with content rotated through 180 degrees
Portrait Display’s height is greater than its width
Portrait 180 Portrait with content rotated through 180 degrees

The orientations supported by a Display can be determined by calling its getCapabilities() method.

7.1 Runtime Constants

The possible orientatations are represented by the following constants defined in the Display class

  • ORIENTATION_LANDSCAPE
  • ORIENTATION_LANDSCAPE180
  • ORIENTATION_PORTRAIT
  • ORIENTATION_PORTRAIT180

7.2 Getting The Orientation

The current orientation of the Display can be obtained by calling its

    public int getOrientation()

method which will return one of the constants listed above.

7.3 Setting The Preferred Orientation

The preferred orientation of a Display can be set using its

    public void setPreferredOrientation(int orientation)

method where orientation must be one of the constants listed above.

Note

It is not clear from the specification exactly what setPreferredOrientation() does. It states

This call may not have an effect on the actual orientation of the display if the specified orientation is not supported on the device.

It then goes on to say

The application may use getOrientation() to detect the actual orientation of the display after this call.

which would seem to imply that it is not guaranteed to do anything even if the specified orientation is supported by the Display.

More generally it is not clear what it means for a Display to support a given orientation. One possible interpretation is that if a Display supports more than one orientation, then, if the orientation of the Display changes it will automatically re-render all visible UI elements appropriately. This would seem to make sense as there is no API by which a MIDlet could achieve the same effect. Other aspects of the UI such as the size of the UI elements are potentially under the control of the MIDlet and are presumably, therefore, its responsibility.

8. Display Events

A MIDlet can listen for the addition of secondary Displays, and for changes in the

  • display state
  • hardware state
  • orientation
  • size

of individual Displays using an instance of the DisplayListener interface.

All Display events are serialized with respect to other LCDUI events.

Note

An orientation change may also result in a size change, but the specification does not explicitly state that the resulting events must occur in a particular order.

8.1 Adding A DisplayListener

A MIDlet can begin listening by using the Display method

    public static void addDisplayListener(DisplayListener l)

to add a DisplayListener.

8.2 Removing A DisplayListener

A MIDlet can stop listening using the Display method

    public static void removeDisplayListener(DisplayListener l)

to remove a DisplayListener added previously.

8.3 DisplayListener

Events are reported to a DisplayListener using event specific methods as follows.

8.3.1 Addition

The addition of secondary display is reported via the

    public void displayAdded(Display d)

method.

8.3.2 State Changes

Changes to the state of a Display are reported via the

    public void displayStateChanged(Display d, int newState)

method.

The newState argument will be one of the Display state runtime constants.

8.3.3 Hardware State Changes

Changes to the hardware state of a Display are reported via the

    public void hardwareStateChanged(Display d, int newState)

method.

The newState argument will be one of the Hardware state runtime constants.

8.3.4 Orientation Changes

Changes to the orientation of a Display are reported via the

     public void void orientationChanged(Display d, int newOrientation)

method.

The newOrientation argument will be one of the Orientation runtime constants.

8.3.5 Size Changes

Changes to the size of a Display are reported via the

    void sizeChanged(Display d, int w, int h)

method.

The arguments w and h are the new width and height of the Display respectively.

9. Getting Displays

9.1 Getting The Primary Display

The existing Display method

    public static Display getDisplay(MIDlet m)

will return the primary Display for the given MIDlet.

9.2 Getting Displays With Specific Capabilities

The new Display method

    public static Display[] getDisplays(int capabilities)

can be used to obtain a list of all the Displays currently available, or a list of those which support a specified set of capabilities.

If capabilities is 0 then a list available Displays will be returned, with the primary Display first.

If capabilities is a bit-wise ORed combination of the runtime constants representing capabilities, then the list of Displays supporting those capabilities will be returned, with the primary Display first.

Note

The method documentation states

Since the Primary Display must support all capabilities, it is always returned as the first element regardless of the capabilities requested.

For this to be true the Primary display must not only support all the LCDUI features, but all the possible orientations as well. It is not clear what supporting all possible orientations entails nor whether it is necessarily feasible on every device.

10. Transient Secondary Displays

The physical display corresponding to a secondary Display can become unavailable. In this case the hardware state of the secondary Display will change to Absent. Once this happens the secondary Display is no longer usable, and calls to methods such as setCurrent(Displayable) will throw an IllegalStateException.

If the physical display corresponding to the secondary Display becomes available again it
will be reported as a new Display via a call to the DisplayaListener.displayAddedd(Display) method.

12. Backwards Compatibility

Some existing methods now throw new exceptions. For example, Display.setCurrent(Displayable) can now throw a DisplayCapabiltyException or an IllegalStateException. However, as required to ensure binary compatibility, all new exceptions thrown are RuntimeExceptions. In addition these exceptions cannot occur when using the Primary display which is the only Display that a legacy MIDlet has access to,


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

June 19, 2009

What’s New In MIDP 3.0 ? Part 17: Preventing Users From Starting And Stopping MIDlets

Filed under: Java, JME, MIDlets, MIDP, MIDP3 — Tags: , , , , , , — Simon Lewis @ 6:27 pm

A user can be prevented from starting and/or stopping a given MIDlet.

This can be done by using a

    MIDlet-<n>-UserDenied

attribute corresponding to the

    MIDlet-<n>

attribute used to declare the MIDlet itself.

It is an error if a MIDlet-<n>-UserDenied attribute is specified without a corresponding MIDlet-<n> attribute and installation will fail.

The value of the attribute must be a comma separated list of actions, where an action is one of

  • run
  • stop

If the run action is specified then a user will not be able to start the MIDlet using the device’s application launcher.

If the stop action is specified and a device supports application management level functionality for stopping applications then the user will not be able to use that functionality to stop the MIDlet. It does not affect the user’s ability to stop the MIDlet using functionality provided by the MIDlet itself via the UI, if any.

To specify a MIDlet-<n>-UserDenied attribute or attributes a MIDlet Suite must have been granted the ActionsDeniedPermission.

The specified MIDP 3 security policy does not make it possible for MIDlet Suites bound to either the Identified Third Party or the Unidentifed Third Party protection domains to be granted the ActionsDeniedPermission under any circumstances.

What’s New In MIDP 3.0 ? Part 16: Scalable MIDlet Icons

Filed under: Java, JME, MIDlets, MIDP, MIDP3 — Tags: , , , , , , — Simon Lewis @ 5:37 pm

A scalable image in SVG Tiny format can be specified as the icon for a MIDlet.

This can be done at installation time by using a

    MIDlet-<n>-Scalable-Icon

attribute corresponding to the

    MIDlet-<n>

used to specify the MIDlet itself.

The value of the attribute should be the relative pathname of a file in the MIDlet Suite JAR containing the image.

The MIDlet-<n>-Scalable-Icon is a localizable attribute, so a locale specific scalable icon can be specified using a

	MIDlet-<n>-Scalable-Icon-<locale>

attribute.

Note

If icons are specified using both a MIDlet-<n>-Scalable-Icon attribute and the corresponding MIDlet-<n>, attribute, then whether the scalable icon should be used in preference to the non-scalable icon, or vice-versa, is unspecified, as is whether it is actually legal to specify both.

What’s New In MIDP 3.0 ? Part 15: Localized MIDlet Attributes

The MIDlet-<n> attribute is now a localizable attribute. It is possible for a MIDlet to have a locale specific name and icon, and also, apparently, class.

A locale specific variant of a given

    MIDlet-<n>

attribute can be specified using a corresponding

    MIDlet-<n>-<locale> 

attribute.

The value of the attribute must be of the form

    [<name>] "," [<icon>] "," [<class>]

where, as for a MIDlet-<n> attribute, <name> is the name of the MIDlet, <icon> the icon with which to represent the MIDlet, and <class> the MIDlet class, and the same constraints apply.

The name, icon, and class that are used for the n‘th MIDlet are defined to be the values specified by the MIDlet-<n>-<locale> attribute whose <locale> matches the current locale. In each case if there is no locale specific version, then the value specified by the corresponding MIDlet-<n> attribute is used instead.

If there is no matching MIDlet-<n>-<locale> attribute then the values default to those specified by the MIDlet-<n> attribute.

Example

Assuming the following MIDlet-<n> and MIDlet-<n>-<locale> attributes are specified


    MIDlet-1:       SwatchMIDlet, SwatchMIDlet.png, example.midlet.SwatchMIDlet
    MIDlet-1-en-UK: ColourSwatchMIDlet
    MIDlet-1-en-US: ColorSwatchMIDlet, ColorSwatchMIDlet.png

then the possible values for the MIDlet name, icon and class are as follows

Locale MIDlet Name MIDlet Icon MIDlet Class
en-UK ColourSwatchMIDlet SwatchMIDlet.png example.midlet.SwatchMIDlet
en-US ColorSwatchMIDlet ColorSwatchMIDlet.png example.midlet.SwatchMIDlet
Any other locale SwatchMIDlet SwatchMIDlet.png example.midlet.SwatchMIDlet

Issues

On the basis of the documentation for the MIDlet-<n>-<locale> attribute it would appear that a MIDlet class can be locale specific.
It is certainly not explicitly forbidden. If this is true then it has implications for other supported features.

For example, push connections. The MIDlet-Push-<n> attribute specifies the class of the MIDlet to launch. The documentation states

The named MIDlet MUST be registered in the application descriptor or the JAR manifest with a MIDlet-<n> record.

The same constraint applies to the dynamic registration of alarms

The named MIDlet MUST be registered in the application descriptor or the JAR manifest with a MIDlet-<n> record. This parameter has the same semantics as the MIDletClassName in the Push registration attribute defined above in the class description.

using the PushRegistry.registerAlarm() method, and push connections

The named midlet MUST be registered in the application descriptor or the JAR manifest with a MIDlet-<n> record. This parameter has the same semantics as the MIDletClassName in the Push registration attribute defined in the class description.

using the PushRegistry.registerConnection() method.

The use of a MIDlet class to identify a MIDlet is not unique to alarm and push connection registration. Event Handler registration also requires the use of a class name.

For static registration the MIDlet-Event-Launch-<n> does not explicitly require that the class has been registered via a MIDlet-<n> attribute, which is in itself an issue, but dynamic registration does. Documentation for all variants of the EventHandler.registerApplication() method states

For MIDP, the named application class MUST be registered in the JAD or JAR Manifest for the MIDlet suite of the calling MIDlet with a MIDlet-<n> application attribute, and MUST extend javax.microedition.midlet.MIDlet.

Outside MIDP there is the Content Handler API (JSR211) which also uses class names for static and dynamic registration of content handlers as well as for generating Application IDs.

If a MIDlet class can be locale specific then the specification really needs to explain what the semantics of MIDlet classes now are and how the features mentioned above should work in this case.

If a MIDlet class cannot be locale specific then this needs to be made explicit.

There is one possible further complication. In discussing whether localized attributes should be
discarded at installation time the specification states

Usually one or more localized attribute versions end up being retained …

It is not clear why any localized attributes other than those matching the current locale actually
need to be retained. One possibility is that is is expected that if the current locale changes
subsequently then the appropriate localized attributes should be used. For most attributes this
is fairly innocuous, the MIDlet Suite description, for example, would simply be in language A
rather than language B. If MIDlet classes can be locale specific however things get very
complicated indeed: push connections, event handlers and content handlers could all end up
registered to the wrong MIDlet class. I assume that this is not what is intended.


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

June 18, 2009

What’s New In MIDP 3.0 ? Part 14: Localizable Attributes

Filed under: Java, JME, LocalizableAttributes, MIDP, MIDP3 — Tags: , , , , — Simon Lewis @ 10:10 pm

MIDP 3 adds support for localizable attributes, that is, attributes which can have locale specific values in addition to the value specified by the attribute itself.

A locale specific value for a localizable attribute can be specified at installation time using a localized attribute, which is an attribute whose name is formed from the name of the localizable attribute with the suffix

    "-"<locale>

appended, where the value of <locale> is of the form

    <language> ["-" <country> ["-" <variant>]]

The value of <language> must be a lower-case ISO-639-1 two-letter language code.

The value of <country> if present must be an upper-case ISO-3166-1 two-letter country code.

For example, the existing attribute

    MIDlet-Description 

is now localizable. so it is now possible to define locale specific versions of the MIDlet Suite description using attributes such as

  • MIDlet-Description-de
  • MIDlet-Description-de-DE
  • MIDlet-Description-fr
  • MIDlet-Description-tr

Multiple locale specific values of a localizable attribute can be specified at installation time. For example, all the MIDlet-Description localized attributes above can appear in the JAD and/or manifest of the MIDlet Suite Jar.

At installation time the specification permits an implementation to discard all those localized attributes whose specified language is not supported by the device.

The value of a localizable attribute to be used is selected on the basis of the current locale. If there is a locale specific variant of the localizable attribute whose locale matches the current locale then the specified value is used. If there is no matching locale specific variant the value of the localizable attribute itself is used.

The algorithm used to do locale matching is similar to the one used to select locale specific resources in JSE. In pseudo-code it might be expressed as follows

    current = current locale
    if attribute with locale equal to current found then
        return matching attribute
    else
    if current has variant then
        current = current with variant removed
        if attribute with locale equal to current found then
            return matching attribute
        else
            current = current with country removed
            if attribute with locale equal to current found then
                return matching attribute
            else
                return no match
            endif
       endif
   else
   if current has country then
       current = current with country removed
       if attribute with locale equal to current found then
          return matching attribute
       else
           return no match  
       endif
   else
       return no match
   endif

Note

As has been mentioned, the specification permits an implementation to discard at installation time any localized attributes for languages not supported on the device. It is not clear whether the discarded localized attributes are subsequently accessible via the variants of the MIDlet.getAppProperty() methods. If they are not then it would be useful if the specification made this clear. Alternatively, if they are accessible it is not clear what discard might actually mean in this context.


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

What’s New In MIDP 3.0 ? Part 13: MIDlet Types

Filed under: Java, JME, MIDlets, MIDP, MIDP3 — Tags: , , , , , , , — Simon Lewis @ 4:05 pm

There are three specialized MIDlet types in MIDP 3.0

  • AutoStart
  • IdleScreen
  • ScreenSaver

If a MIDlet is of one or more of these types, then they must be declared at installation time using a

    MIDlet-<n>-Type

attribute corresponding to the

    MIDlet-<n>

attribute used to declare the MIDlet itself.

The value of the attribute is of the form

    <type> ["," <type>]*

where <type> is one of

  • autostart
  • idlescreen
  • screensaver

To declare the type of a MIDlet as autostart a MIDlet Suite must be granted the javax.microedition.midlet.AutoStartPermission.


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

June 16, 2009

What’s New In MIDP 3.0 ? Part 12: MIDlet Categories

Filed under: Java, JME, MIDlets, MIDP, MIDP3, Mobile Java — Tags: , , , , , , , — Simon Lewis @ 3:32 pm

A MIDlet can now be specified as belonging to one or more categories.

This is done at installation time by specifying a

    MIDlet-<n>-Category

attribute corresponding to the

    MIDlet-<n>

attribute used to declare the MIDlet itself.

The value is a comma separated list of categories.

The specification defines the following categories

  • calls
  • camera
  • contacts
  • games
  • internet
  • location
  • messaging
  • music
  • office
  • pictures
  • settings
  • shop
  • video

and implementations can extend this list if they choose.

There are no semantics associated with the use of categories and their handling is entirely implementation specific.

Note

As a rule this information is going to be used by the device to decide how to present the MIDlet to the user in terms of available applications and types of application, but it could also be used to make quality-of-service and resource allocation decisions at runtime for example.


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

Older Posts »

Blog at WordPress.com.

%d bloggers like this: