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 ...
| |||||||
| Register | FAQ | Members List | Calendar | Mark Forums Read |
|
#1
| |||
| |||
| 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)
}
}
} 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(); Last edited by prasannavigneshr : 08-21-2007 at 02:14 AM. |
|
#2
| |||
| |||
| 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. Last edited by prasannavigneshr : 07-24-2008 at 08:42 PM. |
|
#3
| |||
| |||
| 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. |
|
#4
| |||
| |||
| 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);
} |
|
#5
| |||
| |||
| 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; Code: switch(screenSize)
{
case SMALL_SCREEN: x = 2;
break;
case LARGE_SCREEN: x = 4;
break;
case QVGA_SCREEN: x = 6;
break;
} Code: public static final int SMALL_SCREEN = 0; public static final int LARGE_SCREEN = 1; public static final int QVGA_SCREEN = 2; Code: public static final int screenSize = ${screenSize}; |
|
#6
| |||
| |||
| 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(); } } |
|
#7
| |||
| |||
| 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) {}
}
}
} |
|
#8
| |||
| |||
| 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 |
|
#9
| |||
| |||
| 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){}
} |
|
#10
| |||
| |||
| 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();
}
} |
![]() |
| Thread Tools | |
| Display Modes | |
| |
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 |
Our Partners |