0% found this document useful (0 votes)
57 views

Mobile Java

This document provides an overview of the content and tools used in a mobile computing workshop focused on programming mobile phones using Java Micro Edition (Java ME) with an emphasis on communication features. The workshop will use the Eclipse IDE, Sun Java Wireless Toolkit (WTK), and a Java ME plugin for Eclipse to develop and test Java ME applications. Topics that will be covered include the Java ME vs Java SE/EE, MIDlet lifecycles, GUI design, network communication, Bluetooth, and GPS.

Uploaded by

Ville Autio
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
57 views

Mobile Java

This document provides an overview of the content and tools used in a mobile computing workshop focused on programming mobile phones using Java Micro Edition (Java ME) with an emphasis on communication features. The workshop will use the Eclipse IDE, Sun Java Wireless Toolkit (WTK), and a Java ME plugin for Eclipse to develop and test Java ME applications. Topics that will be covered include the Java ME vs Java SE/EE, MIDlet lifecycles, GUI design, network communication, Bluetooth, and GPS.

Uploaded by

Ville Autio
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 104

Mobile Computing Workshop

Gerhard Juen
Faculty of Electrical Engineering
Gelsenkirchen University of Applied Sciences
Bocholt Campus

Version: 02.07.2008

1 Workshop content and used tools 4 4 MIDlet lifecycle 51


1.1 Eclipse IDE 6 4.1 MIDlet states 51
1.2 Sun Java Wireless Toolkit (WTK) 6 4.2 State transitions initiated by the JAM 52
1.3 Java ME-plugin for Eclipse 7 4.3 Exercise 55
2 Getting started 8 4.4 State transitions initiated by the MIDlet 57
2.1 Create a new Java ME-compatible 4.5 Resource management 59
workspace 8
4.6 Exercise 61
2.2 Prepare Debugging 11
5 Installation on the mobile device 62
2.3 Create new MIDlet project 12
6 GUI 65
2.4 Create a new MIDlet 15 6.1 Elements 65
2.5 Run MIDlet in the simulator 20 6.2 Callbacks for processing GUI events 68
2.6 Run MIDlet on the mobile phone 23 6.3 GUI example 78
2.7 Feed the MIDlet with external parameters 29 6.4 Exercise 94
2.8 Exercise 31 7 Network communication 95
2.9 Behind the curtain of getting started 32 7.1 Overview 96
2.10 Exercise 43 7.2 Example for a HTTP-connection 98
3 JAVA ME vs. Java SE, Java EE 45 7.3 Exercise 102

MobileComputing Workshop page 2 G. Juen, 02.07.2008


8 Bluetooth 108 9 GPS-Data 204

8.1 Bluetooth features 114 9.1 NMEA-format 204

8.2 JAVA SE Bluetooth programs 119 9.2 Exercise 207

8.3 Getting started: read GPS receiver data


with the PC 121
8.4 Exercise 128
8.5 Developing and testing Java ME-Bluetooth
programs on the PC 130
8.6 Exercise 141
8.7 Bluetooth protocols 142
8.8 Bluetooth-for-Java (JSR-82) profiles 147
8.9 The JSR-82 API 150
8.10 Search for devices and services
(Discovery) 151
8.11 Device Discovery Classes 158
8.12 Service discovery classes 160
8.13 Device class → kind of device/service 163
8.14 Services search configuration 169
8.15 Service discovery: an example 173
8.16 Exercise 203

MobileComputing Workshop page 3 G. Juen, 02.07.2008

1 Workshop content and used tools


Programming mobile applications

Windows mobile OS Symbian OS

• native C++ native C++


• .net compact framework
C#, Visual Basic

Many OS Linux OS

Java Micro Edition Android (Google-Phone)


OpenMoko

MobileComputing Workshop page 4 G. Juen, 02.07.2008


Topic here: programming of mobile phones
• with Java Micro Edition (Java ME)
• with an emphasis on communication (Internet, Bluetooth)

We need
• Eclipse IDE
• The Java Wireless Toolkit (WTK) from SUN
• Java Micro Edition (ME) plugin for Eclipse

MobileComputing Workshop page 5 G. Juen, 02.07.2008

1.1 Eclipse IDE


• Can be downloaded from http://eclipse.org
• We use version 3.3.1.1

1.2 Sun Java Wireless Toolkit (WTK)


• Can be downloaded from
http://java.sun.com/products/sjwtoolkit/
• We use version 2.6.2
• Can be used for the complete development of
Java applications for mobile devices
• Drawback:
Little development comfort (Text editor only)
• Required also for the Eclipse ME-plugin:
contains all Java ME libraries.

MobileComputing Workshop page 6 G. Juen, 02.07.2008


1.3 Java ME-plugin for Eclipse
• Can be downloaded from http://eclipseme.org/
• We use version 1.7.7
• Can be used for the complete development of
Java applications for mobile devices
• Much comfort during development process (editor with integrated help)
• Needs Sun Java Wireless Toolkit
• Drawback: Not all Java ME functionality available.
Missing: Over The Air Provisioning (OTA)

In this course: We use Eclipse with Java ME plugin

MobileComputing Workshop page 7 G. Juen, 02.07.2008

2 Getting started
2.1 Create a new Java ME-compatible workspace

Create a new workspace

• File → Switch Workspace


• Browse→ Create New Folder
Create a new directory MIDlets under your Eclipse root directory
from which Eclipse workspaces start
• OK → OK
restarts Eclipse in the new workspace

MobileComputing Workshop page 8 G. Juen, 02.07.2008


Relate workspace to Sun Java Wireless Toolkit

Window → Preferences

• J2ME →
Device Management
• At first call table is
empty
• Press Import

MobileComputing Workshop page 9 G. Juen, 02.07.2008

• Enter or browse to the


root directory of the
Sun Wireless Toolkit
(here version 2.5.2
installed in
C:\Programme\
WTK2.5.2)
• Press
Refresh then Finish

• Select
MediaControlSkin
• Press OK

MobileComputing Workshop page 10 G. Juen, 02.07.2008


2.2 Prepare Debugging
• Menu sequence:
Window → Preferences
→ Java → Debug:
• Deselect
Suspend execution on
uncaught exceptions
• Deselect
Suspend execution on
compilation errors
• Debugger timeout (ms): 15000

MobileComputing Workshop page 11 G. Juen, 02.07.2008

2.3 Create new MIDlet project


File→New→Other

MobileComputing Workshop page 12 G. Juen, 02.07.2008


• Select J2ME → J2ME Midlet Suite
• Press Next

• Enter FirstStep as Project name


• Press Next

MobileComputing Workshop page 13 G. Juen, 02.07.2008

• Select entries for Group and Device


(Should offer the default device)
• Press Finish

MobileComputing Workshop page 14 G. Juen, 02.07.2008


2.4 Create a new MIDlet
• File → New → Other

MobileComputing Workshop page 15 G. Juen, 02.07.2008

• Select J2ME → J2ME Midlet


• Press Next

MobileComputing Workshop page 16 G. Juen, 02.07.2008


• Enter FirstStep in field Name
• Press Finish

Now Eclipse creates an empty MIDlet


with the three required MIDlet
methods (see next page)
startApp()
pauseApp()
destroyApp()

MobileComputing Workshop page 17 G. Juen, 02.07.2008

The created empty MIDlet


import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.
MIDletStateChangeException;

public class FirstStep extends MIDlet {

public FirstStep() {
super();
}

protected void startApp()


throws MIDletStateChangeException {
}

protected void pauseApp() {


}

protected void destroyApp(boolean arg0)


throws MIDletStateChangeException {
}
}
MobileComputing Workshop page 18 G. Juen, 02.07.2008
Insert own program code

1. Insert the following import line


import javax.microedition.lcdui.*;
for GUI support.

2. Insert the following grey lines code into startApp


protected void startApp()
throws MIDletStateChangeException {
Form form = new Form("My first Title");
form.append(new StringItem(
null,"My first Java ME Program"));
Display display = Display.getDisplay(this);
display.setCurrent(form);
}

MobileComputing Workshop page 19 G. Juen, 02.07.2008

2.5 Run MIDlet in the simulator

Prepare a new Run.. entry

Select (the down


arrow!) from the toolbar
an then
Open Run Dialog...
• Press right mouse
click on Wireless
Toolkit Emulator
(opens popup menu)
• Select New

MobileComputing Workshop page 20 G. Juen, 02.07.2008


• Change Name field
into FirstStep
• Activate radiobutton
MIDlet in the area
Executable and
insert FirstStep in
the related text field
• Press Apply
• Press Run

MobileComputing Workshop page 21 G. Juen, 02.07.2008

MobileComputing Workshop page 22 G. Juen, 02.07.2008


2.6 Run MIDlet on the mobile phone

Adapt Midlet-Suite to the mobile phone capabilities

Most existing mobile phones


only support MIDP version 2.0.
We have to indicate that we use
only MIDP 2.0 packages:
• Click on FirstStep.jad
• Change
Mobile Information Device
Profile (2.1) into …(2.0)

MobileComputing Workshop page 23 G. Juen, 02.07.2008

Prepare files fort the phone

Remark: Up to here the


deployed folder is empty

We have to create in the deployed folder:


FirstStep.jar contains all class files as jar-Archiv
FirstStep.jad contains parameters such as Midlet name etc.

MobileComputing Workshop page 24 G. Juen, 02.07.2008


• Right mouse click on
FirstStep in the Navigator
window
• Select
J2ME → Create Package

MobileComputing Workshop page 25 G. Juen, 02.07.2008

Eclipse creates the required


JAR and JAD-file and shows
them in the deployed folder of
the Navigator window.

MobileComputing Workshop page 26 G. Juen, 02.07.2008


