Sunday, August 23, 2009

Fullscreen Landscape

Most handset screens are portrait: higher than wider. What if you want to show content in landscape mode? Since MIDP 2.0 we can use an Sprite to rotate an image in 90 degrees.


First thing we need is an Image of the correct size. Following code could be inside the constructor of a class that extends Canvas - considering an Sprite and an Image attributes:



int width = Math.max(super.getWidth(), super.getHeight());
int height = Math.min(super.getWidth(), super.getHeight());
screen = Image.createImage(width, height);
sprite = new Sprite(screen);
if (super.getWidth() < super.getHeight()) { // portrait screen
sprite.setTransform(Sprite.TRANS_ROT90);
sprite.setPosition(0, 0);
}

When painting your content use the mutable Image Graphics, then update the sprite with the image like bellow.



protected void paint(Graphics g1) {
Graphics g = screen.getGraphics();
// ... do your drawing
this.sprite.setImage(screen, screen.getWidth(), screen.getHeight());
sprite.paint(g1);
}

How can you use the biggest possible area on the handset display?



  1. Do not setTitle on your Canvas

  2. Do not addCommand to your Canvas

  3. Call setFullScreenMode(true) before calling super.getWidth() and super.getHeight()

Monday, August 17, 2009

Open File Dialog

Ok, this is not a Dialog... It is an Implicit List. As we do not have File Dialogs on LCDUI I decided to share my version with you. It did work with Sony Ericson and Motorola iDEN handsets and I use it in my Books application.

import java.io.IOException;
import java.util.Enumeration;
import java.util.Stack;

import javax.microedition.io.Connector;
import javax.microedition.io.file.FileConnection;
import javax.microedition.io.file.FileSystemRegistry;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.List;
import javax.microedition.lcdui.Ticker;


public class OpenFileDialog extends List
implements CommandListener
{
public static final String PREFIX = "file:///";
private static final String UP = "[ .. ]";
private static final String DIR = " + ";
private Stack stack = new Stack();
private OpenFileListener listener;
private CommandListener commandListener;
private String extension;

public OpenFileDialog (OpenFileListener listener,
String title, String extension)
{
super(title, List.IMPLICIT);
super.setCommandListener(this);
this.listener = listener;
this.extension = extension;
addRoots();
}

public void setCommandListener(CommandListener l) {
this.commandListener = l;
}

public void commandAction(Command c, Displayable d) {
if (c == List.SELECT_COMMAND) {
this.changeSelection();
} else {
if (this.commandListener != null) {
this.commandListener.commandAction(c, d);
}
}
}

private String getSelectedText () {
int index = getSelectedIndex();
if (index < 0 || index >= this.size()) {
return "";
}
return this.getString(index);
}

private void changeSelection () {
String target = this.getSelectedText();
String parent = null;
boolean goingUp = false;

if (UP.equals(target)) {
goingUp = true;
stack.pop();
if (stack.isEmpty() == false) {
target = (String) stack.peek();
} else {
super.deleteAll();
addRoots();
this.setTicker(null);
return;
}
} else {
if (stack.isEmpty() == false) {
parent = stack.peek().toString();
}
}

try {
if (target.startsWith(DIR)) {
target = target.substring(3);
}
if (parent != null) {
target = parent + target;
}
this.setTicker(new Ticker(target));
FileConnection fc = (FileConnection)
Connector.open(PREFIX + target, Connector.READ);
if (fc.isDirectory()) {
super.deleteAll();
if (goingUp == false) {
stack.push(target);
}
super.append(UP, null);

Enumeration entries = fc.list();

while (entries.hasMoreElements()) {
String entry = (String) entries.nextElement();
FileConnection fc2 = (FileConnection)
Connector.open(PREFIX + target + entry,
Connector.READ);
if (fc2.isDirectory()) {
super.append(DIR + entry, null);
} else if (entry.toLowerCase().endsWith(extension)) {
super.append(entry, null);
}
fc2.close();
}
fc.close();
} else {
this.listener.fileSelected(fc);
}
} catch (IOException e) {
e.printStackTrace();
}

}

private void addRoots() {
Enumeration roots = FileSystemRegistry.listRoots();
while (roots.hasMoreElements()) {
super.append(DIR + roots.nextElement().toString(), null);
}
}

}

Related topics:

Monday, July 6, 2009

Know your audience

Which handsets are actually downloading your Java ME application? How many users report that your applications runs fine with their handsets? The answers are available to GetJar developers at Download Stats - Compatibility report, but I had a problem with it...


Since 2009 May, 14 my chess board has two versions available, one for MIDP 1.0 handsets and another for MIDP 2.0. From this day onwards I evaluate weekly downloads with handset details. At June, 7 I noticed that the most active handset at MIDP 1.0 version (Nokia 3110c - with 11% of all downloads and 53% of new downloads since May, 14) has droped to zero downloads, but appeared at MIDP 2.0 version and now it is one of the top 10 downloaders.



  1. Nokia N73

  2. Nokia 6300

  3. Sony-Ericsson K800i

  4. Nokia N70-1

  5. Nokia 5800 XpressMusic

  6. Nokia 6600

  7. Nokia E71

  8. Nokia 5310 XpressMusic

  9. Nokia 3110c

  10. Sony-Ericsson W200i

According to the official site this device is really MIDP 2.0, so it was an error from GetJar to have it download MIDP 1.0 content to begin with. So what? Other 43 handsets are still downloading MIDP 1.0 version, below are the top 10 downloaders since May, 14.



  1. Nokia 3100

  2. Nokia 3120

  3. Samsung SGH D900i

  4. Nokia 3200

  5. Nokia N-Gage QD

  6. Nokia 6610i

  7. Sony-Ericson T610

  8. Samsung SGH U700

  9. Nokia N-Gage

  10. Nokia 7210


Related topics: