IT Community - Software Programming, Web Development and Technical Support

J2ME Tips & Tricks

This is a discussion on J2ME Tips & Tricks within the J2ME forums, part of the Mobile Software Development category; The Problem: J2ME's TimerTask is run on a background thread independant of the event thread thus causing potential synchronization ...


Go Back   IT Community - Software Programming, Web Development and Technical Support > Software Development > Mobile Software Development > J2ME

Register FAQ Members List Calendar Mark Forums Read
  #1  
Old 08-21-2007, 02:12 AM
prasannavigneshr prasannavigneshr is offline
D-Web Incredible
 
Join Date: Feb 2007
Posts: 1,264
prasannavigneshr is on a distinguished road
Send a message via MSN to prasannavigneshr
Thumbs up J2ME Tips & Tricks

The Problem:

J2ME's TimerTask is run on a background thread independant of the event thread thus causing potential synchronization problems with things like drawing to the screen etc.

The solution:
Derive from the TimerTask a threadsafe TimerTask that calls itself serially thus placing itself in the event thread. The following derived class has an option to run serialized on the event thread or as a normal TimerTask.

Code:
import java.util.TimerTask;
public class GeneralTimerTask extends TimerTask
{ 
private boolean runOnEventThread;
 public GeneralTimerTask(boolean runOnEventThread)
 { 
this.runOnEventThread= runOnEventThread;
 }

 private Thread timerThread; 
public void run()
 { 
if (timerThread == null)
 { // first run through will be on the timer thread 
 timerThread = Thread.currentThread();
 } 
if (timerThread==Thread.currentThread() && runOnEventThread) 
{ 
MApp.mainApp.d.callSerially(this); 
}
 else
 {
 (call whatever handler/function you want to execute here) 
}
 } 
}
Use this GeneralTimerTask just like any other TimerTask:

Code:
Timer timer;
 GeneralTimerTask timerTask; 
long updateDelay = 500; 
// milliseconds ... 
timerTask = new GeneralTimerTask(true); 
timer.schedule(timerTask, updateDelay);
// GeneralTimerTask:run will now be called every 500ms ... 
timerTask.cancel();
Thanks
__________________
Prasanna Vignesh
MCPD | Web Developer

Last edited by prasannavigneshr : 08-21-2007 at 02:14 AM.
Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #2  
Old 08-21-2007, 02:17 AM
prasannavigneshr prasannavigneshr is offline
D-Web Incredible
 
Join Date: Feb 2007
Posts: 1,264
prasannavigneshr is on a distinguished road
Send a message via MSN to prasannavigneshr
Smile Re: J2ME Tips & Tricks

Adding JSR75 Contacts:

To set up contacts for the WTK or Sprint emulator for JSR75 access you need to make some vcards. The vcards should have the following format:

begin:vcard
fn:Will Perone
n:Perone;
Will;;
TEL;HOME;
VOICE:123-456-7890 TEL;
CELL;
VOICE:987-654-3210 URL;
HOME:Prasanna Vignesh EMAIL;INTERNET:mail@office.
version:2.1
end:vcard

The TEL, UTL and EMAIL lines are all optional (and I think the n and fn too). You can go here to find out more about the vcard format.
The cards should be saved in .vcf files (If you have Outlook or Outlook Express you can create contacts in there and save them as vcard files as well). Put the vcards in the (toolkit)/appdb/(phone)/pim/contacts/Contacts and that's it! Now your j2me app will be able to access some contacts in the emulator. You can go here for more info.
__________________
Prasanna Vignesh
MCPD | Web Developer

Last edited by prasannavigneshr : 07-24-2008 at 08:42 PM.
Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #3  
Old 08-21-2007, 02:24 AM
prasannavigneshr prasannavigneshr is offline
D-Web Incredible
 
Join Date: Feb 2007
Posts: 1,264
prasannavigneshr is on a distinguished road
Send a message via MSN to prasannavigneshr
Thumbs up Re: J2ME Tips & Tricks

Script Error 909:

Figuring out what is going on when we get a 909 error while trying to install our application may take quite some time (trust me). Here are some things to check:

If this is a developer phone, make sure you have activated it on the Sprint Developer Site. When you type in the ESN for activation (this is on the back of the phone behind the battery) make sure the letters are the correct case (usually upper case); typing in the wrong case letters will not activate the phone. Also there will be no notification sent when the phone is activated but usually it's the same day.

If the phone is not developer enabled and you have an application with a developer certificate (not a Verisign certificate) then you will also get this error. This can be eliminated by removing the certificate and Midlet-Permissions from the jad altogether.