Sending FirstStep via Bluetooth to a phone

.. 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)

Click on Install Applications


in the Nokia PC Suite

MobileComputing Workshop page 27 G. Juen, 02.07.2008

• At the left window select the folder


YourEclipseProjectsRootDir\MIDlets\FirstStep\deployed
• Mark FirstStep.jar and click on the arrow in the middle of the screen

Start the program on the phone

Select Menü → Programme → Sammlung → FirstStep MIDlet

MobileComputing Workshop page 28 G. Juen, 02.07.2008


2.7 Feed the MIDlet with external parameters

Excursus: Look into JAD-files

Right mouse click on


FirstStep.jad
Open With → Text Editor

Result:
JAD-files are simple
parameter text files with lines
parameter: value

MobileComputing Workshop page 29 G. Juen, 02.07.2008

Modify/Extend the JAD-file with own parameters

• 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");

MobileComputing Workshop page 30 G. Juen, 02.07.2008


2.8 Exercise
Modify your FirstStep MIDlet according to the following specification and test
the modifications in the simulator and on the phone:
• the title of the form („My first Title“ in the demo above)
is read from the JAD-file.
• Instead of the message My first Java ME Program
we see the actual date.

Example how to obtain the date


import java.util.Date;
:

// long version
Date d =new Date();
String dString = d.toString();

// short version
String dString = (new Date()).toString();

MobileComputing Workshop page 31 G. Juen, 02.07.2008

2.9 Behind the curtain of getting started

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)

• may obtain additional parameters for the application


• is also contained in the MIDlet JAR-file
• URL of the JAD-file is needed to download a MIDlet over the internet
MobileComputing Workshop page 32 G. Juen, 02.07.2008
Template JAD-file and deployed JAD-file

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

MobileComputing Workshop page 33 G. Juen, 02.07.2008

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

MobileComputing Workshop page 34 G. Juen, 02.07.2008


MIDlets

Java programs on mobile devices are so called MIDlets


(similar principle as an applet).
MIDlets
• extend javax.microedition.midlet.MIDlet
• are forced to implement three methods:

startApp()
pauseApp()
destroyApp()

called by the Java Application Manager during MIDlet state transition

MobileComputing Workshop page 35 G. Juen, 02.07.2008

Java Application Manager

Java Midlet
Application
Manager installation
Constructor
start

startApp()

removing
pauseApp()

destroyApp ()

MobileComputing Workshop page 36 G. Juen, 02.07.2008


MIDlets run under the control of a Java Application Manager (JAM)
which controls the MIDlet's
• installation
• running
• removing

After clicking the particular MIDlet symbol on the mobile device


• the JAM creates an instance of the MIDlet (install) and
• calls it's startApp() method (start)

MobileComputing Workshop page 37 G. Juen, 02.07.2008

Explanation of the user code


protected void startApp()
throws MIDletStateChangeException {

// preparation of the form


A Form form = new Form("My first Title");
B form.append(new StringItem(
null,"My first Java ME Program"));

// getting handle to the phone’s screen


C Display display = Display.getDisplay(this);

// make prepared form visible


D display.setCurrent(form);
}

MobileComputing Workshop page 38 G. Juen, 02.07.2008


A A Form is a particular Displayable object. Displayables represent the
part of the mobile devices's display available for the Java application. They
consist of a body (Form's body is empty) and a frame with a headline. The
content of the headline can be defined in the Form’s constructor call.
B With the Form object method append a chain of various Item objects can
be attached to the Form object. StringItem contains a simple string.
Other Items are ImageItem, TextField etc.

Form’s title
Form
(fills the full screen) Item 2

GUI
Item 2 elements on
the screen

Item 3

MobileComputing Workshop page 39 G. Juen, 02.07.2008

In contradiction to PC based GUI applications the programmer has only


little influence on the appearance of the attached objects on the screen!
C The class method Display.getDisplay() returns a Display object
which serves as "handle" to the physical screen. As there exists only one
physical screen there is only one Display instance (Design pattern
Singleton) which can be accessed by Display.getDisplay() (Design
pattern Factory)
D A Displayable becomes only visible when it is attached to the real
display by calling the display's setCurrent() method. At a given time
instant max. one Displayable is visible on the screen.

MobileComputing Workshop page 40 G. Juen, 02.07.2008


Form form1 = new Form("My first Form");
form1.append(new StringItem
(null,"Bocholt"));

Form form2 = new Form("My second Form");


form2.append(new StringItem
(null,"Ylivieska"));

display.setCurrent(form2);

MobileComputing Workshop page 41 G. Juen, 02.07.2008

Typical program flow in a MIDlet

Create all Displayables


Select one Displayable to be seen on the screen
Loop forever
{
Wait for user input (or external event)
Process input (or external event)
Select next Displayable for the Screen
}

MobileComputing Workshop page 42 G. Juen, 02.07.2008


2.10 Exercise

Exercise 1

Create a new Midlet FormsDemo in the FirstStep Midlet-Suite.


Specificaton for FormsDemo:
• It has 3 forms with the titles Date, Cities and Course
• form1 has one StringItem with the actual date
form2 has two StringItems with the text Ylivieska and Bocholt
form3 has three StringItems with the text Mobile, Computing and
Workshop
• The MIDlet displays the three forms sequentially in an endless loop with a
delay of 1 s
Hint: Code for a 1000 ms delay
try {Thread.sleep(1000);} catch (Exception e) {}

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

Create a new Midlet-Suite StopWatch.


Develop a StopWatch Midlet which counts in 1s intervals from 10s down to 0s. On
the display the remaining seconds are shown. When 0 has been achieved the text
“Stop watch finished” occurs.
Hints:
• You can change the text of a StringItem xxx by:
xxx.setText(“New text”);
• In order to be able to do this you need a reference of the StringItem
appended to the form:
StringItem number = new StringItem(null,"10")
form.append(number);
:
number.setText(...);
• The String representation of an integer yyy is obtained by
String.valueOf(yyy)
• Loops work as in C++ or C#
MobileComputing Workshop page 44 G. Juen, 02.07.2008
3 JAVA ME vs. Java SE, Java EE

The Java familiy (view 1)

Server Desktop High-end Low-end Smart


mobile mobile devices Cards
Optional devices
packages
Optional Optional
packages packages
Optional
Personal
packages
profile

Foundation
JEE JSE MIDP
profile

CDC Java
CLDC Card
Java
Java Virtual
Virtual Machine
Machine KVM
KVM Card VM

Java Micro Edition (JME)

MobileComputing Workshop page 45 G. Juen, 02.07.2008

The Java familiy (view 2

MobileComputing Workshop page 46 G. Juen, 02.07.2008


Java familiy subset for low end devices (“connected limited devices”)

http://www.microjava.com/articles/images/midp/image006.gif

MobileComputing Workshop page 47 G. Juen, 02.07.2008

Java general Java ME


(for low end mobile devices
H/W, O/S hardware and operating system: e.g. NOKIA 6320i
device manufacturer specific, totally e.g. Symbian OS
transparent to Java developers.
Virtual abstract computer to execute the Java KVM = Kilobyte Virtual Machine
Machine byte code. reduced capabilities for devices
with limited resources (typ. 256
kByte)
Confi- minimum required Java technology CLDC = Connected Limited
guration (components and libraries) Primary Device Configuration
topics: target features:
• Java language resource-constrained,
• virtual machine features connected devices
• core libraries
typical target devices:
• security
mobile phones.
• input/output
• networking
MobileComputing Workshop page 48 G. Juen, 02.07.2008
Java general Java ME
(for low end mobile devices
Profiles Set of additional libraries targeted at a MIDP = Mobile Device
particular application field Information Profile (typ. mobile
phones)

Current Java ME architecture for mobile phones: CLDC1.1/MIDP2.0

MobileComputing Workshop page 49 G. Juen, 02.07.2008

Another view on the Java ME architecture

Important Packages

• Java APIs for Bluetooth (JABWT)


• Wireless Messaging API (WMA)
• Mobile Media API (MMAPI)
• Web Services API (WSA)
• Location API

Evolution

actual optional packages may


become part of future profiles

http://developers.sun.com/techtopics/mobility/getstart/articles/survey/fig2.gif

MobileComputing Workshop page 50 G. Juen, 02.07.2008


4 MIDlet lifecycle
4.1 MIDlet states

Possible MIDlet's States

active (what we are mainly interested in)


paused
destroyed

Initiator of state transitions

• JAM (external events)


• MIDlet itself (our application)

MobileComputing Workshop page 51 G. Juen, 02.07.2008

4.2 State transitions initiated by the JAM

JAM calls
MIDlet constructor

paused

JAM calls JAM calls JAM calls


pauseApp() startApp() destroyApp()

active destroyed
JAM calls
destroyApp()

MobileComputing Workshop page 52 G. Juen, 02.07.2008


Call back function for JAM-initiated MIDlet state transitions

• entering destroyed JAM calls destroyApp()


• entering paused JAM calls pauseApp()
• entering active JAM calls startApp()
(here we insert our application code)

MobileComputing Workshop page 53 G. Juen, 02.07.2008

Typical state transition initiated by JAM

Init state Event New state JAM calls


nothing MIDlet is started by the paused → active 1. MIDlet constructor
user 2. startApp()
active JAM needs memory (e.g. paused pauseApp()
because of a receiving The MIDlet is set into
MMS) a sleep mode where
it should release not
needed resources
destroyed destroyApp()
active/ User presses button destroyed destroyApp()
paused on the phone
paused An external event occurs active startApp()
which has to be
consumed by the MIDlet

MobileComputing Workshop page 54 G. Juen, 02.07.2008


4.3 Exercise
Take the FirstStep MIDlet and insert System.out.println("…") type debug
output messages for the console into the methods
FirstStep() (midlet’s constructor)
startApp()
pauseApp()
destroyApp()
Then do the following
• Start the MIDlet
• Initiate active → paused transition from the simulator’s menu (see below)
• Initiate paused → active transition from the simulator’s menu (see below)
• Initiate active → destroyed transition by pressing the simulator’s button
• Initiate paused → destroyed transition by pressing the simulator’s button
Check the expected debug output

MobileComputing Workshop page 55 G. Juen, 02.07.2008

active → paused paused → active

MobileComputing Workshop page 56 G. Juen, 02.07.2008


4.4 State transitions initiated by the MIDlet

paused

MIDlet calls MIDlet calls MIDlet calls


notifyPaused() resumeRequest() notifyDestroyed()

active destroyed
MIDlet calls
notifyDestroyed()

MobileComputing Workshop page 57 G. Juen, 02.07.2008

How to initiate state transition by the application

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?

In additional threads via timers or callback function connected to external


events (from other MIDlets, incoming connection requests, ..).
MobileComputing Workshop page 58 G. Juen, 02.07.2008
4.5 Resource management
Which resources could and should be released when the MIDlet enters paused
(forced by the JAM or voluntarily by the MIDlet itsself)?

Resources which should be released ("temporary ressources")

• GUI components
• Stateless resources (which do not store anything),

Resources which often can not be released "stay alive resources"

• Network connections
• IO streams
• Resources that are shared between MIDlet's

Handling resources

Storage consuming resources should not be allocated in the MIDlet-constructor


but in startApp(). Reason: “Constructed” MIDlets are still in paused state
which should need only few resources.
MobileComputing Workshop page 59 G. Juen, 02.07.2008

public class FirstStep extends MIDlet {


private boolean firstcall=true;

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 ..]
}
}

MobileComputing Workshop page 60 G. Juen, 02.07.2008


4.6 Exercise
Extend startApp() of the FirstStep MIDlet such that after 3 seconds the
MIDlet is destroyed.

MobileComputing Workshop page 61 G. Juen, 02.07.2008

5 Installation on the mobile device

Installation over direct connection

Copy JAR-file (JAD-file is not needed) to the mobile device via


• cable
• infrared (Irda)
• Bluetooth link

Installation over the internet Over-The-Air provisioning (OTA)

• Installation of a MIDlet suite from a remote HTTP-server


using the device's built-in browser.
• Browser's address file: URL of the MIDlet suite's JAD-file
• After entering the JAD-file's URL the installation process starts
• MIME-Type for the HTTP-server:
JAD-file: text/vnd.sun.j2me.app-descriptor
JAR-file: application/java-archive
MobileComputing Workshop page 62 G. Juen, 02.07.2008
OTA simulation in Eclipse

Menu sequence: Run → Open Run Dialog

MobileComputing Workshop page 63 G. Juen, 02.07.2008

runs the specified MIDlet direct without any check


(typically used during the development)

• 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 ..)

simulates the MIDlet-Suite download from a web-server.


Try to load Google Maps
http://www.hostj2me.com/downloads/1216/4940/gmaps-162-m2_ts_L1.jad

MobileComputing Workshop page 64 G. Juen, 02.07.2008


6 GUI
6.1 Elements

Displayable

Canvas Screen

Alert List Form Textbox

can be attached

Item

StringItem TextField ImageItem DateField Gauge ChoiceGroup

MobileComputing Workshop page 65 G. Juen, 02.07.2008

Screens

Screen = (abstract) superclass of all high-level user interface classes:


• Alert
shows data to the user and waits for a certain period of time before
proceeding to the next screen.
• Form
contains an arbitrary mixture of Items
(images, text, text fields, choice groups..)
• List
contains a list of choices,
• Textbox
allows the user to enter and edit text.

MobileComputing Workshop page 66 G. Juen, 02.07.2008


Items

Item = (abstract) superclass for components that can be added to a Form.

ChoiceGroup is a group of selectable elements (for a menu)

DateField is an editable component for presenting calendar date and time


information

Gauge implements a bar graph display of a numerical value

ImageItem contains an Image object (with layout control)

StringItem contains a non editable string

TextField is an editable text component

MobileComputing Workshop page 67 G. Juen, 02.07.2008

6.2 Callbacks for processing GUI events

menus and commands

Your Coice menu

• Tonno
menu • Salami
• Scampi

Back Exit

commands

command buttons

MobileComputing Workshop page 68 G. Juen, 02.07.2008


processes is connected to
CommandListener command events Displayable
from Displayable objects objects
(Form, List, Menu, Alert)
menu events
(from List objects)
ItemStateListener changes in the internal state*) of Form objects
a GUI Item attached to a Form (more simple than
Example: Content of a to the individual
TextField has been modified Item Objects)
by the user

MobileComputing Workshop page 69 G. Juen, 02.07.2008

CommandListener to process menu events (user clicks on menu items)

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);
}

A class which implements CommandListener


public class ArbitraryClass() implements CommandListener{
:
:
void commandAction(Command c, Displayable d)
{
// do what has to be done, when command c
// from Displayable d has been selected by
// the user
}
:
:
}

MobileComputing Workshop page 71 G. Juen, 02.07.2008

• CommandListener is an interface with a method signature


commandAction(..). (Interfaces are only "contracts").
• Each MIDlet with command/menu input needs at least one object
which implements the CommandListener interface.
• Such an object is shortly referred to as “CommandListener”.
• Implementing CommandListener means to provide a
commandAction(..) method with “content”.
• Each

Form, List, Alert, Textbox instance with commands


List instance with a menu

has to be connected to a CommandListener.

MobileComputing Workshop page 72 G. Juen, 02.07.2008


Attaching CommandListeners

Attaching a CommandListener to a List instance with appended menu items


List menu=new List(..)
menu.append(..) // menu item
menu.append(..)
:
menu.setCommandListener(commandListener)

Attaching a CommandListener to a Form instance with commands


Form form=new Form(..)
form.addCommand(..)
form.addCommand(..)
:
form.setCommandListener(commandListener)

MobileComputing Workshop page 73 G. Juen, 02.07.2008

CommandListener for more than one event

CommandListener instance
calls
commandAction commandAction(..)
Your Coice switch ..
{
• Tonno case Tonno:
• Salami :
case Salami:
• Scampi
:
case Scampi:
:
}

If a CommandListener has been connected to more than one Screen Objects:


How does commandAction(..)know which Screen has sent the event?

MobileComputing Workshop page 74 G. Juen, 02.07.2008


Signature of commandAction

void commandAction(Command c, Displayable d)

The event calls commandAction with


in case of a command: the Command object c and the Displayable
object d where the command has been generated
in case of a menu: the List object d in which a choice has been
taken.

CommandListener candidates

• the MIDlet itself (often)


• a separate object (seldom)

MobileComputing Workshop page 75 G. Juen, 02.07.2008

MIDlet CommandListener as separate object

form commandListener myMIDlet

commandListener= new SomeClass


implements CommandListener
create form with
commands and relate
it to commandListener
select
command
commandAction(cmd,form)
serve selected command cmd
(coming from form)

MobileComputing Workshop page 76 G. Juen, 02.07.2008


MIDlet CommandListener as part of the MIDlet

form MyMIDlet implements CommandListener

create form with


commands and relate
it to myMidlet

select
command
commandAction(cmd, form)
serve selected command cmd
(coming from form)

MobileComputing Workshop page 77 G. Juen, 02.07.2008

6.3 Simple Menu example

MobileComputing Workshop page 78 G. Juen, 02.07.2008


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

public class MenuDemo extends MIDlet implements


CommandListener {
Display display; // physical screen
List menu; // the menu

public MenuDemo() {
display = Display.getDisplay(this);
}

public void commandAction(Command c, Displayable d) ..

protected void startApp() ..

protected void pauseApp() {}

protected void destroyApp(boolean unconditional)


throws MIDletStateChangeException { }

MobileComputing Workshop page 79 G. Juen, 02.07.2008

protected void startApp()


throws MIDletStateChangeException {
menu = new List("Menu Demo", Choice.IMPLICIT);
menu.append("Item 1 ", null);
menu.append("Item 2 ", null);
menu.append("Item 3 ", null);
menu.append("Exit ", null);
menu.setCommandListener(this); // the midlet itself is
// the CommandListener
display.setCurrent(menu); // display the menu
}

MobileComputing Workshop page 80 G. Juen, 02.07.2008


public void commandAction(Command c, Displayable d) {
switch (((List)d).getSelectedIndex()) {
case 0: System.out.println("A selected"); break;
case 1: System.out.println("B selected"); break;
case 2: System.out.println("C selected"); break;
case 3: notifyDestroyed(); break;
}
}
}

MobileComputing Workshop page 81 G. Juen, 02.07.2008

6.4 Simple Command example

MobileComputing Workshop page 82 G. Juen, 02.07.2008


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

public class CommandDemo extends MIDlet implements


CommandListener {
Display display; // physical screen
TextBox input; // Text input from the phone

public CommandDemo() {
display = Display.getDisplay(this);
}

static final Command backCommand


= new Command("Back", Command.BACK, 0);
static final Command exitCommand
= new Command("Exit", Command.STOP, 2);
:

MobileComputing Workshop page 83 G. Juen, 02.07.2008

:
protected void startApp()
throws MIDletStateChangeException ..

public void commandAction(..) ..

protected void pauseApp() {}

protected void destroyApp(boolean unconditional)


throws MIDletStateChangeException { }
}

MobileComputing Workshop page 84 G. Juen, 02.07.2008


