Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

J2ME MIDlet Calling

Options
  • 29-03-2010 11:50am
    #1
    Registered Users Posts: 23,564 ✭✭✭✭


    Hey, I have a J2ME package of a collection of games that I'm trying to get to work.

    Basically I'm trying to implement the main menu so I can pick between whatever game I want, but I'm running into an error.

    I've read up on it and from what I can see you can only call a MIDlet from another MIDlet if they're in the same package.

    In the case below I want to call the HangMan.java class to start when the user selects 'Hangman' from the main menu:
    package packageone;
    import javax.microedition.lcdui.*;
    import javax.microedition.midlet.*;
    
    public class MainMenu extends MIDlet implements CommandListener {
        // display manager
        Display display = null;
        
        // a menu with items
        List menu = null; // main menu
    
        // textbox
        TextBox input = null;
    
    
         //command
        static final Command enterCommand = new Command("Enter", Command.OK, 0);
        static final Command backCommand = new Command("Back", Command.BACK, 1);
        static final Command mainMenuCommand = new Command("Main", Command.SCREEN, 2);
        static final Command exitCommand = new Command("Exit", Command.STOP, 3);
        String currentMenu = null;
    
        
    
        // constructor.
        public MainMenu() {
        }
    
        /**
         * Start the MIDlet by creating a list of items and associating the
         * exit command with it.
         */
        public void startApp() throws MIDletStateChangeException {
          display = Display.getDisplay(this);
    
          menu = new List("Menu Items", Choice.IMPLICIT);
          menu.append("Hangman", null);
          menu.append("Space Wars", null);
          menu.append("Who Wants to be a Millionaire?", null);
          menu.append("High Scores", null);
          menu.addCommand(enterCommand);
          menu.addCommand(exitCommand);
          menu.setCommandListener(this);
    
          mainMenu();
        }
    
        public void pauseApp() {
          display = null;
          menu = null;
          input = null;
        }
    
        public void destroyApp(boolean unconditional) {
          notifyDestroyed();
        }
    
        // main menu
        void mainMenu() {
          display.setCurrent(menu);
          currentMenu = "Main"; 
        }
    
        /**
         * a generic method that will be called when selected any of
         * the items on the list.
         */
    //    public void prepare() {
    //       input = new TextBox("Enter some text: ", "", 5, TextField.ANY);
    //       input.addCommand(backCommand);
    //       input.setCommandListener(this);
    //       input.setString("");
    //       display.setCurrent(input);
    //    }
    
        /**
         * Test item1.
         * @throws ClassNotFoundException 
         */
    
    [COLOR="Red"]   
        public void testHangman(){  
    
        	Thread aThread = new Thread()
        	{
        	public void run()
        	{
    
        	try
        	{
        	Class c = Class.forName("packageone.HangMan");
        	MIDlet m = (MIDlet) c.newInstance();
        	HangMan b = (HangMan) c.newInstance();
        	}
        	catch(Exception e)
        	{
        	//form.append("Couldnt launch MIDlet 'B'");
        	System.out.println("Couldnt launch HangMan");
        	System.out.println(e.getMessage());
        	e.printStackTrace();
        	}
        	}
        	};
        	aThread.start();
        [/COLOR]
    
        		
        		
          
          currentMenu = "item1";
        }
       
        /**
         * Test item2.
         */
        public void testItem2() {
          
           currentMenu = "item2"; 
        }
    
        /**
         * Test item3.
         */
        public void testItem3() {
           
           currentMenu = "item3"; 
        }
    
    
       /**
        * Handle events.
        */  
       public void commandAction(Command c, Displayable d) {
          String label = c.getLabel();
          if (label.equals("Exit")) {
             destroyApp(true);
          } else if (label.equals("Back")) {
              if(currentMenu.equals("item1") || currentMenu.equals("item2") ||
                 currentMenu.equals("item3") || currentMenu.equals("item4"))  {
                // go back to menu
                mainMenu();
              } 
    
          } else {
             List down = (List)display.getCurrent();
             switch(down.getSelectedIndex()) {
               case 0: testHangman();break;
               case 1: testItem2();break;
               case 2: testItem3();break;
             }
                
          }
      }
    }
    

    The bit I have in red there is where I'm trying to call it, I'm really not sure whether to use a try/catch or declare an exception.

    I keep getting the following error:
    Couldnt launch HangMan
    Application not authorized to access the restricted API
    java.lang.SecurityException: Application not authorized to access the restricted API
    at com.sun.midp.security.SecurityToken.checkIfPermissionAllowed(+40)
    at com.sun.midp.security.SecurityToken.checkIfPermissionAllowed(+7)
    at com.sun.midp.midletsuite.MIDletSuiteImpl.checkIfPermissionAllowed(+8)
    at com.sun.midp.midlet.MIDletState.<init>(+83)
    at javax.microedition.midlet.MIDletProxy.<init>(+5)
    at javax.microedition.midlet.MIDlet.<init>(+13)
    at packageone.HangMan.<init>(+4)
    at java.lang.Class.runCustomCode(+0)
    at packageone.MainMenu$1.run(+10)