Also on some phones (Sanyo mainly) this error can come up if the manifest file and the jad file have their Midlet-Permissions mismatching. According to the Manifest file format, the lines are supposed to wrap at 72 characters and the next line will insert a space and continue the previous line. The jad file will end up with one long line for the Midlet-Permissions while the Manifest have a bunch of lines. This can cause some phones to give a 909 error. To correct it you need to actually go back into the Manifest file in the jar and take out the line breaks/spaces so that Midlet-Permissions is exactly the same as the jad file. After you do this you need to make sure you update the jad with the correct jar size. Unfortunately there is no way to get the jad file to do multiple lines for a property so you will likely need a post processing step in your build process to unjar, correct the manifest, rejar then rewrite the jad.

On a related note, you will get a 910 error if you have no certificate in the jad but have Midlet-Permissions.

Also Make sure that the phone hasn't cached the jad/jar otherwise it will not download the new version of the program. You can do this by adding a ?(some letter) to the end of the url to grab the jad from on the phone.

Hope Usefull.
__________________
Prasanna Vignesh
MCPD | Web Developer
Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #4  
Old 08-21-2007, 02:48 AM
prasannavigneshr prasannavigneshr is offline
D-Web Incredible
 
Join Date: Feb 2007
Posts: 1,264
prasannavigneshr is on a distinguished road
Send a message via MSN to prasannavigneshr
Thumbs up Re: J2ME Tips & Tricks

Image Scaling in J2ME:

This function scales images using an optimized form of bresenham's formula. You can also add bilinear sampling and such to it but I figured since it's on a cell phone it won't matter much and will also cause it to be slower.

Code:
public static Image scaleImage(Image original, int newWidth, int newHeight)
 {
   int[] rawInput = new int[original.getHeight() * original.getWidth()];
   original.getRGB(rawInput, 0, original.getWidth(), 0, 0, original.getWidth(), original.getHeight());
   int[] rawOutput = new int[newWidth*newHeight];
  // YD compensates for the x loop by subtracting the width back out 
  int YD = (original.getHeight() / newHeight) * original.getWidth() - original.getWidth(); 
  int YR = original.getHeight() % newHeight; int XD = original.getWidth() / newWidth;
   int XR = original.getWidth() % newWidth;
   int outOffset= 0;
   int inOffset= 0;
   for (int y= newHeight, YE= 0; y > 0; y--)
   {
      for (int x= newWidth, XE= 0; x > 0; x--)
         {
             rawOutput[outOffset++]= rawInput[inOffset]; 
               inOffset+=XD; 
               XE+=XR;
                if (XE >= newWidth)
                { 
                  XE-= newWidth; inOffset++; 
                }
      }
      inOffset+= YD; 
     YE+= YR;
     if (YE >= newHeight)
     {
        YE -= newHeight; inOffset+=original.getWidth();
     }
  }
  return Image.createRGBImage(rawOutput, newWidth, newHeight, false);
}
__________________
Prasanna Vignesh
MCPD | Web Developer
Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #5  
Old 08-21-2007, 02:54 AM
prasannavigneshr prasannavigneshr is offline
D-Web Incredible
 
Join Date: Feb 2007
Posts: 1,264
prasannavigneshr is on a distinguished road
Send a message via MSN to prasannavigneshr
Thumbs up Re: J2ME Tips & Tricks

J2ME Tips & tricks:

Consider the following two pieces of code

Code:
if (screenSize==SMALL_SCREEN)
  x = 2; 
   else  if (screenSize==LARGE_SCREEN)
      x = 4;
        else  if (screenSize==QVGA_SCREEN) x = 6;
And

Code:
switch(screenSize)
{
     case SMALL_SCREEN: x = 2;
     break;
     case LARGE_SCREEN: x = 4;
     break;
     case QVGA_SCREEN: x = 6;
     break;
}
Normally if the SCREEN variables are defined in order, a switch statement will optimize better than the if-else chain:

Code:
public static final int SMALL_SCREEN = 0;
public static final int LARGE_SCREEN = 1;
public static final int QVGA_SCREEN = 2;
This is because the switch statement will optimize to become a table in the bytecode. You can actually optimize this further though if you consider that ScreenSize is always the same value at run time (either SMALL_SCREEN, LARGE_SCREEN or QVGA_SCREEN).

Code:
public static final int screenSize = ${screenSize};
In this case an if-else chain will actually optimize better because it will remove the dead code that's never called thus eliminating the entire check.
__________________
Prasanna Vignesh
MCPD | Web Developer
Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #6  
Old 08-21-2007, 03:15 AM
prasannavigneshr prasannavigneshr is offline
D-Web Incredible
 