protected void startApp()
throws MIDletStateChangeException {
input = new TextBox("Enter Some Text:",
"", 10, TextField.ANY);
input.setString("");
input.addCommand(backCommand);
input.addCommand(exitCommand);
input.setCommandListener(this);
}

MobileComputing Workshop page 85 G. Juen, 02.07.2008

public void commandAction(Command c, Displayable d) {


if (c == exitCommand) {
notifyDestroyed();
return;
}
if (c == backCommand) {
System.out.println("Back selected");
display.setCurrent(input); // switch to "another"
// Displayable
return;
}
}

MobileComputing Workshop page 86 G. Juen, 02.07.2008


6.5 Sophisticated GUI example
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
import java.util.Date;

public class GuiDemo extends MIDlet implements


CommandListener {
Display display; // physical screen

// all the screens


List menu; // main menu
TextBox input;
List choose;
Alert soundAlert;
Form today;
Form textIO;

// item for Form today (date output/input)


DateField date;
:

MobileComputing Workshop page 87 G. Juen, 02.07.2008

:
// item for Form textIO (text input/output)
TextField textfield;

// commands for softkeys


static final Command backCommand
= new Command("Back", Command.BACK, 0);
static final Command mainMenuCommand
= new Command("Main", Command.SCREEN, 1);
static final Command exitCommand
= new Command("Exit", Command.STOP, 2);

public void commandAction(Command c, Displayable d) ..

protected void startApp() ..

protected void pauseApp() {}

protected void destroyApp(boolean unconditional)


throws MIDletStateChangeException { }

MobileComputing Workshop page 88 G. Juen, 02.07.2008


// the screens
void prepareMenu() ..
void prepareInput()..
void prepareChoose()..
void prepareSoundAlert()..
void prepareToday()..
void prepareTextIO()..
}

protected void startApp()


throws MIDletStateChangeException {
display = Display.getDisplay(this);
prepareMenu();
prepareTextBox();
prepareList();
prepareAlert();
prepareDate();
prepareTextIO();
display.setCurrent(menu); // start with main menu
}

MobileComputing Workshop page 89 G. Juen, 02.07.2008

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);
}

MobileComputing Workshop page 90 G. Juen, 02.07.2008


void prepareChoose() {
choose = new List("Choose Items", Choice.MULTIPLE);
choose.append("Item 1", null);
choose.append("Item 2", null);
choose.append("Item 3", null);
choose.addCommand(backCommand);
choose.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
}

MobileComputing Workshop page 91 G. Juen, 02.07.2008

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);
}

MobileComputing Workshop page 92 G. Juen, 02.07.2008


public void commandAction(Command c, Displayable d) {
if (c == exitCommand) {
notifyDestroyed();
return;
}
if (c == backCommand) {
// the if is not necessary here
if (d == choose || d == input || d == today ||
d == textIO)
display.setCurrent(menu);
return;
}
switch (((List)d).getSelectedIndex()) {
case 0: display.setCurrent(input); break;
case 1: display.setCurrent(choose); break;
case 2: display.setCurrent(soundAlert); break;
case 3: display.setCurrent(today); break;
case 4: display.setCurrent(form); break;
}
}
}
MobileComputing Workshop page 93 G. Juen, 02.07.2008

6.6 Exercise

Exercise 1: Pizza Choice

Develop a MIDlet PizzaChoice according to the following specification


• We have a main form entryScreen with an explaining introduction and the
following commands:
Start, Exit
• With the command Start we go to a second form selectPizza with the
menu:

Tonno
Salami
Scampi

The only command is Back, which goes back to the entryScreen.


• If the users selects a pizza a message occurs:
You selected … (Hint: take Alert)

MobileComputing Workshop page 94 G. Juen, 02.07.2008


Exercise 2: What Client

Develop a MIDlet WhatClient in a separate MIDlet-suite WhatClient with the


following menu
Read GPS
Set Ylivieska
Set Bocholt
Set Position
Search devices
Exit

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.

MobileComputing Workshop page 95 G. Juen, 02.07.2008

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")

MobileComputing Workshop page 97 G. Juen, 02.07.2008

7.2 Example for a HTTP-connection


// detailed import lines in order to document
// which class belongs to which package
import java.io.DataInputStream;
import java.io.IOException;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;

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);

// desired endpoint of the http connection


String url = "http://www.cou.fi/index.asp";

HttpConnection c = null; // the connection itsself


DataInputStream dis = null; // the stream to read from
:

MobileComputing Workshop page 99 G. Juen, 02.07.2008

:
try {
c = (HttpConnection) Connector.open(url); // open
c.setRequestMethod(HttpConnection.GET); // or POST

// we can only read from streams not from connections


dis = c.openDataInputStream();
String rcvMsg=readUntilEof(dis); // read whole page
message(rcvMsg); // show the received page (as text)
} catch (Exception e) {
message(e.getMessage());
}
try {dis.close();} catch (Exception ignore) {}
try {c.close();} catch (Exception ignore) {}
}

MobileComputing Workshop page 100 G. Juen, 02.07.2008


// display text on phone's display and console
void message(String msg){
form.append(new StringItem(null,msg));// phone display
System.out.println(msg); // console
}

// read characters from a data input stream


// until eof is reached
String readUntilEof(DataInputStream dis)
throws IOException{
StringBuffer sb = new StringBuffer();
int ch; // return value of dis.read it int
while ((ch = dis.read()) != -1) { // read until Eof
sb.append((char) ch); // it was a char
}
return sb.toString();
}

MobileComputing Workshop page 101 G. Juen, 02.07.2008

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

MobileComputing Workshop page 103 G. Juen, 02.07.2008

WHAT http interface

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=

without carriage-return and linefeed (for cut & paste purpose):


http://what.et.bocholt.fh-
ge.de:443/what/setposition.php?uid=3857ee159a1a42541c9e0c54
2ffddfff&set=6.6527,51.8398&type=mobile&msg=BocholtCampus&s
etmode=
MobileComputing Workshop page 104 G. Juen, 02.07.2008
Hints

• In order to avoid that everybody sits exactly on the same point


you should vary in the last digits: 6.6xxx,51.8xxx
• Usually you would put the http-communication into commandAction(..).
However, this will result in an error message during runtime. What does this
error message mean?
• The solution is to put the http-communication into a separate thread (see
code fragment below).

MobileComputing Workshop page 105 G. Juen, 02.07.2008

Code fragment for a MIDlet with a thread


public class ExampleMidlet extends MIDlet {
String url;

class ThreadHandler extends Thread {


public void run() {
// code which uses url and
// should run in a separate thread
}
}
:
public void commandAction(..) {
:
if (...)
url="http://web.de";
new ThreadHandler().start();
return;
if (...)
:
}
}
MobileComputing Workshop page 106 G. Juen, 02.07.2008
Tool to find UTM coordinates on a map
http://mapmaker.donkeymagic.co.uk/

MobileComputing Workshop page 107 G. Juen, 02.07.2008

7.4 Example for a Socket Connection

// detailed import lines in order to document


// which class belongs to which package
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import javax.microedition.io.Connector;
import javax.microedition.io.SocketConnection;

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;
:

MobileComputing Workshop page 108 G. Juen, 02.07.2008


public class HttpClientViaSocketConnection extends MIDlet
{
Form form = null;
public HttpClientViaSocketConnection() {
}

protected void destroyApp(boolean arg0) throws


MIDletStateChangeException {
}

protected void pauseApp() {


}

protected void startApp()..


}

MobileComputing Workshop page 109 G. Juen, 02.07.2008

protected void startApp() throws


MIDletStateChangeException {
// prepare phone display
form = new Form("HTTP Client with sockets");
Display display = Display.getDisplay(this);
display.setCurrent(form);

// desired endpoint of the http connection


A String url = "socket://www.cou.fi:80";

B SocketConnection client = null; // the connection


DataInputStream dis = null; // stream to read from
C DataOutputStream dos = null; // stream to write into

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();

// read server response


G String rcvMsg = readUntilEof(dis);
H message(rcvMsg);
} catch (Exception e) {
e.printStackTrace();
message(e.getMessage());
}
try {dis.close();} catch (Exception ignore) {}
try {dos.close();} catch (Exception ignore) {}
try {client.close(); } catch (Exception ignore) {}
}

The following remarks refer to the difference to the HTTP-Connection-based HTTP


client from above:

MobileComputing Workshop page 111 G. Juen, 02.07.2008

A In the protocol part of the URL http is substituted by socket. The


address cou.fi:80 remains the same.
B, D Here SocketConnection is used instead of HttpConnection.
C SocketConnection is a raw data-Connection. The programmer has to
care for the application protocol (here http) by himself. This means that he
has to set up the request string, see line E, and to send it via the
DataOutputStream.
E http is a line-oriented protocol. The strind in line E is the most simple http-
request. It consists of a single line terminated by a \n followed by an
empty line (the second \n).
G, H correspond to the according lines of the HttpConnection based
HttpClient with its methods readUntilEOF() and message().

MobileComputing Workshop page 112 G. Juen, 02.07.2008


Answer:
HTTP/1.1 200 OK HTTP-status response
Date: Mon, 09 Jun 2008 19:26:07 GMT Begin HTTP-Parameter
Server: Microsoft-IIS/6.0 :
Content-Length: 19134 :
Content-Type: text/html End HTTP-Parameter
Empty line
<html> Begin of Data
<head> :
<title>Keski-Pohjanmaan ammattikorkeakoulu</title>
: :
</head> :
<body> :
: :
</body> :
</html> End of Data

MobileComputing Workshop page 113 G. Juen, 02.07.2008

8 Bluetooth
8.1 Bluetooth features

Radio frequency based

ISM (Industrial Scientific Medicine, royalty free) 2.402 GHz-2.483GHz

Other ISM users:


Cordless phones 3rd generation
WLAN 11Mbit/s (802.11b)
WLAN 54Mbit/s (802.11g)
Microwave

Short distance communication

Class 1: 100m 100 mW,


Class 2: 20m 10 mW
Class 3: 10m 1 mW
MobileComputing Workshop page 114 G. Juen, 02.07.2008
Transfer rates

Symmetric asymmetric 723,2 kbit/s / 57,6 kbit/s


Symmetric (Data) 432,6 kbit/s / 432,6 kbit/s
Symmetric (Speech) 64 kbit/s / 64 kbit/s

Communication type

1 to 1 (point-to-point)
1 to many (multipoint device)

Bluetooth Adress

48 bit number, e.g. 000B0D14D80D (hex format)

Network structure (Piconet)

255 devices = 8 active devices + 247 parking devices

MobileComputing Workshop page 115 G. Juen, 02.07.2008

8 active devices = 1 master + 7 slaves


master = one of the 8 active devices which takes
the additional coordinator role

MobileComputing Workshop page 116 G. Juen, 02.07.2008


piconet = 255 devices

247 not active 8 active devices

1 master 7 slaves
slaves

MobileComputing Workshop page 117 G. Juen, 02.07.2008

Security configuration

• devices can be visible or not


• establishing a connection requires authentification or not

Security class Visibility Authentification


Low yes no
Medium yes yes
High no yes

MobileComputing Workshop page 118 G. Juen, 02.07.2008


8.2 JAVA SE Bluetooth programs

Bluecove Bluetooth API


http://code.google.com/p/bluecove/
• free
• equires Windows XP service stack 2 (with the Microsoft BT stack)

Avetana Bluetooth API


http://www.avetana-gmbh.de/avetana-gmbh/produkte/jsr82.eng.xml
• free for Linux

MobileComputing Workshop page 119 G. Juen, 02.07.2008

• not free for Windows


(25€/80€ for SW hard coded stack for 3/10 BT-adresses)
• works with the Microsoft and the Widcom BT stack

MobileComputing Workshop page 120 G. Juen, 02.07.2008


8.3 Getting started: read GPS receiver data with the PC
We want to read from
• GPS device with
• known BT-adress
• with a PC program (not a MIDlet)

The JAVA SE program

import javax.io.*;
import javax.microedition.io.*;
import de.juen.util.InpStrReader;
public class SimpleGPSReaderPC {
public static void main(String[] args) ..
}

MobileComputing Workshop page 121 G. Juen, 02.07.2008

public static void main(String[] args) {


InpStrReader in = null;
try {
// connect to the GPS device ..
A StreamConnection con = (StreamConnection)
Connector.open ("btspp://000B0D14D80D:1;"+
"authenticate=false; master=false;encrypt=false");
B in = new InpStrReader(con);
// .. and read a single line
C System.out.println(in.readLine());
} catch (IOException e) {
D System.out.println(e.getMessage());
}
if (in!=null) in.close();

MobileComputing Workshop page 122 G. Juen, 02.07.2008


A The address btspp://000B0D14D80D:1 contains 3 elements
- protocol part btspp:
we want to establish a BT connection over the Serial Port Profile
(i.e. a serial connection)
- address 000B0D14D80D
contains the 48 bit BT address in hex code
- additional parameters separated by semicolons
B The return value of the class method Connector.open is a handle for the
connection, A. If we want to communicate via this connection we need an
input- and/or output stream (for raw byte communication) or even a reader
and writer (for character based communication). Instead of the Java
InputStreamReader we use our own InpStrReader class for reading
CRLF (carriage return + linefeed) terminated lines from the connection.
C Reads a single line (terminated with CRLF), in.readLine(..), from the
GPS-device and displays the line on the console.
D In case of an error we see an error message instead of the GPS-line.

MobileComputing Workshop page 123 G. Juen, 02.07.2008

The class InpStrReader

The Java ME InputStreamReader class does not provide a readLine method.


Therefore we use our own InpStrReader (External JarFile JuenUtil.jar)

MobileComputing Workshop page 124 G. Juen, 02.07.2008


package de.juen.util;
public class InpStrReader {
InputStream in;
StreamConnection con;
public InpStrReader(StreamConnection con)
throws IOException {
this.con = con;
this.in = con.openInputStream();
}
String readLine() ..

public void close() {


// we try to close anyhow and ignore any exception
try {in.close(); } catch (Exception ignore) { }
try {con.close();} catch (Exception ignore) { }
}
}

MobileComputing Workshop page 125 G. Juen, 02.07.2008

The most important method of our InpStrReader

String readLine() throws IOException {


// read input stream until LF (linefeed) is found
// CR (carriage return) and LF are skipped

A StringBuffer buf = new StringBuffer();


int i;
while (true) { // exit loop via break
B i = in.read(); // read a single character
C if (i == 13) continue;// ignore carriage return
D if (i == 10) break; // linefeed -> end of line
E buf.append((char) i); // interprete number as char,
} // e.g 36-> $
F return buf.toString(); // buf contains the line
}

MobileComputing Workshop page 126 G. Juen, 02.07.2008


A The string buffer collects the receiving characters until we have obtained a
complete line.
B We read only one character per read call. We read the characters as
equivalent number (the return value of read is int), e.g. if we read the
character A the variable i has the value 65 (decimal) or 41 (hex).
C, D We stop the read if we detect a LF (linefeed → decimal 10), D. CR
(carriage return → decimal 13) is skipped, C. The CRLF sequence will not
be part of the line and is therefore not stored into buf.
E We add the received character to the StringBuffer but have to tell the
compiler that it should cast the int to char (this does not mean any
operation during runtime. It only satisfies the compiler which normally does
not allow to copy int to s.th. else than int).
F The StringBuffer buf now contains the received line. It is "unloaded"
into String which is the expected format for the return value.

MobileComputing Workshop page 127 G. Juen, 02.07.2008

8.4 Exercise
Implement and test the SimpleGPSReaderPC.

Hints

• Create a New Java Project SimpleGPSReaderPC (not a MIDlet Suite)


• Add blueCove-2.0.1.jar and JuenUtilities.jar to the project’s build
path (→ see below)

Add external Java archives (JAR-files) to the project build path

Mark the project, then


select Project →
Properties

MobileComputing Workshop page 128 G. Juen, 02.07.2008


• Select Java Build Path
→ Folder Libraries
• Click Add External
JARs
• Select the JAR-file
from the file system

MobileComputing Workshop page 129 G. Juen, 02.07.2008

8.5 Developing and testing Java ME-Bluetooth programs on the PC

With mobile phone simulators

• 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

MobileComputing Workshop page 130 G. Juen, 02.07.2008


8.5.1 Avetana stack with Mpowerplayer

Idea

• Mpowerplayer is a device (like the WTK devices)


• avetana-Bluetooth stack can be included into the device

Steps

1) Download aventana-Stack (avatanaBluetooth.jar)


from http://www.avetana-gmbh.de/avetana-gmbh/
2) Download Mpowerplayer (mpp-sdk-1185.zip)
from http://www.mpowerplayer.com/
3) Unpack mpp-sdk-1185.zip e.g. into yourlibs\mpp-sdk-1185
4) Copy avatanaBluetooth.jar into yourlibs\mpp-sdk-1185.

MobileComputing Workshop page 131 G. Juen, 02.07.2008

5) Add Mpowerplayer as additional device into your Eclipse IDE:

Press

MobileComputing Workshop page 132 G. Juen, 02.07.2008


Browse to yourlibs\mpp-sdk-1185

then and press and

MobileComputing Workshop page 133 G. Juen, 02.07.2008

6) Add avetanaBluetooth.jar to Mpowerplayer

Mark Mpowerplayer and press

MobileComputing Workshop page 134 G. Juen, 02.07.2008


Press

and select avetanaBluetooth.jar in the coming file-menu.

MobileComputing Workshop page 135 G. Juen, 02.07.2008

Press

Remark

This Mpowerplayer Bluetooth integration works only with the avetana-stack not
with bluecove!!

MobileComputing Workshop page 136 G. Juen, 02.07.2008


8.5.2 Bluecove Stack with Mpowerplayer

Idea

• Mpowerplayer can also be started from the command line


• Start Mpowerplayer from Eclipse as “External Tool”

MobileComputing Workshop page 137 G. Juen, 02.07.2008

Select right the menu sequence

MobileComputing Workshop page 138 G. Juen, 02.07.2008


Right click on Program,
select New

Location has to be set with the


file system location of the java
virtual machine javaw.exe.
Meaning of the Arguments*) field
• start javaw.exe with the class
com.mpp.player.PowerPl
ayerApp
• with the bluecove-library in the
classpath
• and the MIDlet defined by the
JAD-file of the actually
focussed project

MobileComputing Workshop page 139 G. Juen, 02.07.2008

The outward appearance of the


FirstStep MIDlet in the
mpowerplayer

*) 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:

Mpowerplayer uses the deployed version of the MIDlet !

MobileComputing Workshop page 140 G. Juen, 02.07.2008


8.6 Exercise
Convert SimpleGPSReaderPC to a MIDlet and test it with Mpowerplayer (and
Bluecove)

Remark

If you use the Bluecove model the project has first to be deployed if modifications
have been carried out before you start Mpowerplayer

How to deploy: Right click on the project

MobileComputing Workshop page 141 G. Juen, 02.07.2008

8.7 Bluetooth protocols

http://developers.sun.com/techtopics/mobility/apis/articles/bluetoothintro/images/fig1_sm.jpg

MobileComputing Workshop page 142 G. Juen, 02.07.2008


SDP (Service Discovery Protocol)

Application

Java APIs for Bluetooth Wireless Technology (JSR-082)