Comments

  • Registered Users Posts: 134 ✭✭anton


    I wouldn't try to create another instance of MIDlet class, I suppose there could be just one at any given time created by VM itself.

    Essentially there are two options to do something like that:

    1. Enumerate all midlets in JAD file, so the phone will give you sub-menu of all midlets when you click on midlet suite.

    2. Modify your games, so they're not separate midlets but rather Runnable's or whatever.


  • Registered Users Posts: 23,564 ✭✭✭✭Frisbee


    anton wrote: »
    I wouldn't try to create another instance of MIDlet class, I suppose there could be just one at any given time created by VM itself.

    Essentially there are two options to do something like that:

    1. Enumerate all midlets in JAD file, so the phone will give you sub-menu of all midlets when you click on midlet suite.

    2. Modify your games, so they're not separate midlets but rather Runnable's or whatever.

    Sorry I'm fairly new to using J2ME and MIDlets so not entirely sure what you mean here.

    Are you saying I can't invoke a MIDlet class from another one?
    All I'm trying to do is create a menu system that will call one of the three games to begin when it's chosen from the menu.


  • Registered Users Posts: 18,272 ✭✭✭✭Atomic Pineapple


    java.lang.SecurityException: Application not authorized to access the restricted API

    Do you need to set up permissions of some sort to allow access to the API?


  • Registered Users Posts: 23,564 ✭✭✭✭Frisbee


    draffodx wrote: »
    Do you need to set up permissions of some sort to allow access to the API?

    I was actually looking into this earlier, I'll have a look at it and post back how I did.


  • Registered Users Posts: 23,564 ✭✭✭✭Frisbee


    Ok I think I've found what permissions I need to add:
    MIDlet-Permissions: javax.microedition.io.Connector.socket,javax.microedition.io.Connector.http
    MIDlet-Permissions-Opt: javax.microedition.media.Player,javax.microedition.media.Manage,javax.microedition.media.control.VideoControl.getSnapshot,javax.microedition.media.control.RecordControl
    

    Now this is going to sound like a really stupid question but how exactly do I add permission in Eclipse?

    I've never had to do it before and I've googled it and can't find anything...


  • Advertisement
  • Registered Users Posts: 134 ✭✭anton


    You can't (easily) call one midlet from the other, adding permissions won't help. I assume you're using eclipse MTJ?

    Click on your "Application descriptor" in your project, select MIDlet tab and add all midlets you have in your project.

    Once you copied the jar to your phone and attempted to start the midlet, the phone will give you an additional menu allowing to choose a midlet you'd like to run.


  • Registered Users Posts: 23,564 ✭✭✭✭Frisbee


    anton wrote: »
    Click on your "Application descriptor" in your project, select MIDlet tab and add all midlets you have in your project.

    This didn't work either..

    So if you can't call one MIDlet from another how are you supposed to, for example, implement a menu system made up of multiple files? Or are you going to have to have all the code in one MIDlet?


  • Registered Users Posts: 134 ✭✭anton


    Yep, you'd normally have all code in one midlet. You can have several classes of course, and you can logically split functionality any way you like.

    However, you'd have one entry point into your code. Think of main() in C program.
    Frisbee wrote: »
    This didn't work either..

    So if you can't call one MIDlet from another how are you supposed to, for example, implement a menu system made up of multiple files? Or are you going to have to have all the code in one MIDlet?


  • Registered Users Posts: 23,564 ✭✭✭✭Frisbee


    Ah ok. so I'd be better off breaking down the individual component game files into class files and just calling them all through the 'Main Menu' MIDlet?


  • Registered Users Posts: 134 ✭✭anton


    You might do that. But it's quite easy to add several MIDlet-1, MIDlet-2, etc lines to your jar manifest. It'll make single jar file appear as a collection of midlets. Eariler you said you had problem doing that, so what was the problem?
    Frisbee wrote: »
    Ah ok. so I'd be better off breaking down the individual component game files into class files and just calling them all through the 'Main Menu' MIDlet?


  • Advertisement
  • Registered Users Posts: 23,564 ✭✭✭✭Frisbee


    anton wrote: »
    You might do that. But it's quite easy to add several MIDlet-1, MIDlet-2, etc lines to your jar manifest. It'll make single jar file appear as a collection of midlets. Eariler you said you had problem doing that, so what was the problem?

    I've taken screenshots of what I did jsut so you can tell me if I'm doing it correctly:


    This is where I added the first MIDlet:

    MIDlet1.jpg


    Then I added the second MIDlet:

    MIDlet2.jpg



    And I'm still getting these errors:

    MIDletErrors.jpg


    Cheers for all the help so far man!


  • Registered Users Posts: 134 ✭✭anton


    Do you still have that in your code?

    Class c = Class.forName("packageone.HangMan");
    MIDlet m = (MIDlet) c.newInstance();
    HangMan b = (HangMan) c.newInstance();

    Adding MIDlet-... stuff won't allow you to call midlet from midlet, instead it sort-of replaces the menu you're trying to make.

    For example you have three games: Hangman, Tic-Tac-Toe,Bingo in one jar file.

    Your manifest will have following lines:

    MIDlet-Name: ThreeGames
    MIDlet-1: Hangman,/hangman.png,packageone.hangman.HangManMidlet
    MIDlet-2: Tic-Tac-Toe,/hangman.png,packageone.ttt.TttMidlet
    MIDlet-3: Bingo,/hangman.png,packageone.bingo.BingoMidlet

    Once you transfer your file (say threegames.jar) onto your phone, you'll see
    a new item in your Applications menu called 'ThreeGames'. If you try to
    lanuch this midlet, the phone OS will produce a menu with three items:
    Hangman, Tic-Tac-Toe, Bingo. Depending on what you select from menu it'll
    launch appropriate midlet.


  • Registered Users Posts: 23,564 ✭✭✭✭Frisbee


    anton wrote: »
    Do you still have that in your code?

    Class c = Class.forName("packageone.HangMan");
    MIDlet m = (MIDlet) c.newInstance();
    HangMan b = (HangMan) c.newInstance();

    Yeah I still have that.
    anton wrote: »
    Your manifest will have following lines:

    MIDlet-Name: ThreeGames
    MIDlet-1: Hangman,/hangman.png,packageone.hangman.HangManMidlet
    MIDlet-2: Tic-Tac-Toe,/hangman.png,packageone.ttt.TttMidlet
    MIDlet-3: Bingo,/hangman.png,packageone.bingo.BingoMidlet

    When you say Manifest do you mean what's under the MIDlet Tab in the Application Descriptor?


  • Registered Users Posts: 134 ✭✭anton


    Yep. The Application Discriptor in MTJ is a convinience tool of sorts, amongst other things it allows you to generate/edit jar manifest.

    Once you package your code into a jar file (which is essentially a zip archive) there will be a text file in it, called META-INF/manifest.mf Amongst other info it'll contain MIDlet-... lines int it.
    Frisbee wrote: »
    When you say Manifest do you mean what's under the MIDlet Tab in the Application Descriptor?


  • Registered Users Posts: 134 ✭✭anton


    Frisbee wrote: »
    Yeah I still have that.

    Remove it, either have several distinct midlet classes and have several midlets described int your manifest, or have one midlet and make it call into other classes that implement your games.


Advertisement