Join Date: Feb 2007
Posts: 1,264
prasannavigneshr is on a distinguished road
Send a message via MSN to prasannavigneshr
Default Re: J2ME Tips & Tricks

Draw mutable image on a canvas


import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class MutableImageWithCanvas extends MIDlet
{
private Display display; // The display
private ImageCanvas canvas; // Canvas

public MutableImageWithCanvas()
{
display = Display.getDisplay(this);
canvas = new ImageCanvas(this);
}

protected void startApp()
{
display.setCurrent( canvas );
}

protected void pauseApp()
{ }

protected void destroyApp( boolean unconditional )
{ }

public void exitMIDlet()
{
destroyApp(true);
notifyDestroyed();
}
}

/*--------------------------------------------------
* Class ImageCanvas
*
* Draw mutable image
*-------------------------------------------------*/
class ImageCanvas extends Canvas implements CommandListener
{
private Command cmExit; // Exit midlet
private MutableImage midlet;
private Image im = null;
private String message = "Core J2ME";

public ImageCanvas(MutableImage midlet)
{
this.midlet = midlet;

// Create exit command & listen for events
cmExit = new Command("Exit", Command.EXIT, 1);
addCommand(cmExit);
setCommandListener(this);

try
{
// Create mutable image
im = Image.createImage(80, 20);

// Get graphics object to draw onto the image
Graphics graphics = im.getGraphics();

// Specify a font face, style and size
Font font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
graphics.setFont(font);

// Draw a filled (black) rectangle
graphics.setColor(0, 0, 0);
graphics.fillRoundRect(0,0, im.getWidth()-1, im.getHeight()-1, 20, 20);

// Center text horizontally in the image. Draw text in white
graphics.setColor(255, 255, 255);
graphics.drawString(message,
(im.getWidth() / 2) - (font.stringWidth(message) / 2), 0,
Graphics.TOP | Graphics.LEFT);
}
catch (Exception e)
{
System.err.println("Error during image creation");
}
}

/*--------------------------------------------------
* Draw mutable image
*-------------------------------------------------*/
protected void paint(Graphics g)
{
// Center the image on the display
if (im != null)
g.drawImage(im, getWidth() / 2, getHeight() / 2, Graphics.VCENTER | Graphics.HCENTER);
}

public void commandAction(Command c, Displayable d)
{
if (c == cmExit)
midlet.exitMIDlet();
}
}
__________________
Prasanna Vignesh
MCPD | Web Developer
Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #7  
Old 08-21-2007, 03:27 AM
prasannavigneshr prasannavigneshr is offline
D-Web Incredible
 
Join Date: Feb 2007
Posts: 1,264
prasannavigneshr is on a distinguished road
Send a message via MSN to prasannavigneshr
Thumbs up Re: J2ME Tips & Tricks

Load Image - J2ME
Code:
import java.io.*;

import javax.microedition.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

public class ImageLoader extends MIDlet
    implements CommandListener, Runnable {
  private Display mDisplay;
  private Form mForm;
  
  public ImageLoader() {
    mForm = new Form("Connecting...");
    mForm.addCommand(new Command("Exit", Command.EXIT, 0));
    mForm.setCommandListener(this);
  }
  
  public void startApp() {
    if (mDisplay == null) mDisplay = Display.getDisplay(this);
    mDisplay.setCurrent(mForm);
    
    // Do network loading in a separate thread.      
    Thread t = new Thread(this);
    t.start();
  }
  
  public void pauseApp() {}

  public void destroyApp(boolean unconditional) {}
  
  public void commandAction(Command c, Displayable s) {
    if (c.getCommandType() == Command.EXIT)
      notifyDestroyed();
  }
  
  public void run() {
    HttpConnection hc = null;
    DataInputStream in = null;
    
    try {
      String url = getAppProperty("ImageLoader-URL");
      hc = (HttpConnection)Connector.open(url);
      int length = (int)hc.getLength();
      byte[] data = null;
      if (length != -1) {
        data = new byte[length];
        in = new DataInputStream(hc.openInputStream());
        in.readFully(data);
      }
      else {
        // If content length is not given, read in chunks.
        
        
        int chunkSize = 512;
        int index = 0;
        int readLength = 0;
        in = new DataInputStream(hc.openInputStream());
        data = new byte[chunkSize];
        do {
          if (data.length < index + chunkSize) {
            byte[] newData = new byte[index + chunkSize];
            System.arraycopy(data, 0, newData, 0, data.length);
            data = newData;
          }
          readLength = in.read(data, index, chunkSize);
          index += readLength;
        } while (readLength == chunkSize);
        length = index;
      }
      Image image = Image.createImage(data, 0, length);
      ImageItem imageItem = new ImageItem(null, image, 0, null);
      mForm.append(imageItem);
      mForm.setTitle("Done.");
    }
    catch (IOException ioe) {
      StringItem stringItem = new StringItem(null, ioe.toString());
      mForm.append(stringItem);
      mForm.setTitle("Done.");
    }
    finally {
      try {
        if (in != null) in.close();
        if (hc != null) hc.close();
      }
      catch (IOException ioe) {}
    }
  }
}
__________________
Prasanna Vignesh
MCPD | Web Developer
Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #8  
Old 08-21-2007, 03:38 AM
prasannavigneshr prasannavigneshr is offline
D-Web Incredible
 
