Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
Developer
Developer
Posts: 39
Registered: ‎03-17-2009
My Device: Not Specified

multiple 4.0.2 bugs in J2ME MIDP2 implementation - example included

Some weeks ago, I set out to port my existing MIDP 2.0 MIDlet application to BlackBerry.  There were a few issues that were relatively well documented:

* need to break application into <64K pieces
* need to generate COD files instead of JAR
* need to do I/O (in particular, HTTP connection) on different thread from UI
* need to build with tools corresponding to OS version *or earlier* than the target device

although I don't remember where in the BlackBerry documentation I first saw reference to these issues.

I then began to try to port my MIDlet to BlackBerry.  I picked 4.0.2 because I wanted to be able to target MIDP 2.0 devices.  Along the way I have run into the following issues, some of which I was able to create or find workarounds for, others not:

1. Setting an HTTP header value to the empty string caused the device simulator to swallow HTTP POST data.

WORKAROUND: In my case, it was OK to make sure that the empty string was never sent as an HTTP header value

TEST CASE: Abstraction of test case at http://supportforums.blackberry.com/rim/board/message?board.id=java_dev&message.id=27083#M27083 .

2. Display.getColor() broken: always returns black for (regular/highlit)foreground/background

WORKAROUND: Set foreground and background colors in canvas to black and white if Display.getColor returns equal values for foreground and background colors.

OTHER PEOPLE RUNNING INTO PROBLEM:
http://blogs.sun.com/lukas/entry/tip_using_colorschema_for_tableitem

TEST CASE: See below.

3. In non-trivial MIDlet, "RuntimeException: pushModalScreen called by a non-event thread" thrown on MIDlet.platformRequest().

WORKAROUND: None found.

FORUM POST: http://supportforums.blackberry.com/rim/board/message?board.id=java_dev&thread.id=27496

TEST CASE: Example below does not exhibit this behavior.  Stack trace for 4.0.2 device simulator is:
    UiEngineImpl.pushModalScreen(Screen) 481
    Dialog.doModal() 509
    Dialog.ask(int,String,int) 432
    MIDlet.platformRequest(String) 323

4. popup ChoiceGroup.deleteAll() leaves Field/Manager in illegal state

WORKAROUND: See below.

TEST CASE: See below.

OTHER PEOPLE RUNNING INTO PROBLEM:

http://www.blackberry.com/developers/forum/thread.jsp?forum=1&thread=13272

5. ItemStateListener.ItemStateChanged() never fired for popup value change

WORKAROUND: None found.

TEST CASE: See below.

OTHER PEOPLE RUNNING INTO PROBLEM:

"itemStateChanged() method did not call"   
http://www.blackberryforums.com/developer-forum/34823-itemstatechanged-method-did-not-call.html

"How to ItemStateChange on BlackBerry 7100i"   
http://supportforums.blackberry.com/rim/board/message?board.id=java_dev&thread.id=11061   

6. Hang on OutputStream.flush() for HTTP POST

WORKAROUND: Shutdown and restart MDS and device simulators: See
http://supportforums.blackberry.com/rim/board/message?board.id=java_dev&message.id=27078#M27078

TEST CASE: Don't have simple one, requires HTTP server to handle POST.

OTHER PEOPLE RUNNING INTO PROBLEM:

http://supportforums.blackberry.com/rim/board/message?board.id=java_dev&thread.id=4558



Here is my test case for these issues:

package cd;
import javax.microedition.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class BBMIDlet extends MIDlet implements CommandListener {
protected void destroyApp(boolean unconditional)
throws MIDletStateChangeException {
System.out.println("shutting down...");
}
protected void pauseApp() {
psdDsp = Display.getDisplay(this).getCurrent();
System.out.println("pausing...");
}
private Displayable psdDsp;
protected void startApp() throws MIDletStateChangeException {
Displayable dspble;
if ( null == psdDsp ) {
Form form = new Form( "BBMIDlet" );
form.append( new StringItem(null,"started") );
addCmds(form);
dspble = form;
}
else {
dspble = psdDsp;
}
setCurrent( dspble );
}
public void setCurrent( Displayable displayable ) {
Display.getDisplay( this ).setCurrent( displayable );
}
private void addCmds( Displayable displayable ) {
displayable.addCommand( new Command("Browse", Command.SCREEN, 1) );
displayable.addCommand( new Command("CanvasColor", Command.SCREEN, 2) );
displayable.addCommand( new Command("CanvasColorWorkaround", Command.SCREEN, 3) );
displayable.addCommand( new Command("CGDel", Command.SCREEN, 4) );
displayable.addCommand( new Command("CGState", Command.SCREEN, 5) );
displayable.addCommand( new Command("Pause", Command.STOP, 3) );
displayable.addCommand( new Command("Exit", Command.EXIT, 2) );
displayable.setCommandListener( this );
}
private ChoiceGroup cgd = null;
private Form cgdf = null;
private Command cgd2Cmd =
new Command("CGDel2", Command.SCREEN, 1);
private Command cgd2waCmd =
new Command("CGDel2Workaround", Command.SCREEN, 1);
private int cgDex = -1;
public void commandAction(Command command, Displayable displayable) {
String label = command.getLabel();
System.out.println("command label:"+label);
if ( "Exit".equals( label ) ) {
notifyDestroyed();
}
else if ( "Pause".equals( label ) ) {
notifyPaused();
}
else if ( "Browse".equals( label ) ) {
try {
platReq("http://www.google.com");
}
catch ( ConnectionNotFoundException cnfe ) {
System.out.println("browse exception:"+cnfe.toString());
}
}
else if ( "CanvasColor".equals( label ) ) {
Canvas c = new Cnvs( this, false );
addCmds( c );
setCurrent( c );
}
else if ( "CanvasColorWorkaround".equals( label ) ) {
Canvas c = new Cnvs( this, true );
addCmds( c );
setCurrent( c );
}
else if ( "CGDel".equals( label ) ) {
cgdf = new Form("CGDel");
TextField tf =
new TextField("random","text", 32, TextField.UNEDITABLE);
cgdf.append(tf);
cgd = new ChoiceGroup( "CGD", ChoiceGroup.POPUP );
cgd.append("1", null);
cgd.append("2", null);
cgd.append("3", null);
cgDex = cgdf.append( cgd );
cgdf.addCommand( cgd2Cmd );
cgdf.addCommand( cgd2waCmd );
cgdf.setCommandListener( this );
setCurrent( cgdf );
}
else if ( "CGDel2".equals( label ) ) {
cgd.deleteAll();
// BlackBerry 4.0.2 simulator bug, get:
// IllegalStateException: Field added to a manager while it is already parented.
//Field.setManager( Manager, int ) 3538
//Manager.insertInternal( Field, int ) 835
//PopupChoice.doInsert( int, String, Image ) 82
//BasicChoice.insert( int, String, Image ) 89
//BasicChoice.append( String, Image ) 77
//ChoiceGroup.append( String, Image ) 285
//
// also posted at:
//http://www.blackberry.com/developers/forum/thread.jsp?forum=1&thread=13272
cgd.append("4", null);
cgd.append("5", null);
cgd.append("6", null);
cgdf.removeCommand( cgd2Cmd );
cgdf.removeCommand( cgd2waCmd );
addCmds( cgdf );
}
else if ( "CGDel2Workaround".equals( label ) ) {
cgd = new ChoiceGroup( "CGD", ChoiceGroup.POPUP );
cgd.append("4", null);
cgd.append("5", null);
cgd.append("6", null);
cgdf.set( cgDex, cgd);
cgdf.removeCommand( cgd2Cmd );
cgdf.removeCommand( cgd2waCmd );
addCmds( cgdf );
}
else if ( "CGState".equals( label ) ) {
Form f = new Form("CGState");
TextField tf =
new TextField( "new value", "(none)", 32, TextField.UNEDITABLE);
f.append(tf);
ChoiceGroup cg = new ChoiceGroup( "CGS", ChoiceGroup.POPUP );
cg.append("a", null);
cg.append("b", null);
cg.append("c", null);
f.setItemStateListener( new CGStateListener( tf ) );
f.append( cg );
addCmds( f );
setCurrent( f );
}
else {
System.out.println("unknown command "+label);
}
}
static class CGStateListener implements ItemStateListener {
public CGStateListener( TextField tf ) {
this.tf = tf;
}
private TextField tf;
// BUG in BlackBerry 4.0.2 simulator:
// ItemStateListener.itemStateChanged(Item) never invoked
// also posted at:
//"itemStateChanged() method did not call"
//http://www.blackberryforums.com/developer-forum/34823-itemstatechanged-method-did-not-call.html
// and
//"How to ItemStateChange on BlackBerry 7100i"
//http://supportforums.blackberry.com/rim/board/message?board.id=java_dev&thread.id=11061
public void itemStateChanged( Item item ) {
ChoiceGroup cg = (ChoiceGroup)item;
int selDex = cg.getSelectedIndex();
String newVal = cg.getString(selDex);
tf.setString( newVal );
}
}
static class Cnvs extends Canvas {
private MIDlet midlet;
private boolean doWorkaround;
public Cnvs( MIDlet midlet, boolean doWorkaround ) {
this.midlet = midlet;
this.doWorkaround = doWorkaround;
}
Font f;
int y;
int fHt;
Graphics g;
final int STRING_ANCHOR = ( Graphics.TOP | Graphics.LEFT );
private void draw( int fg, int bg, String s ) {
int sW = f.stringWidth( s );
g.setColor( bg );
g.fillRect(0, y, sW, fHt);
g.setColor( fg );
g.drawString( s, 0, y, STRING_ANCHOR);
y += fHt;
}
private void draw( int fg, int bg, String s1, String s2 ) {
draw( fg, bg, s1 );
draw( fg, bg, s2 );
}
protected void paint(Graphics g) {
this.g = g;
f = g.getFont();
fHt = f.getHeight();
int ht = getHeight();
int wd = getWidth();
Display display = Display.getDisplay( midlet );
int fgColor =
display.getColor( Display.COLOR_FOREGROUND );
int bgColor =
display.getColor( Display.COLOR_BACKGROUND );
int hlFgColor =
display.getColor( Display.COLOR_HIGHLIGHTED_FOREGROUND );
int hlBgColor =
display.getColor( Display.COLOR_HIGHLIGHTED_BACKGROUND );
String s1 = "fgColor = " + fgColor;
String s2 = "bgColor = " + bgColor;
String s3 = "hlFgColor = " + hlFgColor;
String s4 = "hlBgColor = " + hlBgColor;
// BUG for BlackBerry 4.0.2: they're all zero (black)
// WORKAROUND IS TO SET COLORS TO SIMPLE BLACK AND WHITE
// problem also noted at:
//http:blogs.sun.com/lukas/entry/tip_using_colorschema_for_tableitem
if ( doWorkaround ) {
if ( fgColor == bgColor ) {
bgColor = 0x00ffffff; // RGB white
fgColor = 0x00000000; // RGB black
}
if ( hlFgColor == hlBgColor ) {
hlBgColor = 0x00000000; // RGB black
hlFgColor = 0x00ffffff; // RGB white
}
}
g.setClip( 0, 0, wd, ht );
g.setColor( bgColor );
g.fillRect( 0, 0, wd, ht );
y = 0;
draw( fgColor, bgColor, s1, s2 );
draw( hlFgColor, hlBgColor, s3, s4 );
}

}
public void platReq( String url ) throws ConnectionNotFoundException {
// issue posted at
//http://supportforums.blackberry.com/rim/board/message?board.id=java_dev&thread.id=27496
boolean mustExit;
// 1. works on generic J2ME devices and trivial BlackBerry MIDlets,
// freezes on BlackBerry non-trivial MIDlet with following exception
// RuntimeException: pushModalScreen called by a non-event thread
//UiEngineImpl.pushModalScreen(Screen)
//Dialog.doModal() 509
//Dialog.ask(int,String,int) 432
//MIDlet.platformRequest(String) 323
mustExit = platformRequest( url );
// separate thread for BlackBerry
//PltReq pltReq = new PltReq( this, url );
// 2. freezes on BlackBerry
//Thread prThr = new Thread( pltReq );
//prThr.start();
// 3. shows browser cofirmation dialog on BlackBerry, then freezes
//Display.getDisplay( this ).callSerially( pltReq );
//mustExit = pltReq.isExitReqd();
if ( mustExit ) {
notifyDestroyed();
}
}
// class PltReq implements Runnable {
// private final MIDlet mlt;
// private final String url;
// public PltReq( MIDlet mlt, String url) {
// this.mlt = mlt;
// this.url = url;
// }
// private boolean haveME;
// private Object sncO = new Object();
// private boolean mustExit;
// private ConnectionNotFoundException cnfe;
// public void run() {
// synchronized ( sncO ) {
// try {
// mustExit = mlt.platformRequest( url );
// }
// catch (ConnectionNotFoundException cnfe) {
// this.cnfe = cnfe;
// }
// haveME = true;
// sncO.notifyAll();
// }
// }
// public boolean isExitReqd() throws ConnectionNotFoundException {
// synchronized ( sncO ) {
// while ( !haveME ) {
// try {
// sncO.wait();
// }
// catch (InterruptedException e) {
// }
// }
// }
// if ( null != cnfe ) {
// throw cnfe;
// }
// return mustExit;
// }
// }
}