OBEX (Object Exchange)

SDP (Service Discovery) RFCOMM (Serial Connection )

• defines a service as any feature of a Bluetooth-device (server)


that is usable by another Bluetooth-device (client).
• defines how a client acts to discover server (with services).

MobileComputing Workshop page 143 G. Juen, 02.07.2008

Remarks on service discovery:


• A single Bluetooth-device can be both a server and a client.
• Most services are related to profiles.
• An SDP server maintains a set of service records each of which describe a
single service. The most important item is the service’s UUID (universally
unique identifier → BT-adress).
service record
1 UUID for service 1, ...
2 UUID for service 2, ...
3 UUID for service 3, ...
:

MobileComputing Workshop page 144 G. Juen, 02.07.2008


RFCOMM (Radio Frequency COMMunication)

Application

Java APIs for Bluetooth Wireless Technology (JSR-082)

OBEX (Object Exchange)

SDP (Service Discovery) RFCOMM (Serial Connection )

• emulates a RS-232 serial port


• provides serial data transfer

MobileComputing Workshop page 145 G. Juen, 02.07.2008

OBEX (OBject EXchange)

Application

Java APIs for Bluetooth Wireless Technology (JSR-082)

OBEX (Object Exchange)

SDP (Service Discovery) RFCOMM (Serial Connection )

• defines the exchange of data objects


• defines a folder-listing object, which is used to
browse the contents of folders on a remote device
• uses RFCOMM as the main transport layer

MobileComputing Workshop page 146 G. Juen, 02.07.2008


8.8 Bluetooth-for-Java (JSR-82) profiles

Profile: Set of API’s for particular areas of application

Serial Port Profile (SPP)


• defines how to set-up virtual serial ports and connect two Bluetooth-devices.
• uses the RFCOMM protocol to provide serial-port emulation.
• SPP is dependent on GAP.

Generic Access Profile (GAP)


• provides the basis for all other profiles
• defines a consistent means to establish a baseband link between Bluetooth
enabled devices. In addition to this, GAP defines the following:
• must be implemented in all Bluetooth devices
• Generic procedures for discovering and linking to devices

MobileComputing Workshop page 147 G. Juen, 02.07.2008

Generic Access Profile (GAP)

SDAP PAN CTP


Service Discovery
Application Profile
HCRP HID

Serial Port Profile (SPP)

DUN GOEP
Generic Object
Exchange Profile
HFP
FTP OPP

FAXP SYNCH BIP

LAP BPP

MobileComputing Workshop page 148 G. Juen, 02.07.2008


GAP Generic Access Profile
SDAP Service Discovery Application Profile
HCRP Hardcopy Cable Replacement Profile
CTP Cordless Telephony Profile
HID Human Interface Device Profile
PAN Personal Area Networking Profile
SPP Serial Port Profile
DUN Dial-up Networking Profile
FAXP FAX Profile
HFP Hands Free Profile
LAP LAN Access Profile
GOEP Generic Object Exchange Profile
FTP File Transfer Profile
OPP Object Push Profile
SYNCH Synchronisation Profile
BIP Basic Imaging Profile
BPP Basic Printing Profile
MobileComputing Workshop page 149 G. Juen, 02.07.2008

Meaning of the hierarchy above

indented profiles need profile of the layer above. e.g.


GOEP needs SPP needs GAP

8.9 The JSR-82 API

Topics

• Register services (not in this course)


• Discover devices and services on the devices
• Establish a connection and communicate

MobileComputing Workshop page 150 G. Juen, 02.07.2008


8.10 Search for devices and services (Discovery)
Our SimpleGPSReader only works if the BT-address of the BT-device is known.
Typical BT-applications do not know the BT addresses of the service they want to
consume:
• Is there a printer?
• Is there a hot spot over which I can connect to the internet?

Disovery classes

• For device discovery


• For service discovery on these devices
• Java package: javax.bluetooth

MobileComputing Workshop page 151 G. Juen, 02.07.2008

Sequence diagram of a combined device/service search

Search for devices Search for services


myApplication discoveryAgent myApplication discoveryAgent
(Singleton) (Singleton)

initiate searchDevices() initiate


device startInquiry() service
searchServices ()
search search

deviceDiscovered() servicesDiscovered()
do s.th. do s.th.
arbitrary arbitrary

deviceDiscovered() servicesDiscovered()

deviceSearchCompleted()
inquiryCompleted() serviceSearchCompleted()

MobileComputing Workshop page 152 G. Juen, 02.07.2008


Features of device and service search

Device and service search are asynchronous


• The main program starts the inquiry which then runs in an own thread:
startInquiry(..) for all devices
searchServices(..) for all services offered by a single device
• If an inquiry thread finds s.th. it calls a method provided by the main program
for that purpose (call back method). Remark: workflow is similar to an
interrupt service routine:
deviceDiscovered(..) when a device has been found
servicesDiscovered(..) when one or more services have been found
• When the inquiry finishes it calls another callback method:
inquiryCompleted for the actual device search
(There is only one at a given time)
serviceSearchCompleted for one of the service searches
(There might be more than one at a given time)

MobileComputing Workshop page 153 G. Juen, 02.07.2008

The callback-method contract

The signature of the callback methods are defined in the interface


DiscoveryListener:
public void inquiryCompleted(int discType)

discType is one of
INQUIRY_COMPLETED end of normal search
INQUIRY_TERMINATED terminated by the program
INQUIRY_ERROR terminated because of an error

MobileComputing Workshop page 154 G. Juen, 02.07.2008



public void deviceDiscovered
(RemoteDevice btDevice, DeviceClass cod)

btDevice The device which has been found, contains


BT adresse
name
cod The device class of the device, contains
major device class
minor device class
service class

MobileComputing Workshop page 155 G. Juen, 02.07.2008


public void servicesDiscovered
(int transID, ServiceRecord[] servRecord)

transID the transaction ID of the service search thread that found


the service(s)
servRecord list of the services having been found. The most important
attribute of a service is the URL under which the
service can be called

MobileComputing Workshop page 156 G. Juen, 02.07.2008



public void serviceSearchCompleted
(int transID, int respCode)

transID transaction ID identifies the service search which has


completed
respCode is one of
SERVICE_SEARCH_COMPLETED end of normal search
SERVICE_SEARCH_TERMINATED terminated by the
program
SERVICE_SEARCH_ERROR terminated because of
an error

MobileComputing Workshop page 157 G. Juen, 02.07.2008

8.11 Device Discovery Classes


Package javax.bluetooth

Overview of the functionality

• Searching for all type of devices


• Searching for devices with a given profile (e.g. "only printers")
• Retrieving device parameters (e.g. BT address, name)

MobileComputing Workshop page 158 G. Juen, 02.07.2008


List of Classes

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)

MobileComputing Workshop page 159 G. Juen, 02.07.2008

8.12 Service discovery classes


Package javax.bluetooth

Overview of the functionality

• searching for services on a given device


• retrieving service attributes
• simultaneously searching for services and retrieving their attributes
• terminating a service search transaction in progress.

MobileComputing Workshop page 160 G. Juen, 02.07.2008


List of Classes
UUID
128 bit unsigned integer (some short UUIDs are 16 or 32 bit) which serves as
a universally unique identifier for the corresponding service

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.

MobileComputing Workshop page 161 G. Juen, 02.07.2008

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.

servicesDiscovered() is called when services are discovered.


serviceSearchCompleted() is called when a service search transaction
is completed or cancelled.

MobileComputing Workshop page 162 G. Juen, 02.07.2008


8.13 Device class → kind of device/service

23 13 12 8 7 3 1 0
service class maj. device class minor device class reser.

We talk about a 24 bit register in the BT-stack which specifies


• The class of the device (e.g. mobile phone OR printer OR ...)
• The classes of all services offered by the device
(e.g. phone AND calendar data exchange AND …)

MobileComputing Workshop page 163 G. Juen, 02.07.2008

Major device class number

23 13 12 8 7 3 1 0
service class maj. device class minor device class reser.

Construction of JSR-082 major device class number


X X X X X 0 0 0 0 0 0 0 0

Example: Phone: 0x200


0 0 0 1 0 0 0 0 0 0 0 0 0
hex code → 2 0 0

(max. number = 0x1F00 → "Uncategorized")

MobileComputing Workshop page 164 G. Juen, 02.07.2008


Major Device class: list of JSR-82 numbers

Value (hex) Contents


0 Miscellaneous
100 Computer
200 Phone
300 LAN/Network access point
400 Audio/Video
500 Peripheral (mouse, joystick, keyboard)
600 Imaging (printer, display, scanner, camera)
700 Wearable
1F00 Uncategorized

Java call: rd.getMajorDeviceClass


with a RemoteDevice instance rd
Remark: Device classes can be defined by numbers
because a device may only have one
MobileComputing Workshop page 165 G. Juen, 02.07.2008

Service Class

23 13 12 8 7 3 1 0
service class maj. device class minor device class reser.

Construction of JSR-082 service class number


X X X X X X X X X X X 0 0 0 0 0 0 0 0 0 0 0 0 0

Example (Phone + Object Transfer + Networking)


0 1 0 1 0 0 1 0 0 0 0

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

MobileComputing Workshop page 166 G. Juen, 02.07.2008


Service class: list of JSR-82 numbers (Hex-format)
active JSR-82 Contents
bit number
13 2000 Limited Discoverable Mode
14 4000 reserved
15 8000 reserved
16 10000 Positioning (Location identification)
17 20000 Networking (LAN, Ad hoc, ..)
18 40000 Rendering (Printing, Speaker, ..)
19 80000 Capturing (Scanner, Microphone,)
20 100000 Object Transfer (v-Inbox, v-Folder, ..)
21 200000 Audio (Speaker, Microphone, Headset service, ..)
22 400000 Telephony
(Cordless telephony, Modem, Headset service, ..)
23 800000 Information (WEB-server, WAP-server, ..)