Join Date: Feb 2007
Posts: 1,264
prasannavigneshr is on a distinguished road
Send a message via MSN to prasannavigneshr
Default Re: J2ME Tips & Tricks

Image Transparency in J2ME

Firstly, the native transparent file format in MIDP is the .png file. On the Series 40 (7210, 6610, 6100), a .png file allows not only entirely transparent pixels, but also translucent ones. Unfortunately, with the Series 60 (3650, 7650) as far as I can see, only transparent pixels can be used - which is the main thing.

Save a .png file with a transparency mask. To do this in paint shop pro:

1. File->New Image.
2. Draw Image.
3. Masks->New->Show All.
4. Masks->View Mask
5. Masks->Edit
6. The colour palette will change to grey scale - select absolute black (0,0,0)
7. Paint over the pixels in your image that you wish to be invisible.
8. Masks->Save to Alpha Channel.
9. Hit OK twice.
10. Save the image.

To use the newly created image in your app.

1. Make sure you have the path with the graphics files mounted (right click on File Systems->Mount->Local Directory)
2. Include the .png file in your jar file - In Sun One, right click the Midlet Suite Icon and select 'Edit Suite', then the tab 'Jar Contents'. Browse on the left side to the newly mounted directory, and select the png file. Click 'Add'. Click 'OK'.
3. Create a class variable: [Image MadCrazyDudeImage=null;]
4. In your Class constructor (or wherever appropriate), create the image from the .png file. [MadCrazyDudeImage= Image.createImage("/MadCrazyDude.png");] It is vital that the case of the name is the correct case, and that you preceed the filename with the forward slash.
5. Create a DirectGraphics object in your paint routine, and initialise it: [DirectGraphics dg; dg=DirectUtils.getDirectGraphics(graphics);]
6. Draw the image to the canvas. [dg.drawImage(MadCrazyDudeImage, 0, 0, Graphics.TOP | Graphics.LEFT, 0);]

If this doesn't work, it may be that you are trying to read the graphics out of a graphics strip first (this is the part that threw me when porting my first Series 40 to a Series 60 phone). To do this, you cannot use a Graphics object alone to create your individual images. They have to be passed through a DirectGraphics object for the transparency to be maintained. I include the code that I use below:

In the class global area:

Image imReceptors=null;
Image Receptors[]=new Image[12];

imReceptors=Image.createImage("/S60receptors.png");
for (int i=0; i<12; i++)
{
Receptors[i]=DirectUtils.createImage(21, 20, 0x00000000);
Graphics g = Receptors[i].getGraphics();
DirectGraphics dgtemp=DirectUtils.getDirectGraphics(g);
dgtemp.drawImage(imReceptors, -21*i, 0, Graphics.TOP | Graphics.LEFT, 0);
}
imReceptors=null;

It's best to put a try...catch block around your graphics creation code to make sure that there isn't a problem there (i usually just add a System.out.println("Graphics Error here") type of statemnt to the catch block). If using Sun One, you may be getting frustrated because Sun One is expecting the graphics to be located a sub folder up from where you would expect it to look for them. Try placing the images into the parent directory of your app project if Sun One is struggling to find them in the main app directory.


Thanks
__________________
Prasanna Vignesh
MCPD | Web Developer
Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #9  
Old 08-21-2007, 06:54 AM
itbarota itbarota is offline
D-Web Architect
 
Join Date: Jun 2007
Posts: 542
itbarota is on a distinguished road
Default Using ChoiceGroup in J2ME