None of these issues were listed in the BlackBerry Java Development Environment Version 4.0.2 Release Notes and Known Issues List.  Given the requirement to build with the software corresponding to the target device or earlier, I don't see it as practical to expect developers to test several J2ME implementation bugs against the many RIM OS releases in order to find out what the matrix of a correctly functioning J2ME release vs. many different bugs, although it does seem a reasonable activity for RIM QA personnel.  It would seem to me that many, if not all of these issues are known inside RIM; had there been a matrix available as to what features work in what release, then I'd have saves literally weeks of time, and the application that I'm working on would be available to BlackBerry end customers so much the earlier.  I can't be the only one who's run into these sorts of issues: multiply it out and I believe it's significant.  RIM: please consider this a request for such up-to-date information on the developer website.

In many forum posts, I have seen BlackBerry folks give links to quite helpful "how-to" articles, but I have not been able to find comprehensive list of these web pages.  Again, a lot of time could have been saved with such a list and it ought to be pretty easy to generate and maintain.  If I've missed it, I'd sure appreciate a pointer to it. If it doesn't exist: RIM, please consider this a request for a page indexing all BlackBerry developer HOW TO pages.  Searching is not sufficient, it really helps to be able to scan titles.

I hope this information helps some other folks.

--David Bernstein
Highlighted
BlackBerry Development Advisor
Posts: 15,506
Registered: ‎07-09-2008
My Device: BlackBerry PRIV
My Carrier: Bell

