Connector
class to open communication with
something else
Connection conn = Connector.open("...");
open()
method takes a string that defines
the connection type
Connector.open("http://www.monash.edu.au")
Connector.open("socket://www.monash.edu.au:80")
Connector.open("comm:0;baudrate=9600")
Connector.open("datagram:www.monash.edu.au:10")
Connector.open("file:/etc/passwd")
open()
will throw a
ConnectionNotFoundException
if the connection type
is not supported
InputConnection
, and the input
stream can be found by
InputStream in = (InputConnection) conn.getInputStream();
DataInputStream din = (DataInputStream) conn.getDataInputStream();
If the connection does not support reading, then the class cast
will throw an exception - guard by a class check
InputStream in = null;
if (conn instanceof InputConnection) {
in = (InputConnection) conn.getInputStream();
...
} else {...}
OutputConnection
is for writing,
StreamConnection
for both,
DatagramConnection
for UDP packets
ContentConnection
is where the stream conveys a
particular type of data, such as a GIF image sent by HTTP
StreamConnectionNotifier
can be used if the
device can be a server, such as a Web server: it has to
wait for connections to come in
HttpConnection
HttpConnection conn = (HttpConnection)
Connector.open("http://www.monash.edu.au);
HttpConnection
class is similar to the
java.net.URLConnection
class in J2SE
void getFromHttpConnection(String url) throws IOException {
HttpConnection conn = null;
InputStream is = null;
try {
conn = (HttpConnection )Connector.open(url);
// Getting the InputStream will open the connection
// and read the HTTP headers. They are stored until
// requested.
is = conn.openInputStream();
// Get the ContentType
String type = conn.getType();
// Get the length and process the data
int len = (int) conn.getLength();
if (len > 0) {
byte[] data = new byte[len];
int actual = is.read(data);
...
} else {
int ch;
while ((ch = is.read()) != -1) {
...
}
}
} finally {
if (is != null)
is.close();
if (conn != null)
conn.close();
}
}
HttpConnection conn = (HttpConnection)
Connector.open("http://www.monash.edu.au?x=abcd");
MIDlet
MIDlet.startApp()
The application startup code goes in this method
(draw windows, start threads, etc)
public class MyApp extends MIDlet {
public void startApp() {
// we get going here
}
public void pauseApp() {
// we aren't showing any more
}
public void destroyApp(boolean unconditional) {
// clean up
}
}
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class Shell extends MIDlet {
protected Display display;
protected Displayable displayable;
public Shell() {
display = Display.getDisplay(this);
displayable = new Form("a form");
}
public void startApp() {
display.setCurrent(displayable);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
display = null;
displayable = null;
}
}
Assume you have unpacked the J2ME wireless toolkit into a directory such as
WTK=/usr/local/personaljava/WTK2.0
javac -bootclasspath $WTK/lib/midpapi20.zip Shell.java
$WTK/bin/preverify -classpath .:$WTK/lib/midpapi20.zip -d classes Shell
$WTK/bin/emulator -cp classes:$WTK/lib/midpapi20.zip Shell
-Xdevice:device
option, where device
is one of
DefaultColorPhone
,
DefaultGrayPhone
,
MediaControlSkin
or
QwertyDevice
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class List1 extends MIDlet {
protected Display display;
protected List list;
public List1() {
display = Display.getDisplay(this);
list = new List("Sample list",
//List.IMPLICIT,
//List.EXCLUSIVE,
List.MULTIPLE,
new String[] {"One", "Two", "Three"},
null);
}
public void startApp() {
display.setCurrent(list);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
display = null;
list = null;
}
}
Command
class places "buttons" on the screen
to interact with the application, such as an "Okay" button
BACK
, CANCEL
, HELP
,
EXIT
, ITEM
, OK
,
SCREEN
and STOP
ITEM
command refers to a particular item
on the screen, such as a part of a form
SCREEN
command means some application-specific
action based on the current screen, such as "ring the user now"
Command comm = new Command("Ok", Command.OK, 1)
Displayable
objects like
List
List
)
so that the application can respond to events to that occur in
commands attached to the displayable
CommandListener
interface, and implement the method
public void commandAction(Command c, Displayable d)
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class Command1 extends MIDlet implements CommandListener {
protected Display display;
protected List list;
protected Command okCmd;
protected Command helpCmd;
public Command1() {
display = Display.getDisplay(this);
list = new List("Sample list",
List.IMPLICIT,
new String[] {"One", "Two", "Three"},
null);
okCmd = new Command("Okay", Command.OK, 1);
helpCmd = new Command("Help", Command.HELP, 1);
list.addCommand(okCmd);
list.addCommand(helpCmd);
list.setCommandListener(this);
}
public void commandAction(Command c, Displayable d) {
// d == list
if (c == okCmd) {
int index = list.getSelectedIndex();
String item = list.getString(index);
Alert selectedScr = new Alert("Selected item",
"Item selected was " + item,
null,
AlertType.INFO);
selectedScr.setTimeout(5000); // milliseconds
display.setCurrent(selectedScr);
} else {
Alert helpScr = new Alert("Help",
"Scroll to any item and press the select key",
null,
AlertType.INFO);
display.setCurrent(helpScr);
}
// System.out.println("Selected index is " + list.getSelectedIndex());
}
public void startApp() {
System.out.println("Starting");
display.setCurrent(list);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
display = null;
list = null;
}
}
TextBox
gives a full-screen (!) text editor
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class Text1 extends MIDlet {
protected Display display;
protected Displayable displayable;
public Text1() {
display = Display.getDisplay(this);
displayable = new TextBox("Phone number", "+61",
12, TextField.PHONE);
}
public void startApp() {
display.setCurrent(displayable);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
display = null;
displayable = null;
}
}
Form
is the only "container" class in MIDP
Form
can contain Item
objects
Form.append()
form.append(item);
form.append("string");
ItemStateChanged
event
ItemStateListener
which is set on the form
ItemStateListener
method
public void itemStateChanged(Item item)
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class Form1 extends MIDlet implements ItemStateListener {
protected Display display;
protected Form form;
public Form1() {
display = Display.getDisplay(this);
form = new Form("Info entry form");
form.append(new TextField("Name", "", 10, TextField.ANY));
form.append(new Gauge("Age (0-100)", true, 10, 2));
form.append(new ChoiceGroup("Job", Choice.EXCLUSIVE,
new String[] {"nerd", "student"},
null));
form.setItemStateListener(this);
}
public void itemStateChanged(Item item) {
System.out.println("State changed on item " +
item.toString());
}
public void startApp() {
display.setCurrent(form);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
display = null;
form = null;
}
}
Canvas
public void repaint(); // call this to redraw the screen
public void paint(Graphics g); // override this to draw your things
Graphics
object has methods to draw lines, text, etc
public class Graphics {
void drawChar(char character, int x, int y, int anchor);
void drawLine(int x1, int y1, int x2, int y2);
void drawRect(int x, int y, int width, int height);
void fillArc(int x, int y, int width, int height,
int startAngle, int arcAngle);
void fillRect(int x, int y, int width, int height);
void setColor(int red, int green, int blue);
void setFont(Font font);
// etc
}
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class Canvas1 extends MIDlet {
protected Display display;
protected Displayable displayable;
public Canvas1() {
display = Display.getDisplay(this);
displayable = new MyCanvas();
}
public void startApp() {
display.setCurrent(displayable);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
display = null;
displayable = null;
}
}
import javax.microedition.lcdui.*;
public class MyCanvas1 extends Canvas {
public void paint(Graphics g) {
g.setColor(255, 0, 0);
g.drawRect(10, 10, 100, 100);
g.setColor(0, 255, 0);
g.fillRect(20, 20, 80, 80);
}
}
public class Canvas {
void keyPressed(int keyCode);
void keyReleased(int keyCode);
void keyRepeated(int keyCode);
void showNotify();
void hideNotify();
void pointerDragged(int x, int y);
// etc
}
char
Graphics
method
String getKeyName(int keycode)
int getGameAction(int keycode)
translates keycodes to game actions
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class Canvas2 extends MIDlet {
protected Display display;
protected Displayable displayable;
public Canvas2() {
display = Display.getDisplay(this);
displayable = new MyCanvas2();
}
public void startApp() {
display.setCurrent(displayable);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
display = null;
displayable = null;
}
}
import javax.microedition.lcdui.*;
public class MyCanvas2 extends Canvas {
public void paint(Graphics g) {
}
protected void keyPressed(int keycode) {
System.out.println("Keycode: " + keycode);
System.out.println("Key (Unicode): " + getKeyName(keycode));
System.out.println("Game action code: " + getGameAction(keycode));
String gameAction = null;
switch (getGameAction(keycode)) {
case Canvas.DOWN: gameAction = "DOWN"; break;
case Canvas.UP: gameAction = "UP"; break;
case Canvas.LEFT: gameAction = "LEFT"; break;
case Canvas.RIGHT: gameAction = "RIGHT"; break;
case Canvas.FIRE: gameAction = "FIRE"; break;
// should be more valid cases here
default: gameAction = "duh"; break;
}
System.out.println("Action: " + gameAction);
}
}
RecordStore
to store records of binary data
RecordStore
ObjectOutputStream
(and input equivalent)
to serialize a class
import java.io.*;
public class Person {
public String firstName; // should be private
public String lastName; // ditto
public int age; // ditto
public Person(String first, String last, int ag) {
firstName = first;
lastName = last;
age = ag;
}
public Person(byte[] data) throws IOException {
super();
ByteArrayInputStream bis = new ByteArrayInputStream(data);
DataInputStream dis = new DataInputStream(bis);
firstName = DataInputStream.readUTF(dis);
lastName = DataInputStream.readUTF(dis);
age = dis.readInt();
}
public byte[] toBytes() {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeUTF(firstName);
dos.writeUTF(lastName);
dos.writeInt(age);
dos.close();
return bos.toByteArray();
} catch(IOException e) {
// will only happen if e.g. out of memory - return empty
return new byte[] {};
}
}
}
RecordStore.openRecordStore(String name, boolean createIfNeeded)
RecordStore.deleteRecordStore(String recordStoreName)
RecordStoreException
public int addRecord(byte[] data,
int offset,
int numBytes)
throws RecordStoreNotOpenException,
RecordStoreException,
RecordStoreFullException
RecordEnumeration enumerateRecords(RecordFilter filter,
RecordComparator comparator,
boolean keepUpdated)
RecordEnumeration
has methods including
boolean hasNextElement();
byte[] nextRecord();
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.rms.*;
import java.io.*;
public class PersonBook extends MIDlet {
protected Display display;
protected List list;
Person[] people;
public PersonBook() {
display = Display.getDisplay(this);
list = new List("People list", List.IMPLICIT);
// setup dummy data
Person[] people = new Person[2];
people[0] = new Person("Bill", "Smith", 30);
people[1] = new Person("Fred", "Bloggs", 21);
try {
saveToStore("personStore", people);
} catch(RecordStoreException e) {
// ignore
}
}
protected void saveToStore(String storeName, Person[] people)
throws RecordStoreException {
try {
// should backup first - but no copy/rename methods exist
RecordStore.deleteRecordStore(storeName);
} catch(RecordStoreNotFoundException e) {
// ignore
}
RecordStore rs = RecordStore.openRecordStore(storeName, true);
for (int n = 0; n < people.length; n++) {
byte[] data = people[n].toBytes();
int len = data.length;
rs.addRecord(data, 0, len);
}
}
protected Person[] loadFromStore(String storeName)
throws RecordStoreException {
RecordStore rs = null;
try {
rs = RecordStore.openRecordStore(storeName, false);
} catch(RecordStoreException e) {
return null;
}
int numPeople = rs.getNumRecords();
Person[] people = new Person[numPeople];
int count = 0;
RecordEnumeration enumerator = rs.enumerateRecords(null, null, false);
while (enumerator.hasNextElement()) {
byte[] data = enumerator.nextRecord();
try {
people[count] = new Person(data);
count++;
} catch(IOException e) {
people[count] = null;
}
}
return people;
}
public void startApp() {
try {
people = loadFromStore("personStore");
} catch(RecordStoreException e) {
// leave people as null
}
for (int n = 0; n < people.length; n++) {
if (people[n] != null)
list.append(people[n].lastName, null);
}
display.setCurrent(list);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
display = null;
}
}