04-01-2009 08:04 PM
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;
// }
// }
}
04-14-2009 03:58 PM
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).
08-11-2009 08:51 PM
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.