MobileComputing Workshop page 167 G. Juen, 02.07.2008

Java call: rd.getServiceClasses()


with a RemoteDevice instance rd
Remark: Service classes are defined by activated bits because a
device may have more than one service belonging to
different classes (→example below)

Typical mobile phone service class number (bit view → p. 166)

Major Device Class: 200 (Phone)


Service Class
400000 Telephony
+ 100000 Object Transfer
+ 20000 Networking
= 520000

Holux GPS mouse

Major Device Class: 1f00 (Uncategorized)


Service Class: 0

MobileComputing Workshop page 168 G. Juen, 02.07.2008


Problem with Holux GPS mouse

Theory Holux
Major Device Class 1F00 1F00
Minor Device Class ? 0
Service Class 10000 0

8.14 Services search configuration


Searches for services on a remote Bluetooth device can be configured
• service filter
To be specified as UUID in uuidSet[]
(we filter according to protocols and/or profiles)
• result filter
(we are only interested in particular attributes)
→ not in this course

MobileComputing Workshop page 169 G. Juen, 02.07.2008

Some service related UUID's (16bit and 128 bit)

"Service" name UUID


SDP 0x0001
RFCOMM 0x0003
OBEX 0x0008
HTTP 0x000C
L2CAP 0x0100
Serial Port 0x1101
ServiceDiscoveryServerServiceClassID 0x1000
BrowseGroupDescriptorServiceClassID 0x1001
PublicBrowseGroup 0x1002
OBEX Object Push Profile 0x1105
OBEX File Transfer Profile 0x1106
Personal Area Networking User 0x1115

MobileComputing Workshop page 170 G. Juen, 02.07.2008


"Service" name UUID
Network Access Point 0x1116
Group Network 0x1117
Application (example), 128 bit 0x1020304 .. e1f100

MobileComputing Workshop page 171 G. Juen, 02.07.2008

Example
UUID[] searchList = new UUID[1];

// look only for Serial Port


searchList[0] = new UUID(0x1101);

int trans = agent.searchServices(


null, // we only want default parameters
searchList, // devices have to meet one of the
// UUIDS of this list
dev, // the device where to search
dl // the object with the callbacks
// according to the DiscoveryListener
// interface
);

MobileComputing Workshop page 172 G. Juen, 02.07.2008


8.15 Service discovery: an example
We look for a GPS service
class SearchGPSService
private int transactionID[];
private Vector gpsDeviceList;
public getGPSService()

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

MobileComputing Workshop page 174 G. Juen, 02.07.2008


searchServices()
for all devices in gpsDeviceList
if a GPS service has been found return
searchServices (filter: only SPP)
put transaction ID of started search into transactionID list
increment serviceSearchCount
if serviceSearchCount has achieved max. number of possible
service searches
wait for FREE SERVICE SEARCH SLOT

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;

public class SearchGPSDevice


