×

Discussion Board

Results 1 to 13 of 13
  1. #1
    Registered User
    Join Date
    Nov 2008
    Posts
    6

    Unhappy Different behaviour between phone emulator and real S60 phone.

    Hi all,

    I wrote a sample J2ME program. This sample program will simply display a canvas. In "paint" of this canvas, I'll fill the background with red color and draw a character on it. This sample program works well in the S60 emulator. I installed the program to my phone and ran it. The program can be successfully launched,but the background was not filled with red color and the character was missing.

    Can anybody help?

    Code:
    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    
    import javax.microedition.lcdui.*;
    import javax.microedition.midlet.*;
    
    /**
     * @author Eric Xu
     */
    public class TestUnicode extends MIDlet {
        private UnicodeCanvas unicodeCanvas;
        
        public TestUnicode() {
            unicodeCanvas = new UnicodeCanvas();
        }
        public void startApp() {
            Displayable current = Display.getDisplay(this).getCurrent();
            if (current == null) {
                Display.getDisplay(this).setCurrent(unicodeCanvas);
            } else {
                Display.getDisplay(this).setCurrent(current);
            }
        }
    
        public void pauseApp() {
        }
    
        public void destroyApp(boolean unconditional) {
            notifyDestroyed();
        }
    }
    
    class UnicodeCanvas extends Canvas {
        protected void paint(Graphics g) {
            int w = getWidth();
            int h = getHeight();
    
            g.setColor(0xFF0000);
            g.fillRect(0, 0, w, h);
    
            g.setColor(0x000000);
            g.drawString("\u0283", 0, 0, Graphics.TOP);
        }
    }

  2. #2
    Super Contributor
    Join Date
    Jun 2003
    Location
    Cheshire, UK
    Posts
    7,395

    Re: Different behaviour between phone emulator and real S60 phone.

    Quote Originally Posted by hongxu_cn View Post
    Code:
        public void startApp() {
            Displayable current = Display.getDisplay(this).getCurrent();
            if (current == null) {
                Display.getDisplay(this).setCurrent(unicodeCanvas);
            } else {
                Display.getDisplay(this).setCurrent(current);
            }
        }
    Change this to:

    Code:
        public void startApp() {
            Display.getDisplay(this).setCurrent(unicodeCanvas);
        }
    Graham.

  3. #3
    Super Contributor
    Join Date
    Apr 2007
    Posts
    2,708

    Re: Different behaviour between phone emulator and real S60 phone.

    Lol I didn't have the balls to give the same advice :P
    I was wondering what the hell is he trying to do in that if-else :P but on the other hand, he lost me in that logic so I didn't want to make it worse :P
    Anyways, I hope that Graham's advice worked !

  4. #4
    Super Contributor
    Join Date
    Jun 2003
    Location
    Cheshire, UK
    Posts
    7,395

    Re: Different behaviour between phone emulator and real S60 phone.

    He's trying to detect the first time the application runs. The spec for Displayable.getCurrent() says:

    The value returned by getCurrent() may be null. This occurs after the application has been initialized but before the first call to setCurrent().
    But my guess is that getCurrent() is not returning null on his phone. Strictly... it does say "the first call", not "the first call in your code", and doesn't say that setCurrent() can't be called in the application manager's code in order to display some kind of "application starting" screen, so this might not actually be a violation of the spec.

    It is useful to detect the first startApp() call, since many devices will call startApp() more than once (such as, after each call to pauseApp()). startApp() also functions as a kind of "resumeApp()". This is a potential cause of portability issues, since some devices never call pauseApp(), and therefore call startApp() only once. Code works fine on these phones, then breaks on other phones after the app is interrupted by an incoming call. But, don't rely on the device to tell you if it's the first time or not. Create your own flag to do it.

    Code:
    private boolean initialized;
    
    public void startApp() {
        if (!initialized) {
            initialized = true;
            // do first-time-only here here
        }
        // do every-time work here
    }
    I avoid doing initialization in the MIDlet constructor, as sometimes it seems to behave a little bit strangely, as if the MIDlet isn't quite attached to the rest of the system properly yet.

    Then again, I also avoid doing initialization in startApp() - well, I do some, but as little as possible. Anything time-consuming (like, loading images, reading RMS, etc.) goes in a separate thread. This is the rule for any event (startApp() is an event handler) - return as quickly as you can, or other events can't be delivered. It's particularly significant for startApp(), as you can't display anything (paint() can't be delivered) until it exits. You really want something on the screen as quickly as possible, as it makes start-up times feel shorter.

    On the subject of start-up times, remember that Java Verified (if you need to pass it) specifies a maximum 25 seconds from selecting the application icon to the first point of interactivity (usually the main menu). JV used to specify 15 seconds, and I recommend aiming for that on Nokia devices (which are reasonably quick) so that you don't have problems when you port to slower devices.

    Graham.

  5. #5
    Registered User
    Join Date
    Nov 2008
    Posts
    6

    Re: Different behaviour between phone emulator and real S60 phone.

    Quote Originally Posted by grahamhughes View Post
    Change this to:

    Code:
        public void startApp() {
            Display.getDisplay(this).setCurrent(unicodeCanvas);
        }
    Graham.
    Hi, I tried your suggestion, it does not work.

  6. #6
    Registered User
    Join Date
    Nov 2008
    Posts
    6

    Re: Different behaviour between phone emulator and real S60 phone.

    Quote Originally Posted by grahamhughes View Post
    He's trying to detect the first time the application runs. The spec for Displayable.getCurrent() says:



    But my guess is that getCurrent() is not returning null on his phone. Strictly... it does say "the first call", not "the first call in your code", and doesn't say that setCurrent() can't be called in the application manager's code in order to display some kind of "application starting" screen, so this might not actually be a violation of the spec.

    It is useful to detect the first startApp() call, since many devices will call startApp() more than once (such as, after each call to pauseApp()). startApp() also functions as a kind of "resumeApp()". This is a potential cause of portability issues, since some devices never call pauseApp(), and therefore call startApp() only once. Code works fine on these phones, then breaks on other phones after the app is interrupted by an incoming call. But, don't rely on the device to tell you if it's the first time or not. Create your own flag to do it.

    Code:
    private boolean initialized;
    
    public void startApp() {
        if (!initialized) {
            initialized = true;
            // do first-time-only here here
        }
        // do every-time work here
    }
    I avoid doing initialization in the MIDlet constructor, as sometimes it seems to behave a little bit strangely, as if the MIDlet isn't quite attached to the rest of the system properly yet.

    Then again, I also avoid doing initialization in startApp() - well, I do some, but as little as possible. Anything time-consuming (like, loading images, reading RMS, etc.) goes in a separate thread. This is the rule for any event (startApp() is an event handler) - return as quickly as you can, or other events can't be delivered. It's particularly significant for startApp(), as you can't display anything (paint() can't be delivered) until it exits. You really want something on the screen as quickly as possible, as it makes start-up times feel shorter.

    On the subject of start-up times, remember that Java Verified (if you need to pass it) specifies a maximum 25 seconds from selecting the application icon to the first point of interactivity (usually the main menu). JV used to specify 15 seconds, and I recommend aiming for that on Nokia devices (which are reasonably quick) so that you don't have problems when you port to slower devices.

    Graham.
    Hi, I tried your suggestion, it does not work.

  7. #7
    Super Contributor
    Join Date
    Jun 2003
    Location
    Cheshire, UK
    Posts
    7,395

    Re: Different behaviour between phone emulator and real S60 phone.

    Quote Originally Posted by hongxu_cn View Post
    Code:
            g.drawString("\u0283", 0, 0, Graphics.TOP);
    Ah! This line is a problem. The anchor is incomplete.

    Code:
            g.drawString("\u0283", 0, 0, Graphics.TOP | Graphics.LEFT);
    Graham.

  8. #8
    Registered User
    Join Date
    Nov 2008
    Posts
    6

    Re: Different behaviour between phone emulator and real S60 phone.

    Quote Originally Posted by grahamhughes View Post
    Ah! This line is a problem. The anchor is incomplete.

    Code:
            g.drawString("\u0283", 0, 0, Graphics.TOP | Graphics.LEFT);
    Graham.
    Hi, actually the 1st step in "paint" is to fill the background with RED color. In emulator, it's OK. But when I deploy the program to my phone (E51, S60 v2), the program can startup but the canvas is NOT filled with RED color.

    Hope to receive your suggestions.

  9. #9
    Super Contributor
    Join Date
    Jun 2003
    Location
    Cheshire, UK
    Posts
    7,395

    Re: Different behaviour between phone emulator and real S60 phone.

    Yes, I know. Did you try the change I suggested?

  10. #10
    Registered User
    Join Date
    Nov 2008
    Posts
    6

    Re: Different behaviour between phone emulator and real S60 phone.

    Quote Originally Posted by grahamhughes View Post
    Yes, I know. Did you try the change I suggested?
    Hi, I tried and it works! I guess in real phone such as my E51, my original call to drawString throws exception. But in emulator, it won't. :-)

    Thank you for your information.

  11. #11
    Super Contributor
    Join Date
    Jun 2003
    Location
    Cheshire, UK
    Posts
    7,395

    Re: Different behaviour between phone emulator and real S60 phone.

    Because the anchor is invalid, drawString() is throwing an IllegalArgumentException. This should happen on the emulator also - it may be a bug in the emulator.

    Why do you not see the red background, even though the exception is thrown after the background is painted? Because paint() does not draw directly to the screen. It draws to a buffer. When paint() completes, the buffer is copied to the screen. This avoid flicker during repaints. However, if paint() throws an exception, it does not complete normally, and so the buffer is never copied to the screen - hence you see nothing.

    Graham.

  12. #12
    Registered User
    Join Date
    Nov 2008
    Posts
    6

    Re: Different behaviour between phone emulator and real S60 phone.

    Quote Originally Posted by grahamhughes View Post
    Because the anchor is invalid, drawString() is throwing an IllegalArgumentException. This should happen on the emulator also - it may be a bug in the emulator.

    Why do you not see the red background, even though the exception is thrown after the background is painted? Because paint() does not draw directly to the screen. It draws to a buffer. When paint() completes, the buffer is copied to the screen. This avoid flicker during repaints. However, if paint() throws an exception, it does not complete normally, and so the buffer is never copied to the screen - hence you see nothing.

    Graham.
    Mayge the reason is due to the lack of try..catch to enclose the drawString. It's my guess.

  13. #13
    Super Contributor
    Join Date
    Jun 2003
    Location
    Cheshire, UK
    Posts
    7,395

    Re: Different behaviour between phone emulator and real S60 phone.

    I would not recommend wrapping individual method calls in try..catch. You might like to wrap the entire body of the paint() method, something like:

    Code:
    protected void paint(Graphics g) {
        try {
            // do the entire painting here
        } catch (Throwable t) {
            reportException(t);
        }
    }
    Where "reportException()" might display details of the exception in an Alert, for example.

    This would not have fixed your problem, but it might have given you a clue to what the problem was.

    Graham.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
×