×

Discussion Board

Page 1 of 2 12 LastLast
Results 1 to 15 of 21
  1. #1
    Regular Contributor
    Join Date
    Aug 2003
    Location
    uk
    Posts
    232

    series 60 and KEY_END

    Am i right in thinking this doesn't destroy the running midlet, but rather suspends it ?

    Does the midlet get any notification of what is happening ?

    When the user attempts to restart the midlet how can I detect that it was suspected this way and restart it ?
    (I know this is possible some games I have tested do just that)

    Lastly, any idea why, currently, if I press end at any point in my game except the main game canvas it will happy restart where it left off, but if I end while playing it will hang when I try and restart it, and I have to turn the phone off ? As this only happens on a actual phone (testing with an n-gage), its a tad tricky to debug

    Alex

  2. #2
    Super Contributor
    Join Date
    Mar 2003
    Location
    Israel
    Posts
    2,280
    You're correct, it only suspends the MIDlet.

    According to the specs, pauseApp() should be called, but this is not the case for Nokia phones. To detect this (and other things like incoming calls) you have two options: use hideNotify() for Canvas subclasses, or poll the Displayable.isShown() for the current displayable constantly.

    About your game getting stuck. Since you are not handling this pausing you're probably leaving some thread running in the background and that's what causing the problems. You have to stop (or at least change the state to a "paused" state) your main loop for it to behave correctly.

    shmoove

  3. #3
    Regular Contributor
    Join Date
    Aug 2003
    Location
    uk
    Posts
    232
    I already have hideNotify() based pause code
    Will take it out and see what happens.

    Regarding the extra threads (eg my main loop/draw thread)

    Do they get suspected as well ? or are they still trying to run in the background ?

    Assuming they are still running, should I be pausing it or killing it off ? pro's and con's of both ?

    Is the sequence for an END key suspend, followed by
    a restart as follows ?

    - END key
    - running canvas gets hideNotify()
    - midlet suspends once hideNotify() has completed

    ....
    - restart of midlet
    - previously running midlet is restarted
    - previously running canvas recieves showNotify()
    - normal running resumes ..

  4. #4
    Super Contributor
    Join Date
    Mar 2003
    Location
    Israel
    Posts
    2,280
    The thread will keep running in the background. You can easily test this by making a thread that increments a counter every second. After pausing and restarting you'll see that the thread continued counting even when the app was suspended.

    As for the sequence:
    I'm not sure but I think that startApp() might also be called when the app is restarted. This is usually what causes problems (startApp() doesn't know it's just being unpaused and starts a new thread while the old one is still alive, and havok ensues). Again, it would be easy to test this by having a MIDlet with some global string buffer, and appending the method name to this stringbuffer every time one of the aforementioned suspects are called. Then have the application display the contents of this buffer.

    shmoove

  5. #5
    Regular Contributor
    Join Date
    Aug 2003
    Location
    uk
    Posts
    232
    Well according to this test program I wrote, only hideNotify() and showNotify() are being called.

    This was tested on a n-gage, anyone else want to tell me what happens if you run this on other series 60 phones ..

    Code:
    // FileName: IncomingCallTest_Midlet.java
    
    import javax.microedition.midlet.*;
    import javax.microedition.lcdui.*;
    
    public class IncomingCallTest_Midlet extends MIDlet
    {
        public final IncomingCallTest_Canvas canvas;
    
        // ------------------------------------------------------------------------- //
        public IncomingCallTest_Midlet()
        {
            canvas = new IncomingCallTest_Canvas();
        }
        // ------------------------------------------------------------------------- //
    
    
        // ------------------------------------------------------------------------- //
        public void startApp()
        {
            canvas.c_startApp++;
            Display.getDisplay(this).setCurrent(canvas);
            canvas.start();
        }
        // ------------------------------------------------------------------------- //
    
    
        // ------------------------------------------------------------------------- //
        public void pauseApp()
        {
            canvas.c_pauseApp++;
        }
        // ------------------------------------------------------------------------- //
    
    
        // ------------------------------------------------------------------------- //
        public void destroyApp(boolean unconditional)
        {
            canvas.stop();
        }
        // ------------------------------------------------------------------------- //
        
        
        
        // ------------------------------------------------------------------------- //
        void exitRequested()
        {
            destroyApp(false);
            notifyDestroyed();
        }
        // ------------------------------------------------------------------------- //
    }
    Code:
    // FileName: IncomingCallTest_Canvas.java
    import javax.microedition.lcdui.*;
    import java.util.Vector;
    
    public class IncomingCallTest_Canvas extends Canvas implements Runnable 
    {
        public int    screenW, screenH, iLastKey=0;
        
        private static final int FRAMES_PER_SEC        = 30;
        private static final int MILLIS_PER_TICK    = 1000 / FRAMES_PER_SEC;
    
        private volatile Thread    myThread = null;
    
        public int c_startApp = 0;
        public int c_pauseApp = 0;
        public int c_hideNotify = 0;
        public int c_showNotify = 0;
    
        // ------------------------------------------------------------------------- //
        public IncomingCallTest_Canvas()
        {
            screenW        = getWidth();
            screenH        = getHeight();
        }
        // ------------------------------------------------------------------------- //
    
    
        // ------------------------------------------------------------------------- //
        protected void hideNotify()
        {
            c_hideNotify++;
        }
        // ------------------------------------------------------------------------- //
    
    
        // ------------------------------------------------------------------------- //
        protected void showNotify()
        {
            c_showNotify++;
        }
        // ------------------------------------------------------------------------- //
        
    
        // ------------------------------------------------------------------------- //
        public void start()
        {
            myThread = new Thread(this);
            myThread.start();
        }
        // ------------------------------------------------------------------------- //
        
    
        // ------------------------------------------------------------------------- //
        public void stop()
        {
            myThread = null;
        }
        // ------------------------------------------------------------------------- //
    
        
        // ------------------------------------------------------------------------- //
        public void run()
        {
            Thread currentThread = Thread.currentThread();
    
            try
            {
                while (currentThread == myThread)
                {
                    long startTime = System.currentTimeMillis();
                    repaint();
                    serviceRepaints();
    
                    long timeTaken = System.currentTimeMillis() - startTime;
                    
                    if (timeTaken < MILLIS_PER_TICK)
                    {
                        synchronized (this)
                        {
                            wait(MILLIS_PER_TICK - timeTaken);
                        }
                    }
                    else
                    {
                        currentThread.yield();
                    }
                }
            }
            catch (InterruptedException e) {   }
        }
        // ------------------------------------------------------------------------- //
        
    
        // ------------------------------------------------------------------------- //
        public void keyPressed(int keyCode)
        {
            iLastKey = keyCode;
        }
        // ------------------------------------------------------------------------- //
    
    
    
        // ------------------------------------------------------------------------- //
        public void paint(Graphics g)
        {
            // fill background with white
            g.setColor(255, 255, 255);
            g.fillRect(0, 0, screenW, screenH);
            g.setColor(0, 0, 0);
    
            g.drawString("startApp: "    + c_startApp,    5, 0, 0);
            g.drawString("pauseApp: "    + c_pauseApp,    5, 20, 0);
            g.drawString("hideNotify: " + c_hideNotify, 5, 40, 0);
            g.drawString("showNotify: " + c_showNotify, 5, 60, 0);
    
            g.drawString("keyCode: "    + iLastKey,        5, 80, 0);
        }
        // ------------------------------------------------------------------------- //
    }
    ps - yes I know it's called CallTest, but it can be used to test the END key as well. I wrote it to conform that startApp and pauseApp were not being called for incoming calls .. which as I now know .. they are not.

    Alex

  6. #6
    Regular Contributor
    Join Date
    Aug 2003
    Location
    uk
    Posts
    232
    Still stuck.

    I purged my code from 6700 lines down to less than 200
    and it still doesn't work.

    Then mysteriously it did work, and then worse it continued to work as I put features back in .. gah

    Right now the full version of my code hangs indefinitely when you try and resume it. That is until I send the next version of the game over bluetooth to the phone, at which point my game suddenly pops into the forground in a paused state (which is what its supposed todo the moment I try and resume it).

    Do I need to put something in showNotify() to make it pop the thread and display to the forground in some way ?

    Or is this some kind of messed up firmware bug ?

    This is getting too wierd.

    Alex

  7. #7
    Regular Contributor
    Join Date
    Aug 2003
    Location
    uk
    Posts
    232
    Super Smashing Great!

    Forget about bluetooth making it pop to the forground.
    Its now stopping doing that, and just hangs.

    It would be nice if this bloody phone would show any consistancy at all

    Alex

  8. #8
    Regular Contributor
    Join Date
    Aug 2003
    Location
    uk
    Posts
    232
    Call me a genius.

    Finally worked out what was going on.

    The secret to series 60 KEY_END problems comes down to ..

    Don't paint if you are not on screen.

    When the midlet is suspended, the thread keeps on running. And it keeps on trying to paint.
    I am guessing the paint requests stack up into some kind of mess somewhere ..

    Code:
    public void run()
    {
    	Thread currentThread = Thread.currentThread();
    
    	while (currentThread == myThread)
    	{
    		if (isShown()) // <-------------------- THIS IS WHAT YOU NEED :)
    		{
    
    			tick();
    
    			repaint();			
    			serviceRepaints();
    
    			<-- snip -->
    		}
    	}
    }
    Might seem obvious in retrospect, but its taken me long enough to figure it out

    Hope this helps lots of other people.

    Alex

  9. #9
    Registered User
    Join Date
    Nov 2003
    Location
    UK
    Posts
    27
    Hi Alex,
    Can you tell me what happens when you go back to the Apps menu (after pausing a game) and you press right to get to the 'Downloaded' pane.

    When I do this and then return to the Apps page again no apps appear and the phone crashes. I need to remove the battery to reset the phone!

    This doesn't happen when I don't use threads and use call serially instead but in that case the game just doesn't restart.

  10. #10
    Regular Contributor
    Join Date
    Aug 2003
    Location
    uk
    Posts
    232
    Previously the game just wouldn't restart, but now it does restart. It can take an age to do this sometimes though.

    Which phone is it crashing on ?

  11. #11
    Registered User
    Join Date
    Nov 2003
    Location
    UK
    Posts
    27
    It's on an N-Gage.

    So do you get all the games listed on the applications pane after returning from the 'downloaded' pane?

    With me they all disappear so I don't get a chance to try to restart the game.

    Actually, I've just figured out how to get the red_key exiting to work when using callSerially instead of threads so I think I'll stick with that now as it seems to runs faster as well.

    I would however love to know what was causing this problem when using threads... I suspect it might be because I had more than one active thread?

  12. #12
    Registered User
    Join Date
    Oct 2003
    Posts
    6
    I'm having a problem in that you open the application (in this case it's the demo 'Block Game' supplied by nokia for S40). Press the 'End Key', and when you try to open block game again you get a blank screen. From what I can see this uses the method alex desribed (ie use isShown() to supress repaint). Anyone got any ideas?

  13. #13
    Registered User
    Join Date
    Nov 2003
    Location
    UK
    Posts
    27
    S40 is a very different kettle of fish to S60 when it comes to pressing the end key so anything written for that would be unlikely to work properly on an S60 device.

  14. #14
    Regular Contributor
    Join Date
    Aug 2003
    Location
    uk
    Posts
    232
    I did have the case of there being no visible icons in the apps menu a few times, but then I did something (I forget what) and it changed to just hanging up when I tried to start the app I had killed with KEY_END;

    I found under series 60 when things go wrong they don't go wrong consistently.

    I would recommend you backup everything, and then start stripping everything out of your game until it works, making note of what you remove each time.

    This is obviously tedious and very time consuming, but it is a solution to most problems of not knowing the source of a problem.

  15. #15
    Registered User
    Join Date
    Aug 2004
    Posts
    15

    Similar question

    Everything in this thread is correct except on the 6600.

    The problem with it is, when a call comes in hideNotify is
    called (like usual) and the app is suspended. Then,
    when you make your choice to Accept/Decline the call
    showNotify is called immediately and you app resumes WHILE you are still in conversation.

    My question is.... is there any way to detect the hangup or
    to query whether the call is still in progress?

    And no, showNotify is NOT called on hangup.

    I ask this because if you try to play a midi while still in
    conversation it renders that midi useless for the duration
    of the app.

    If anyone has any thoughts/cheap hacks to get around this
    please let me know!

Posting Permissions

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