implements DiscoveryListener {

// BT-mouse is major device class "Uncategorized"


static final int MAJOR_DEVICE_CLASS = 0x1f00;

// service class is "Positioning"


static final int SERVICE_CLASS = 0x10000;

// DiscoveryAgent for the local Bluetooth device.


private DiscoveryAgent agent;

// max number of service searches that can occur


// at any one time.
MobileComputing Workshop page 176 G. Juen, 02.07.2008
private int maxServiceSearches = 0;

// number of service searches that are


// presently in progress.
private int serviceSearchCount;

// transaction IDs of the active service searches


// (service searches that are presently in progress)
private int transactionID[];

// service record to the gps service that has been found


private ServiceRecord gpsService;

// list of the GPS devices found during an inquiry


private Vector gpsDeviceList;

// where to send the debug messages


private Log log;

MobileComputing Workshop page 177 G. Juen, 02.07.2008

// constructor prepares the device/service discovery


public SearchGPSDevice(Log log) ..

// adds a service search transaction ID to the table


// of active service searches
private void addToTransactionTable(int trans) ..

// Removes a service search transaction ID from the


// table of active service searches
private void removeFromTransactionTable(int trans) ..

// carries out a services search on a list of


// remote devices
private ServiceRecord searchServices
(RemoteDevice[] devList) ..

// Finds the first device with gps service


public ServiceRecord getGPSService() ..

MobileComputing Workshop page 178 G. Juen, 02.07.2008


// called when a device has been found during an inquiry
public void deviceDiscovered
(RemoteDevice btDevice, DeviceClass cod) ..

// called when a service search is completed


public void serviceSearchCompleted
(int transID, int respCode)..

// called when service(s) are found during a service


// search
public void servicesDiscovered
(int transID, ServiceRecord[] servRecord) ..

// Called when a device discovery transaction


// is completed
public void inquiryCompleted(int discType) ..

MobileComputing Workshop page 179 G. Juen, 02.07.2008

The methods
// constructor prepares the device/service discovery
public SearchGPSDevice(Log log)
throws BluetoothStateException {
this.log = log; // where to send the debug messages

// retrieve the local Bluetooth device object.


LocalDevice local = LocalDevice.getLocalDevice();

// retrieve the DiscoveryAgent object that allows


// us to perform device and service discovery.
agent = local.getDiscoveryAgent();

MobileComputing Workshop page 180 G. Juen, 02.07.2008


// retrieve the max number of concurrent service
// searches which can exist at the same time
try {
maxServiceSearches = Integer.parseInt
(LocalDevice.getProperty("bluetooth.sd.trans.max"));
log.debug("maxServiceSearches: " + maxServiceSearches;
} catch (NumberFormatException e) {
log.debug("NumberFormatException: " + e.getMessage());
maxServiceSearches = 1; // 1 will always work
}

// initialize the list of active service searches


transactionID = new int[maxServiceSearches];
for (int i = 0; i < maxServiceSearches; i++) {
transactionID[i] = -1; // -1 means "no entry"
}

// prepare list for all devices that where found


gpsDeviceList = new Vector();
}
MobileComputing Workshop page 181 G. Juen, 02.07.2008

// adds a service search transaction ID to the table


// of active service searches
private void addToTransactionTable(int trans) {
for (int i = 0; i < transactionID.length; i++) {
if (transactionID[i] == -1) { // free entry
transactionID[i] = trans; // fill in
return;
}
}
}

// Removes a service search transaction ID from the


// table of active service searches
private void removeFromTransactionTable(int trans) {
for (int i = 0; i < transactionID.length; i++) {
if (transactionID[i] == trans) {
transactionID[i] = -1; // empty entry
return;
}
}
}
MobileComputing Workshop page 182 G. Juen, 02.07.2008
// carries out a services search on a list of
// remote devices
private ServiceRecord searchServices
(RemoteDevice[] devList) {
/* remark:
searchServices blocks until a GPS service has
been found or until the search is terminated without
having found any
*/

// search only for UUID's from the UUID[] vector


UUID[] searchList = new UUID[1];

// we look only for Serial Port


searchList[0] = new UUID(0x1101);

// Start a search on as many devices as the system


// can support.

MobileComputing Workshop page 183 G. Juen, 02.07.2008

for (int i = 0; i < devList.length; i++) {


// If we have found a GPS service we do not need
// to initiate a service on another device
if (gpsService != null) {
return gpsService;
}
try {
// start services search on device i
int trans = agent.searchServices
(null, searchList, devList[i], this);
addToTransactionTable(trans);
log.debug("Services search #" + trans +
" started");
} catch (BluetoothStateException e) {
// Failed to start the search on this device,
// try another device.
}

MobileComputing Workshop page 184 G. Juen, 02.07.2008


// If we have still free search capacity start
// another services search, otherwise wait
synchronized (this) {
serviceSearchCount++;
if (serviceSearchCount >= maxServiceSearches) {
try {
this.wait();// wait for notify on page 193
} catch (Exception e) {}
}
}
} // end of for-loop

MobileComputing Workshop page 185 G. Juen, 02.07.2008

// Now all services searches have been started


// Wait until they have completed.
while (serviceSearchCount > 0) {
synchronized (this) {
try {
this.wait(); // wait for notify on page 193
} catch (Exception e) {
}
}
}
return gpsService; // null if no service has been found
}

MobileComputing Workshop page 186 G. Juen, 02.07.2008


// Finds the first device with gps service
public ServiceRecord getGPSService() {
// try to find a gps service in the list of
// cached devices
ServiceRecord serv;
RemoteDevice[] devList =
agent.retrieveDevices(DiscoveryAgent.CACHED);
if (devList != null) {
serv=searchServices(devList);
if (serv!=null) return gpsService;
}

// try to find a gps service in the list of


// pre-known devices
devList = agent.retrieveDevices
(DiscoveryAgent.PREKNOWN);
if (devList != null) {
serv=searchServices(devList);
if (serv!=null) return gpsService;
}
MobileComputing Workshop page 187 G. Juen, 02.07.2008

// Did not find a gps service in the list of pre-known


// or cached devices => start an inquiry to find all
// devices that could be gps devices and search on
// those devices.
try {
log.debug("Devices search started");
agent.startInquiry(DiscoveryAgent.GIAC, this);
// Wait until all BT-devices have been found before
// starting the services search
synchronized (this) {
try {
this.wait(); // wait for notify on page 196
} catch (Exception e) {
}
}
} catch (BluetoothStateException e) {
log.debug("Error during devices search: "
+ e.getMessage());
}

MobileComputing Workshop page 188 G. Juen, 02.07.2008


if (gpsDeviceList.size() > 0) { // we found devices
devList = new RemoteDevice[gpsDeviceList.size()];
// copy Vector type -> array
gpsDeviceList.copyInto(devList);
// blocking search until we have found one
return searchServices(devList);
}
return null;
}

MobileComputing Workshop page 189 G. Juen, 02.07.2008

// called when a device has been found during an inquiry


public void deviceDiscovered
(RemoteDevice btDevice, DeviceClass cod) {
/*
btDevice The device which has been found
cod The device class, contains
major device class
minor device class
service class
remark:
The same device may be returned multiple times.
*/
log.debug(" Device found");
log.debug(" BT-Adress: "
+ btDevice.getBluetoothAddress());
try {
log.debug(" Name: "
+ btDevice.getFriendlyName(false));
} catch (IOException e) {
e.printStackTrace();
}
MobileComputing Workshop page 190 G. Juen, 02.07.2008
log.debug(" Major Device Class: 0x"
+ Integer.toHexString(cod.getMajorDeviceClass()));
log.debug(" Minor Device Class: 0x"
+ Integer.toHexString(cod.getMinorDeviceClass()));
log.debug(" Service Class: 0x"
+ Integer.toHexString(cod.getServiceClasses()));

// only search on devices with the required


// device/service class profile
/*
if ((cod.getMajorDeviceClass() == MAJOR_DEVICE_CLASS)
A && (cod.getServiceClasses() & SERVICE_CLASS) != 0)
){
gpsDeviceList.addElement(btDevice);
}
}
A has to be removed for HOLUX GPS mouse, because service class is 0.

MobileComputing Workshop page 191 G. Juen, 02.07.2008

// called when a service search is completed


public void serviceSearchCompleted
(int transID, int respCode) {
/*
respCode is one of
SERVICE_SEARCH_COMPLETED
SERVICE_SEARCH_TERMINATED
SERVICE_SEARCH_ERROR
transID
transaction ID identifies the corresponding service
search thread (see method searchServices)
*/

// Remove the transaction ID from the table of pending


// service searches
removeFromTransactionTable(transID);
serviceSearchCount--; // number of still running
// service search threads
log.debug("Services search #" + transID + " completed");

MobileComputing Workshop page 192 G. Juen, 02.07.2008


// allow searchServices(..) to start another services
// search ("wait" on page 185) or to finish the
// services search ("wait" on page 186)
synchronized (this) {
this.notifyAll();
}
}

MobileComputing Workshop page 193 G. Juen, 02.07.2008

// Called when service(s) are found during a service


// search
public void servicesDiscovered
(int transID, ServiceRecord[] servRecord) {
/*
transID
the transaction ID of the service search thread
that found services
services
service list of services found
Remark:
The service search thread calls this method when it
founds service(s) on the related device. It conti-
nues the search and calls serviceSearchCompleted
when it really finished its search
*/

MobileComputing Workshop page 194 G. Juen, 02.07.2008


// If this is the first record found, then store this
// record and cancel the remaining searches.
log.debug(" Services search #" + transID + " found "
+ servRecord.length + " services");
if (gpsService == null) {
gpsService = servRecord[0];
// Cancel all the service searches that are presently
// being performed.
for (int i = 0; i < transactionID.length; i++) {
if (transactionID[i] != -1) {
agent.cancelServiceSearch(transactionID[i]);
}
}
}
}

MobileComputing Workshop page 195 G. Juen, 02.07.2008

// Called when a device discovery transaction is


// completed
public void inquiryCompleted(int discType) {
/* discType might be one of
INQUIRY_COMPLETED end of normal search
INQUIRY_TERMINATED terminated by the program
INQUIRY_ERROR terminated because of an error
*/
synchronized (this) {
try {
this.notifyAll();// send notify to wait on page 188
// to finish the "blocking"
// device search
} catch (Exception e) {
}
}
if (gpsDeviceList.size() > 0) // we found devices
log.debug(" Found "+gpsDeviceList.size() + " possible GPS
log.debug("Devices search completed");
}
MobileComputing Workshop page 196 G. Juen, 02.07.2008
The Log-interface

public interface Log {


void debug(String msg);
}

MobileComputing Workshop page 197 G. Juen, 02.07.2008

The main program

import javax.bluetooth.*;
import javax.microedition.io.*;

public class SearchGPSDevicePC implements Log {

void run() ..

// contract in Log interface → debug msg to console


public void debug(String msg) {
System.out.println(msg);
}

// create a SearchGPSDevicePC instance and cll run()


public static void main(String[] args) {
(new SearchGPSDevicePC()).run();
}
}

MobileComputing Workshop page 198 G. Juen, 02.07.2008


void run() {
SearchGPSDevice client = null;
// search for GPS service
try {
client = new SearchGPSDevice(this);
} catch (BluetoothStateException e) {
debug("Failed to start Bluetooth System: "
+ e.getMessage());
}
ServiceRecord gpsService = client.getGPSService();
if (gpsService == null) {
debug("No GPS service found");
return;
}

// retrieve the connection string.


String conURL = gpsService.getConnectionURL(
ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);
debug("conURL: "+conURL);

MobileComputing Workshop page 199 G. Juen, 02.07.2008

// try to connect and read


InpStrReader in = null;
StreamConnection con = null;
try {
// connect to GPS service
con = (StreamConnection) Connector.open(conURL);
// and read first line
in = new InpStrReader(con);
debug(in.readLine());
} catch (Exception e) {
debug(e.getMessage());
}
if (in != null) in.close();
}

MobileComputing Workshop page 200 G. Juen, 02.07.2008


Console output
A BlueCove version 2.0.1 on winsock
B maxServiceSearches: 1
C Devices search started
Device found
BT-Adress: 000B0D14D80D
Name: HOLUX GPSlim236
D Major Device Class: 0x1f00 Uncategorized
Minor Device Class: 0x0
E Service Class: 0x0 should be 0x10000
Device found
BT-Adress: 0015DE21B729
Name: Nokia 6230i
Major Device Class: 0x200 Phone
Minor Device Class: 0x4
Service Class: 0x52000 Phone+other stuff
F Found 1 possible GPS devices
G Devices search completed

MobileComputing Workshop page 201 G. Juen, 02.07.2008

H Services search #1 started


Services search #1 found 1 services
Services search #1 completed
I conURL: btspp://000B0D14D80D:1;authenticate=false;
encrypt=false;master=false

J $GPGGA,165534.000,5150.5759,N,00637.8046,E,1,05,2.1,
30.8,M,47.3,M,,0000*66

BlueCove stack shutdown completed


A Bluecove output is marked in red
B The max. number of parallel service searches our local device can
execute.
E This number is wrong. A GPS-mouse should provide 0x10000

MobileComputing Workshop page 202 G. Juen, 02.07.2008


F We took only Devices with Major Device Class = 0x1F00 into our device
list. Therefore we have in this application only 1 possible GPS device for
entering the services search.

The number #1 we see here is the transaction id of the particular services


search (we have only one in our test case).
G, H We start the services search not before we have completed the device
inquiry. In order to speed the process up, we could start a services search
immediately after we have found a device.
I The connection URL is obtained from the service record of the service
which has been found.
J The particular meaning of the GPS mouse message is discussed in the
following chapter.
8.16 Exercise
Take the WhatCient and implement the code for Search devices:
we search for devices the name of which starts with HOLUX. On the screen we
want to see the full name und the Bluetooth address. Test it with mpowerplayer.
MobileComputing Workshop page 203 G. Juen, 02.07.2008

9 GPS-Data
9.1 NMEA-format
Source: http://www.gpsinformation.org/dale/nmea.htm

NMEA-Format (National Marine Electronics Association)

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

• Coding: ASCII Text


• Frame ("sentence"):
Line of max. 80 chars terminated with CRLF (carriage return/line feed)
• Each sentence begins with a $.
• Checksum at the end of the line:
starts with * followed by two hex digits representing an 8 bit exclusive OR of
all characters between, but not including, the $ and *.
• Data items are separated by commas.
MobileComputing Workshop page 204 G. Juen, 02.07.2008
Most important NMEA sentences

GPVTG speed over ground


GPGGA time + position data
+ additional information (number of satellites, quality of the data..)
GPRMC time, position, speed over ground ("minimum recommended data")

MobileComputing Workshop page 205 G. Juen, 02.07.2008

The Recommended Minimum data (position, velocity, time)


$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230307,003.1,W,A,*6A
$GPRMC Recommended Minimum sentence
123519 Fix taken at 12:35:19 UTC
A Status A = active or V = Void.
4807.038,N Latitude 48° 07.038' N
01131.000,E Longitude 11° 31.000' E
022.4 Speed over the ground in knots
084.4 Track angle in degrees
230307 Date 23.03.2007
003.1,W Magnetic variation
A Mode indicator
A = autonomous D = differential, E=Estimated,
N = not valid, S = Simulator
*6A Checksum data = * + 2 hex digits
MobileComputing Workshop page 206 G. Juen, 02.07.2008
9.2 Exercise
Complete the WhatClient.
Remark:
NMEA values (from the GPS-mouse) have to be converted to WHAT values.

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)

MobileComputing Workshop page 207 G. Juen, 02.07.2008

// constructor called with already opened BT-connection


public GPSInpStrReader(StreamConnection con) throws
IOException

// reads the next $GPRMC sentence from the GPS-mouse


// returns it and stores it also internally
String readGPRMCSentence()

// get the LAT data of the last sentence in WHAT-Format


String getLatWHAT()

// get the LON data of the last sentence in WHAT-Format


String getLonWHAT()

// get the LAT data of the last sentence in NMEA-Format


String getLatNMEA()

// get the LON data of the last sentence in NMEA-Format


String getLonNMEA()

MobileComputing Workshop page 208 G. Juen, 02.07.2008

You might also like