This j2ME tips illustrates method of using a ChoiceGroup in mobile applications. ChoiceGroup is a group of selectable elements intended to be placed within a Form.
Code:
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class ChoiceGroupDemo extends MIDlet implements CommandListener {
    
    private boolean boolMotion=false;
    Display mDisplay;
    
    Form frm;
    
    ChoiceGroup cg;
    Command cmd;
    
    ChoiceGroupDemo() {
        frm=new Form("Choice Group Demo");
        cg=new ChoiceGroup("Choose Movie:",Choice.MULTIPLE);
        cmd=new Command("OK",Command.OK,1);
        
        cg.append("Horror",null);
        cg.append("Comedy",null);
        cg.append("Action",null);
        frm.append(cg);
        frm.setCommandListener(this);
    }
    
    
    public void commandAction(Command c, Displayable d) {
        
        for(int i=0;i<3;i++) {
            if(cg.isSelected(i)) {
                System.out.println("u selected :" + 
                        cg.getString(elementNum));
                
                return;
            }
        }
    }
    
    public void startApp() {
        mDisplay = Display.getDisplay(this);
        mDisplay.setCurrent(frm);
    }
    public void pauseApp() {}
    public void destroyApp(boolean unconditional){}
}
Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #10  
Old 08-21-2007, 06:56 AM
itbarota itbarota is offline
D-Web Architect
 
Join Date: Jun 2007
Posts: 542
itbarota is on a distinguished road
Default A method of using differnet fonts in Java ME

The Java tips describes methods of using different fonts in J2ME application. The Font class represents fonts and font metrics. Fonts cannot be created by applications. The setFont(Font font) method of graphic class sets the font for all subsequent text rendering operations. And there is no call to showNotify and hideNotify method on some the device. This application will help game developer to find out the exact behaviour of mobile device.
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
Code:
public class FontDemo extends MIDlet {
    
    private boolean boolMotion=false;    
    private int iX=10, iY=60;
    
    Display mDisplay;
    Thread th;
    public void destroyApp(boolean unconditional){}
    
    public void pauseApp() {}
    
    public void startApp() {
        
        mDisplay = Display.getDisplay(this);
        final MyCanvas can = new MyCanvas();
        mDisplay.setCurrent(can);
        
    }
}

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class MyCanvas extends Canvas {
    
    Font font;
    String msg;
    public MyCanvas() {
        
        font=Font.getFont(Font.FACE_MONOSPACE,
                Font.STYLE_ITALIC, Font.SIZE_LARGE);
        msg = "Font:FACE_MONOSPACE  Font.STYLE_ITALIC  Font.SIZE_LARGE";
    }
    
    public void paint(Graphics g) {
        g.setFont(font);
        g.drawString(msg,0,10,g.TOP|g.LEFT);
        g.drawString("press NUM KEY: 1 2 or 3",0,80,g.TOP|g.LEFT);
    }
    
    void changeValue(int change) {
        switch(change) {
            case '1':
                font=Font.getFont(Font.FACE_MONOSPACE, 
                        Font.STYLE_ITALIC, Font.SIZE_LARGE) ;
                msg="Font:FACE_MONOSPACE  Font.STYLE_ITALIC "+
                        "Font.SIZE_LARGE";
                break;
            case '2':
                font=Font.getFont(Font.FACE_PROPORTIONAL, 
                        Font.STYLE_ITALIC, Font.SMALL) ;
                msg = "Font:FACE_PROPORTIONAL Font.STYLE_ITALIC "+
                      "Font.SIZE_SMALL";
                break;
            case '3':
                font=Font.getFont(Font.FACE_SYSTEM , 
                        Font.STYLE_BOLD, Font.SIZE_LARGE) ;
                msg="Font:FACE_SYSTEM  Font.STYLE_BOLD "+
                        "Font.SIZE_LARGE";
                break;
        }
    }
    
    
    //Handling keyEvents
    protected void keyPressed(int keyCode) {
        changeValue(keyCode);
        repaint();
    }
    
}
Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off

Similar Threads
Thread Thread Starter Forum Replies Last Post
C# .Net Tips & Tricks oxygen C# Programming 85 01-08-2009 12:25 AM
SAP Tips & Tricks leoraja8 Operating Systems 0 03-29-2008 12:11 AM
PHP Tips and Tricks Sabari PHP Programming 20 12-18-2007 05:26 AM
.NET tricks & Tips Karpagarajan VB.NET Programming 1 04-23-2007 08:17 AM
SEO Tips & Tricks spid4r Search Engine Optimization 0 03-08-2007 11:03 PM


All times are GMT -7. The time now is 12:29 PM.


Copyright ©2004 - 2007, DiscussWeb. All Rights Reserved.
Our Partners
One Way Moving Companies | Stamford Dentist | Euro Millions Lottery | Home Loans| Furniture

SEO by vBSEO 3.0.0