Re: multiple 4.0.2 bugs in J2ME MIDP2 implementation - example included

Thank you for the detailed post!

Some of these are answered in more detail in other posts, but I’ve included summary results here.

1.   I have sent this issue to our development team.  In my tests this did work on a real BlackBerry handheld, but failed in the simulator.

2.  Our development team is aware of this issue.  It was recently reported.

3.  Are you able to locate the line of code or from where this exception is being triggered?

4.  I wasn’t able to reproduce this using recent versions of BlackBerry handheld software.  I tested back to version 4.3.0 and it worked fine.  Are you still seeing this problem on recent releases?

5.  Same as #4.

6.  This is fixed in version 4.3.0 of the BlackBerry Simulator.

We currently don’t have any external system where developers can look up bugs.  I’ll pass this along.

You can browse the BlackBerry Developer Knowledge base using the link below.  This allows to you view all of the DKB articles (referred to in other posts).

http://www.blackberry.com/knowledgecenterpublic/livelink.exe/fetch/2000/348583/customview.html?func=...

Mark Sohm
BlackBerry Development Advisor

Please refrain from posting new questions in solved threads.
Problem solved? Click the Accept As Solution button.
Found a bug? Report it using Issue Tracker
Developer
Developer
Posts: 39
Registered: ‎03-17-2009
My Device: Not Specified

Re: multiple 4.0.2 bugs in J2ME MIDP2 implementation - example included

Sorry for it taking a while to post back.

 

#3: It was a call to MIDlet.platformRequest(String) as the stack trace (v4.0.2) shows:

 

    UiEngineImpl.pushModalScreen(Screen) 481
    Dialog.doModal() 509
    Dialog.ask(int,String,int) 432
    MIDlet.platformRequest(String) 323

 

#4 & #5: Given the problems encountered with the JavaME UI as well as the business need to support back to 4.0.2 and the desire to eventually run with the native BlackBerry UI anyway, the resources weren't around to do further testing and case analysis.