Mobile Java
Mobile Java
Gerhard Juen
Faculty of Electrical Engineering
Gelsenkirchen University of Applied Sciences
Bocholt Campus
Version: 02.07.2008
Many OS Linux OS
We need
• Eclipse IDE
• The Java Wireless Toolkit (WTK) from SUN
• Java Micro Edition (ME) plugin for Eclipse
2 Getting started
2.1 Create a new Java ME-compatible workspace
Window → Preferences
• J2ME →
Device Management
• At first call table is
empty
• Press Import
• Select
MediaControlSkin
• Press OK
public FirstStep() {
super();
}
.. we assume
• a German version of the Nokia
6230i mobile phone
• the English version of the Nokia
PC-Suite (to communicate with
the phone from the PC)
Result:
JAD-files are simple
parameter text files with lines
parameter: value
• Click on FirstStep.jad (or right click → choice: Open With → Text Editor)
MIDlet-Vendor: MIDlet Suite Vendor
MIDlet-Version: 1.0.0
MIDlet-Jar-URL: FirstStep.jar
MicroEdition-Configuration: CLDC-1.1
MIDlet-1: FirstStep,,FirstStep
MicroEdition-Profile: MIDP-2.0
MIDlet-Name: FirstStep MIDlet Suite
Message: Hello World
• The black entries are the entries used by the MIDlet itself
• The red entry is an additional parameter Message
with the value Hello World
• Read the value of Message from the MIDlet:
String message = getAppProperty("Message");
// long version
Date d =new Date();
String dString = d.toString();
// short version
String dString = (new Date()).toString();
MIDlet JAD-file
MIDlet-Vendor: MIDlet Suite Vendor
MIDlet-Version: 1.0.0
MIDlet-Jar-URL: FirstStep.jar
MicroEdition-Configuration: CLDC-1.1
MIDlet-1: FirstStep,,FirstStep
MicroEdition-Profile: MIDP-2.0
MIDlet-Name: FirstStep MIDlet Suite
Message: Hello World
• contains important information about the MIDlet, such as:
- name of the JAR-file with the code
- CLDC/MIDP versions
- name of the MIDlet(-Suite)
FirstStep/FirstStep.jad
JAD template where the user can define
own additional settings.
FirstStep/deployed/FirstStep.jad
is the final JAD-file which contains the
template entries and some automatically
generated ones, e.g.:
MIDlet-Jar-Size: 1408
automatically generated
JAD-File template
additional lines
MIDlet-Vendor: MIDlet Suite Vendor MIDlet-Jar-Size: 1170
MIDlet-Version: 1.0.0
MIDlet-Jar-URL: FirstStep.jar
MicroEdition-Configuration: CLDC-1.1
MIDlet-1: FirstStep,,FirstStep
MicroEdition-Profile: MIDP-2.0
MIDlet-Name: FirstStep MIDlet Suite
Message: Hello World
deployed JAD-File
MIDlet-1: FirstStep,,FirstStep
MIDlet-Jar-Size: 1170
MIDlet-Jar-URL: FirstStep.jar
MIDlet-Name: FirstStep Midlet Suite
MIDlet-Vendor: Midlet Suite Vendor
MIDlet-Version: 1.0.0
MicroEdition-Configuration: CLDC-1.1
MicroEdition-Profile: MIDP-2.0
Message: Hello World
startApp()
pauseApp()
destroyApp()
Java Midlet
Application
Manager installation
Constructor
start
startApp()
removing
pauseApp()
destroyApp ()
Form’s title
Form
(fills the full screen) Item 2
GUI
Item 2 elements on
the screen
Item 3
display.setCurrent(form2);
Exercise 1
How does the MIDlet-Suite’s JAD-file change when the MIDlet-Suite contains more
than 1 MIDlet? What does this mean for the transfer of MIDlets to a mobile phone?
MobileComputing Workshop page 43 G. Juen, 02.07.2008
Exercise 2
Foundation
JEE JSE MIDP
profile
CDC Java
CLDC Card
Java
Java Virtual
Virtual Machine
Machine KVM
KVM Card VM
http://www.microjava.com/articles/images/midp/image006.gif
Important Packages
Evolution
http://developers.sun.com/techtopics/mobility/getstart/articles/survey/fig2.gif
JAM calls
MIDlet constructor
paused
active destroyed
JAM calls
destroyApp()
paused
active destroyed
MIDlet calls
notifyDestroyed()
state to
MIDlet method call remark
change into
destroyed notifyDestroyed() Is needed to stop GUI applications
(a MIDlet does not stop, when
startApp() has finished)
paused notifyPaused() Typical application: MIDlet which should
react on incoming SMS is set into passed
mode after start
active resumeRequest()*) only possible only from paused state.
It implies a notification to the JAM that the
MIDlet wants to be activated. The
paused→active transition is then initiated
by the JAM calling startApp().
*) how can a paused MIDlet execute any code?
• GUI components
• Stateless resources (which do not store anything),
• Network connections
• IO streams
• Resources that are shared between MIDlet's
Handling resources
public FirstStep() {
// no resources are allocated
}
protected void startApp() {
if (firstCall) {
[ acquire "stay alive" resources ..]
firstCall=false;
}
[ acquire temporary resources ..]
}
protected void pauseApp() {
[ release temporary resources ..]
}
}
• loads the complete MIDlet-Suite (which may contain more than one MIDlet)
to the phone.
• activates a selection menu on the emulator
if the MIDlet Suite contains more than one MIDlet.
• is more constraining but truer to what the end user is confronted with
when using his mobile device (including the installation over the internet)
• provides MIDlet validation (integrity checks ..)
Displayable
Canvas Screen
can be attached
Item
Screens
• Tonno
menu • Salami
• Scampi
Back Exit
commands
command buttons
CommandListener instance
calls
commandAction commandAction(..)
Your Coice switch ..
{
• Tonno case Tonno:
• Salami :
case Salami:
• Scampi
:
case Scampi:
:
}
Menus and commands want to send their events (an item was selected by the
user) to an object with a method commandAction(..) (Call back method)
MobileComputing Workshop page 70 G. Juen, 02.07.2008
The CommandListener interface
public interface CommandListener {
void commandAction(Command c, Displayable d);
}
CommandListener instance
calls
commandAction commandAction(..)
Your Coice switch ..
{
• Tonno case Tonno:
• Salami :
case Salami:
• Scampi
:
case Scampi:
:
}
CommandListener candidates
select
command
commandAction(cmd, form)
serve selected command cmd
(coming from form)
public MenuDemo() {
display = Display.getDisplay(this);
}
public CommandDemo() {
display = Display.getDisplay(this);
}
:
protected void startApp()
throws MIDletStateChangeException ..
:
// item for Form textIO (text input/output)
TextField textfield;
void prepareMenu() {
menu = new List("Test Components", Choice.IMPLICIT);
menu.append("TextBox with text O/I", null);
menu.append("List with 3 items", null);
menu.append("Alert with sound", null);
menu.append("Form with date O/I", null);
menu.append("Form with text O/I", null);
menu.addCommand(exitCommand);
menu.setCommandListener(this); // the midlet "this" is
// the CommandListener
}
void prepareInput() {
input = new TextBox("Enter Some Text:",
"", 10, TextField.ANY);
input.setString("");
input.addCommand(backCommand);
input.setCommandListener(this);
}
void prepareSoundAlert() {
soundAlert = new Alert("sound Alert");
soundAlert.setType(AlertType.ERROR);
soundAlert.setString("** ERROR **");
// returns automatically to preceeding screen
// after some waiting time => no command necessary
}
void prepareToday() {
today = new Form("Today's date");
date = new DateField("Today's date: ", DateField.DATE);
date.setDate(new Date());
today.append(date);
today.addCommand(backCommand);
today.setCommandListener(this);
}
void prepareTextIO() {
textIO = new Form("Form for Stuff");
textfield = new TextField("TextField Label",
"abc", 50, 0);
form.append(textfield);
form.addCommand(backCommand);
form.setCommandListener(this);
}
6.6 Exercise
Tonno
Salami
Scampi
Exit really leaves the MIDlet. The other choices produce a short informing
Alert: “You selected …” or an according System.out.println(..)
message to the Eclipse console.
7 Network communication
7.1 Overview
http://developers.sun.com/techtopics/mobility/midp/articles/midp2network/
MobileComputing Workshop page 96 G. Juen, 02.07.2008
Use pattern
try {
Connector.open("protocol:address;parameters");
} catch (ConnectionNotFoundExeption e) {
// .. some error message
}
• HTTP Connection:
Connector.open("http://java.sun.com/wireless")
• Socket Connection:
Connector.open("socket://java.sun.com:4711")
• Datagram Connection:
Connector.open("datagram://java.sun.com:4712")
• Bluetooth Connection:
Connector.open ("btspp://000B0D14D80D:1;
authenticate=false;master=false;encrypt=false")
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.StringItem;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.
MIDletStateChangeException;
public class SimpleHttpClient extends MIDlet {
Form form;
protected void startApp() ..
void message(String msg) ..
String readUntilEof(DataInputStream dis) ..
}
MobileComputing Workshop page 98 G. Juen, 02.07.2008
protected void startApp()
throws MIDletStateChangeException {
// prepare phone display
form = new Form("HTTP Client");
Display display = Display.getDisplay(this);
display.setCurrent(form);
:
try {
c = (HttpConnection) Connector.open(url); // open
c.setRequestMethod(HttpConnection.GET); // or POST
Answer:
<html>
<head>
<title>Keski-Pohjanmaan ammattikorkeakoulu</title>
:
</head>
<body>
:
</body>
</html>
7.3 Exercise
1) Implement the HTTP client from above
2) Register at the WHAT server und retrieve your personal set-id (32
characters).
3) Take the WhatClient MIDlet and implement actions for the commands
Set Ylivieska (Put me to Ylivieska Campus) and
Set Bocholt (Put me to Bocholt Campus)
4) Test and validate the modified client from step 3).
MobileComputing Workshop page 102 G. Juen, 02.07.2008
UTM coordinates
longitude latitude
(Est-West) (North-South)
FH Gelsenkirchen
University of Applied Sciences 6.6527 51.8398
Bocholt Campus
Central Ostrobothnia
University of Applied Sciences 24.5163 64.0729
Ylivieska Campus
URL for
"Put the WHAT user with 32digit id=01234567890123456789012345678901
to Bocholt Campus":
http://what.et.bocholt.fh-ge.de:443/what
/setposition.php
?uid=01234567890123456789012345678901
&set=6.6527,51.8398
&type=mobile
&msg=BocholtCampus
&setmode=
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.StringItem;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.
MIDletStateChangeException;
:
try {
D client = (SocketConnection) Connector.open(url);
dis = client.openDataInputStream();
dos = client.openDataOutputStream();
:
:
MobileComputing Workshop page 110 G. Juen, 02.07.2008
// send request to server
E dos.write("GET / HTTP/1.0\n\n".getBytes("CP1252"));
F dos.flush();
8 Bluetooth
8.1 Bluetooth features
Communication type
1 to 1 (point-to-point)
1 to many (multipoint device)
Bluetooth Adress
1 master 7 slaves
slaves
Security configuration
import javax.io.*;
import javax.microedition.io.*;
import de.juen.util.InpStrReader;
public class SimpleGPSReaderPC {
public static void main(String[] args) ..
}
8.4 Exercise
Implement and test the SimpleGPSReaderPC.
Hints
• Sun WTK-Simulator:
not possible
• mobile phone simulators from the phone manufacturers
sometimes possible (additional Bluetooth simulators available)
• Mpowerplayer → Midlet simulator for the PC
possible with avetana or bluecove bluetooth stack
Idea
Steps
Press
Press
Remark
This Mpowerplayer Bluetooth integration works only with the avetana-stack not
with bluecove!!
Idea
*) example:
-classpath c:\sonstige\installroh\mpowerplayer\mpp-sdk-
424\player.jar;c:\programme\wtk22\midpapi20.jar;d:\dokument
e\entwicklung\EclipseProjekte\Libraries\bluecove-
2.0.1.jar.jar com.mpp.player.PowerPlayerApp
${project_loc}\deployed\${project_name}.jad
Remark:
Remark
If you use the Bluecove model the project has first to be deployed if modifications
have been carried out before you start Mpowerplayer
http://developers.sun.com/techtopics/mobility/apis/articles/bluetoothintro/images/fig1_sm.jpg
Application
Application
Application
DUN GOEP
Generic Object
Exchange Profile
HFP
FTP OPP
LAP BPP
Topics
Disovery classes
deviceDiscovered() servicesDiscovered()
do s.th. do s.th.
arbitrary arbitrary
deviceDiscovered() servicesDiscovered()
deviceSearchCompleted()
inquiryCompleted() serviceSearchCompleted()
discType is one of
INQUIRY_COMPLETED end of normal search
INQUIRY_TERMINATED terminated by the program
INQUIRY_ERROR terminated because of an error
public void servicesDiscovered
(int transID, ServiceRecord[] servRecord)
DiscoveryListener (Interface)
specifies method calls of an event listener (provided by the application) called
by the DiscoveryAgent when a device or a service has been found.
deviceDiscovered() is called when a device is found during an inquiry
inquiryCompleted() is called when the inquiry is completed or canceled
DiscoveryAgent
provides methods for device and service discovery
startInquiry (non-blocking device discovery)
retrieveDevices (blocking device discovery)
searchServices (non-blocking service discovery)
DataElement
contains the various data types that a Bluetooth service attribute value can take
on:
• signed and unsigned integers(length 1,2, 4, 8, 16 bytes)
• String,
• boolean,
• UUID
• sequences of any one of these scalar types.
ServiceRecord (Interface)
contains the parameters of the service as attribute ID, value pairs
attribute ID is a 16-bit unsigned integer, attribute value is a DataElement
DiscoveryAgent (Singleton)
see DeviceDiscovery
DiscoveryListener (Interface)
specifies method calls of an event listener (to be provided by the application)
when a device or a service has been found.
23 13 12 8 7 3 1 0
service class maj. device class minor device class reser.
23 13 12 8 7 3 1 0
service class maj. device class minor device class reser.
Service Class
23 13 12 8 7 3 1 0
service class maj. device class minor device class reser.
Interpretation: 0x520000
0 1 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
5 2 0 0 0 0
Theory Holux
Major Device Class 1F00 1F00
Minor Device Class ? 0
Service Class 10000 0
Example
UUID[] searchList = new UUID[1];
public getGPSService()
searchServices for cached device
if gpsService found return
searchServices for preknown devices
if gpsService found return
startInquiry() (search devices “in the air”)
wait until all devices in the air have been found
searchServices for actually found and preselected devices
(devices from gpsDeviceList)
wait until all service searches have been completed
(serviceSearchCount has reached 0)
MobileComputing Workshop page 173 G. Juen, 02.07.2008
deviceDiscovered()
if Major_Device_Class and Service_Class fit
add device to gpsDeviceList
inquiryCompleted()
signal ALL DEVICES HAVE BEEN found
serviceSearchCompleted()
decrement serviceSearchCount
remove competed service search from transactionID list
signal FREE SERVICE SEARCH SLOT
serviceDiscovered()
cancel all active service searches
MobileComputing Workshop page 175 G. Juen, 02.07.2008
Main structure
import java.util.*;
import javax.bluetooth.*;
import javax.bluetooth.UUID;
The methods
// constructor prepares the device/service discovery
public SearchGPSDevice(Log log)
throws BluetoothStateException {
this.log = log; // where to send the debug messages
import javax.bluetooth.*;
import javax.microedition.io.*;
void run() ..
J $GPGGA,165534.000,5150.5759,N,00637.8046,E,1,05,2.1,
30.8,M,47.3,M,,0000*66
9 GPS-Data
9.1 NMEA-format
Source: http://www.gpsinformation.org/dale/nmea.htm
Example:
$GPGGA,223111.000,5150.5715,N,00637.8153,E,1,07,1.3,26.0,M,47.3,M,,0000*65
$GPRMC,223111.000,A,5150.5715,N,00637.8153,E,0.00,30.08,130107,,,A*59
$GPVTG,30.08,T,,M,0.00,N,0.0,K,A*36
Example of Formats
degree, seconds degree NMEA What
64° 14.4200' 64.2403350° 6414.4200 64.2403350
Hint
Take the GPSInpStrReader form the package de.juen.util
(Contained in JuenUtilities.jar)