Tải bản đầy đủ (.pdf) (31 trang)

BLUETOOTH APPLICATION PROGRAMMING WITH THE JAVA APIS ESSENTIALS EDITION PHẦN 4 pdf

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (362.66 KB, 31 trang )

// Remove the TextFields from the Form
connForm.delete(0);
connForm.delete(0);
return temp.toString();
}
/**
* Establishes a connection to the server.
*
* @param connString the connection string to connect
* to the server
* @return true if the connection was established;
* false if the connection failed
*/
private boolean connectToServer(String connString) {
try {
// Establish a connection to the server
conn = (StreamConnection)
Connector.open(connString);
// Retrieve the input and output streams to
//communicate with
input = conn.openInputStream();
output = conn.openOutputStream();
return true;
} catch (IOException e) {
connForm.append("Connect failed (IOException: ");
connForm.append(e.getMessage());
connForm.append(")\n");
return false;
}
}
/**


* Retrieves the Bluetooth address and channel ID
* from the Form. This method then establishes a
* connection to the server.
*/
Programming with the API 75
public void run() {
String connString = getConnectionString();
connForm.append("Connecting to Server\n");
if (connectToServer(connString)) {
connForm.append("Done");
// Remove the Connect Command and add the Send
// Command to this Form
connForm.removeCommand(connectCommand);
Command sendCommand = new Command("Send",
Command.SCREEN, 1);
connForm.addCommand(sendCommand);
// Add a TextField to the Form to retrieve the
// text to send to the server from the user
connForm.append(new TextField("Text to send",
null, 20, TextField.ANY));
}
}
}
Most of the previous code handles user interaction. The only code that
uses JABWT is the
connectToServer() method. The connectTo-
Server()
method establishes the connection and retrieves the input
and output streams. The
getConnectionString() method makes the

connectToServer() method work because it specifies the btspp con-
nection scheme, which specifies that the SPP and RFCOMM should be
used to connect to the server.
The next step is to add code that sends a message to the server and
reads the reply. To minimize the amount of work done within the MIDP
CommandListener event handler, all of the communication with the
server is done in a separate thread. To perform the processing in a
separate thread, a new class must be created that implements the
Runnable interface. The Message class does this. The Message class
76 Chapter Four: RFCOMM
takes in its constructor the message, the input stream, and the output
stream. When it starts, the thread of the
Message class writes the mes-
sage to the
OutputStream. It then reads the reply from the server and
displays it on the
Form the user is currently viewing.
public class EchoClient extends BluetoothMIDlet {

/**
* Sends a message and reads the echo in reply.
* Displays the reply on the screen and adds the
* TextField to the end of the Form.
*/
class Message implements Runnable {
// The message to send to the server.
private String theMessage;
// The InputStream to read the reply from.
private InputStream input;
// The OutputStream to send the message to.

private OutputStream output;
/**
* Creates a new Message to send to the server.
*
* @param msg the message to send
* @param in the InputStream to read the reply from
* @param o ut the strea m to w ri te the messag e to
*/
public Message(String msg, InputStream in,
OutputStream out) {
theMessage = msg;
input = in;
output = out;
}
Programming with the API 77
/**
* Sends the m essage to the server and reads the echo
* in reply. The met hod a dds t he ech o to t he For m and
* then a dds a new TextField t o th e end of the Form.
*/
public void run() {
try {
// Send the message to the server.
byte[] data = theMessage.getBytes();
output.write(data);
output.flush();
// Read the reply and keep it in a StringBuffer
// until the full reply is received.
int fullLength = data.length;
int length = input.read(data);

fullLength -= length;
StringBuffer buf = new StringBuffer(new
String(data, 0, length));
while (fullLength > 0) {
length = input.read(data);
fullLength -= length;
buf = buf.append(new String(data, 0, length));
}
// Display the reply on the Form and remove the
// final new line sent from the server
connForm.append("\n");
String displayString = buf.toString();
displayString = displayString.substring(0,
displayString.length() - 1);
connForm.append(displayString);
} catch (IOException e) {
connForm.append("\nFailed to send message: " +
e.getMessage());
}
78 Chapter Four: RFCOMM
connForm.append(new TextField("Text to send",
null, 20, TextField.ANY));
}
}
}
The final step is to use the Message class within the EchoClient MIDlet.
This requires modifying the
commandAction() method. The if state-
ment is changed to a
switch statement to determine whether the ‘‘Send,’’

‘‘Exit,’’ or ‘‘Connect’’
Command was selected. If the ‘‘Send’’ Command was
selected, the
commandAction() method determines whether the last
element in the
Form is a TextField. This check is done to prevent two
messages from being sent at the same time. The
TextField is not the last
Item if a message is currently being sent. If no message is being sent, then
the
TextField is the last Item. After this check is made, the command-
Action()
method creates a new Message object and starts the Message
object in a thread. This thread sends the message and receives the reply.
public class EchoClient extends BluetoothMIDlet {

public void commandAction(Command c, Displayabl e d) {
switch (c.getCommandType()) {
case Command.OK:
// The Connect Command was selected so start a
// thread to establish the connection to the server
new Thread(this).start();
break;
case Command.SCREEN:
// The Send Command was selected so send the
// message to the server
Programming with the API 79
int index = connForm.size() - 1;
// If the last Item is a TextField, then no message
// is currently being sent so send a Message.

Item item = connForm.get(index);
if (item instanceof TextField) {
TextField field = (TextField)item;
connForm.delete(index);
// Start a thread to send the message to the
// server and process the reply
new Thread(new Message(field.getString() +
"\n", input, output)).start();
}
break;
case Command.EXIT:
// The Exit Command was selected so destroy the
// MIDlet
try {
input.close();
output.close();
conn.close();
} catch (Exception e) {
}
notifyDestroyed();
break;
}
}
}
This completes the echo client/server application. Figure 4.9 shows
the
EchoClient and EchoServer running. Now the EchoClient is
able to send messages to the server while the
EchoServer is able to
80 Chapter Four: RFCOMM

echo back any message sent from the client. Most of the code for both
applications is not specific to JABWT but is MIDP code that provides for
interaction between the application and the user. This is likely the case
for most applications that use JABWT.
4.4 Summary
RFCOMM will likely be the most used Bluetooth protocol within JABWT
because RFCOMM provides serial two-way communication and reuses
(A) (B)
Figure 4.9 EchoClient (A) and EchoServer (B) communicating over RFCOMM
(emulation only).
Summary 81
familiar APIs from Java ME. The SPP is the Bluetooth profile realization
of RFCOMM. Many Bluetooth profiles are built on the SPP to take
advantage of existing serial port applications and protocols developed
for wired communication.
Important concepts introduced in this chapter are links and con-
nections. Two Bluetooth devices may have only a single Bluetooth link
between them, but this link allows multiple Bluetooth connections.
Although links are device by device, connections are at the JABWT
application layer. In addition to the terms link and connection, the
concepts of master and slave devices are introduced. The master device
drives the frequency-hopping sequence used to communicate betw een
two devices. Different Bluetooth profiles require one device to be the
master and another device the slave. Being the master allows a device
to accept and establish connections to other devices. By establishing
these additional connections, the master device is able to set up a
piconet.
The basic concepts of Blu etooth security are covered. Bluetooth
provides four types of security on a link basis. Pairing is the initial
process of identifying two devices to each other by exchanging a PI N

outside of Bluetooth communication. Pairing sets up a shared secret
between the device s so that pairing does not need to be completed
every time. After pairing is completed, authentication can occur.
Authentication is the process of verifying the identity of another device.
After authentication has occurred, encryption and/or authorization can
occur. Encryption is the proces s of encoding and decoding a message so
that an eavesdropper cannot listen in on the convers ation. Finally,
authorization is the process of determining whether another device has
permission to use a specific service.
Because RFCOMM provides reliable two-way communic ation, the
StreamConnection and StreamConnectionNotifier interfaces from
the GCF are reused. All RFCOMM connections start with a call to
Connector.open() with a val id RFCOMM connection string. The con-
nection string can include parameters for master/slave and Bluetooth
security. If a client connection stri ng is used in
Connector.open(),
a
StreamConnection object is returned when the connection is
established to the server. An RFCOMM server is created by calling
82 Chapter Four: RFCOMM
Connector.open() with a server connection string, and a
StreamConnectionNotifier object is returned. With the Stream-
ConnectionNotifier
object, the server can accept connections from
RFCOMM clients by calling
acceptAndOpen(). After the connection
has been established, input and output streams can be retrieved to read
and write data.
Summary 83
This page intentionally left blank

5
CHAPTER OBEX
This chapter covers the following topics:
• What is OBEX?
• When should OBEX be used?
• How does the OBEX API fit into the JABWT specification?
• How does OBEX work?
• Establishing an OBEX connection
• Setting and retrieving OBEX headers
• Initiating and responding to OBEX requests
• Using OBEX authentication
5.1 Overview
The IrOBEX (Infrared Object Exchange protocol) [33] is defined by IrDA
as an alternative to the HyperText Transport Protocol (HTTP) for
embedded devices. IrOBEX targets memory-constrained embedded
devices, which have slower processing speeds. Whereas HTTP makes a
single request and a single reply, IrOBEX allows devices to break up
requests and replies into smaller chunks. By breaking up the requests
into smaller chunks of data, IrOBEX allows the data to be processed as it
is received and allows a request or reply to be aborted.
IrOBEX, like HTTP, is transport neutral. In other words, IrOBEX
works over almost any other transport layer protoc ol. Whereas the initial
implementations of IrOBEX used infrared as the transport, there are
presently implementations of IrOBEX that are running over TCP, serial,
and RFCOMM connections. Because IrOBEX may run over different
transports and can break up requests and replies, IrOBEX may be opti-
mized to a specific transport protocol. What does this mean? Every
IrOBEX packet is segmented to fit within each transport layer packet.
This allows for efficient use of bandwidth.
IrOBEX has become even more popular since the Bluetooth SIG

licensed the protocol from IrDA. When the protocol is used with Blue-
tooth wireless technology, the Ir is dropped, and the protocol is referred
to as OBEX. (From this point forward, OBEX and IrOBEX are used inter-
changeably.) The Bluetooth SIG defined OBEX as one of the protocols in
the Bluetooth protocol stack. OBEX sits on the RFCOMM protocol. The
Bluetooth SIG went a step farther. The SIG realized that OBEX is an
excellent building block protocol from which to create Bluetooth pro-
files. To facilitate building new profiles, the Bluetooth SIG defined the
GOEP [11] to be the profile that defines how OBEX works within the
Bluetooth environment.
The OBEX API defined in JABWT is an optional API. This means
that the OBEX API may be implemented within a device tha t supports
the Bluetooth APIs, but just because a device supports the Bluetooth APIs
does not imply that it supports the OBEX APIs. Currently, most mobile
devices that support the Bluetooth APIs do not support the OBEX APIs.
In theory, the reverse is also possible—there could be support for the
OBEX API in devices that do not support the Bluetooth APIs. The reason
for this is that the OBEX API is independent of the Bluetooth APIs.
So why would a developer use OBEX on a device that has RFCOMM,
L2CAP, or TCP/IP? OBEX is a structured protocol that allows separation
of data and the attributes of data. Using OBEX allows clear definition of
one request from another. Using protocols such as RFCOMM or TCP/IP
requires the applications to know how data is sent and when to send the
reply. OBEX hides this within the protocol. OBEX is like the Extensible
Markup Language (XML). It provides structure to the data sent whereas
RFCOMM and TCP/IP simply send bytes.
5.1.1 Use Cases
OBEX can be used for a variety of purposes. The protocol is being used
in PDAs as a way to exchange electronic business cards. OBEX also has
been used to synchronize embedded devices with desktop computers.

86 Chapter Five: OBEX
The OBEX API defined for the Java programming language is intended
to allow OBEX to be used for an even wider range of applications.
Synchronization
A common problem for MIDP devices, such as cell phones, is how to
keep the information on the device synchronized with a desktop com-
puter. With Bluetooth wireless technology, the device doesn’t need to be
connected to the PC and manually synchronized. Instead, the handset
automatically synchronizes with the desktop PC when the device gets
close to the PC. The Bluetooth SIG defined the Synchronization Profile
to support such a use case. The Synchronization Profile utilizes OBEX to
exchange data between the device and the PC.
Printing
Java ME has begun to be used b y businesses as a way to keep in touch with
employees. Being able to s end and retrieve e-mail is n ow possible. Being
able to update and check an employee’s calendar and ‘ ‘to do’ ’ list also is
possible. There is one drawback to using a Java ME device for these tasks.
Most devices have a very limited screen size; therefore, users find it quite
helpful for those dev ices to send e-mail or the calendar to a printer. Up to
this point, the Java ME space contained devi ces that could talk back onl y
with a central server. With the introduction of JABWT to Java ME, any two
devices can talk. Sending documents to print is a natural use of OBEX. The
Bluetooth SIG has released the Basic Printing Profile, which uses OBEX [31].
5.1.2 Protocol Description
OBEX is built on six basic operations: CONNECT, SETPATH, GET, PUT,
ABORT, and DISCONNECT. The client initiates every operation with a
request and waits for the server to send its response. Every OBEX session
begins with a CONNECT request from the client to the server. (Although
the IrOBEX specification defined a connectionless OBEX, it is not
described here. The OBEX API defined by JABWT does not address this

type of OBEX.) Every session ends with a DISCONNECT request.
Between the CONNECT and DISCONNECT requests, the client may
Overview 87
send any number of SETPATH, GET, ABORT, or PUT requests. The
ABORT request is a special type of request. It ends a PUT or GET opera-
tion before the operation ends. (A PUT/GET operation is made of multi-
ple PUT or GET requests and replies.)
Within each requ est and reply, OBEX heade rs may be sent. The
OBEX specification defines a list of common headers. The common
headers include but are not limited to
• NAME, which specifies the name of the object
• LENGTH, which specifies the length of the object
• TYPE, which specifies the Multipurpose Internet Mail Extensions
(MIME) type of the object
• COUNT, which is used by a CONNECT request to specify the num-
ber of objects to send or receive
• DESCRIPTION, a short description of the object
• HTTP, which specifies an HTTP header
• BODY, which specifies part of the object
• END OF BODY, which specifies the last part of the object
The OBEX specification defines how these common headers are encoded.
For example, the NAME header must be a Unicode string. The BODY and
END OF BODY headers are used to send or retrieve objects from a server
via PUT or GET requests. The END OF BODY signals to the receiver that
this is the last chunk of the object. In addition to the common headers,
the specification also allows 64 user-defined headers. The specification
breaks these headers into four groups of 16 headers. Each group represents
a different type of data. There are groups for Unicode strings, 4-byte
unsigned integers, single bytes, and byte sequences.
The OBEX specification defines two ad ditional special operations: the

PUT-DELETE and CREATE-EMPTY operations. The PUT-DELETE operation
is a PUT operation with a NAME header and no BODY header. This opera-
tion is used to tell the server to delete the object with the specified name.
The CREATE-EMPTY operation also is a PUT operation, but the CREATE-
EMPTY operation contains a NAME and an END OF BODY header with no
data. The CREATE-EMPTY operation signals to the server to create the
object with the specified name with nothing in the object.
88 Chapter Five: OBEX
5.1.3 Example Session
Every OBEX session begins with the client issuing a CONNECT request. If
the client wants, the client can include additional headers to send to
the server. When the server receives the request, the server processes the
headers and decides whether it will accept the connection request. If the
server accepts the request, the server responds with an OK, SUCCESS
response code. If the server rejects the request, the server responds with
one of the HTTP response codes that specify why the request was not
accepted. In the example in Figure 5.1, the client issues the CONNECT
request and sends the COUNT header to the server to specify the number
of objects to be transferred. The server processes the request and replies
with the OK, SUCCESS response code.
After the connection is established, the client may want to change
to a different location on the server. The client is able to change folders
by using the SETPATH operation. In Figure 5.2, the client sends the
SETPATH operation and specifies the name of the directory to change
to by using the NAME header. When the server receives the request, it
may decide to allow or not allow the change. The server can deny the
request for a variety of reasons, including using the NOT FOUND
response if the folder does not exist on the server.
Even though the server was not able to fulfill the SETPATH opera-
tion, the session is still active and the client may continue to make

requests to the server. For example, the client may want to send a file
CONNECT (COUNT)
OK, SUCCESS
Client
Server
Figure 5.1 OBEX CONNECT operation.
Overview 89
to the server. To do this, the client issues a PUT request. If the file is large,
the client may need to break the file up into smaller chunks to send to
the server. If this is the case, the client sends the initial PUT request with
a NAME header, to specify the name of the file, and the BODY header
containing the first chunk of the file. When the server receives this
request, the server stores the first chunk of the file and replies with a
CONTINUE response. When the client receives the CONTINUE
response, the client sends the next chunk of the file via another PUT
request with the BODY header. After storing this part of the file, the
server sends another CONTINUE response. This back and forth con-
tinues until the last chunk of data is sent to the server (see Figure 5.3).
For the last chunk of the file, the client again send s a PUT request, but
the client includes the data in an END OF BODY header rather than a
BODY header. This header signals to the server that this is the last piece
of the file. After the server receives notice from the client that no more
data will be sent, the server responds with an OK, SUCCESS response
code. When the client receives this response code, the client knows that
the object was successfully sent to the server.
To end the OBEX session, the client must issue a DISCONNECT
request. Usually, a DISCONNECT request does not contain any addi-
tional headers, but OBEX does not restrict headers from being included
in the DISCONNECT request. When it receives a DISCONNECT request,
the server frees any resources that it may have allocated and sends an

OK, SUCCESS response to the client (see Figure 5.4). When the client
receives this response, the OBEX session has ended.
SETPATH (NAME)
NOT FOUND
Client
Server
Figure 5.2 OBEX SETPATH operation.
90 Chapter Five: OBEX
PUT (NAME, BODY)
CONTINUE
CONTINUE
PUT (BODY)
PUT (END-OF-BODY)
OK, SUCCESS
Client
Server
Figure 5.3 OBEX PUT operation.
DISCONNECT
OK, SUCCESS
Client
Server
Figure 5.4 OBEX DISCONNECT operation.
Overview 91
It is important to remember that when the OBEX session has
ended, the physical connection between the two devices may not have
been closed. The transport protocol also must be disconnected. How or
when this is done is not specified by the OBEX specification.
5.2 API Capabilities
The OBEX API is quite different from most existing OBEX implementa-
tions, which provide only a high-level interface to the protocol. For

example, Palm developers can use an API for OBEX that allows a user
to send a business card or receive an appointment but not to control how
the data was sent. Control of the specifics of the transaction is not
available. The Java OBEX API provides a low-level interface. The low-
level interface gives developers more control over each request and
reply, adding a new layer of complexity.
Although the OBEX API provides greater access to the protocol, the
OBEX API hides some of the details of the protocol from developers. The
OBEX API handles all the translation of OBEX headers to their corre-
sponding byte representation. The API also hides some of the details of
the CONNECT request. For example, the OBEX API implementation
handles the negotiation of OBEX packet sizes. Because the packet size
is not available to an application developer, the OBEX API implementa-
tion handles converting requests into multiple packets for PUT and GET
requests. This allows an application to simply send the BODY data while
relying on implementation of the API to convert the BODY data into
different packets.
To make it easier to learn, the OBEX API was based on other Java
APIs with which many developers are familiar. The client API is designed
from the combination of the
javax.microedition.io.Co ntent-
Connection
interface and the javax.microedition.io.Datagram-
Connection
interface from the GCF (see Figure 5.5). GET, PUT, and
CREATE-EMPTY operations use the
javax.obex.Operation interfa ce,
which extends the
ContentConnection interface. The CONNECT,
SETPATH, PUT-DELETE, and DISCONNECT operations work as the

DatagramConnection interface does. For sending a message with the
DatagramConnection,ajavax.microedition.io.Datagram object
must be created and used as the argument to the
send( ) method of the
92 Chapter Five: OBEX
DatagramConnection interface. Similarly, for sending OBEX headers, a
javax.obex.HeaderSet object must be created and passed to the
connect(), setPath(), delete(), and disconnect() methods of
the
javax.obex.ClientSession interface.
For an OBEX server, the OBEX API combines concepts from the
javax.microedition.io.St reamConnectionNotifier interface
and the Java servlet API (see Figure 5.6). The server API, like the client API,
javax.microedition.io
ContentConnection
javax.microedition.io
DatagramConnection
OBEX
client API
Figure 5.5 OBEX client API resulted from the combination of two connection types.
javax.servlet.http
HttpServlet
javax.microedition.io
OBEX
server API
StreamConnectionNotifier
Figure 5.6 OBEX server API was created by combining two well known APIs.
API Capabilities 93
is based on the GCF. After a SessionNotifier object is created by calling
Connector.open(), acceptAndOpen() is called with a javax.obex.

ServerRequestHandler
object. The ServerRequestHandler cla ss is
similar to t he
java.servlet.http.HttpServlet class. The Server-
RequestHandler
class defines methods for each type of OBEX request
that a server may receive, such as
onConnect(), onDisconnect(),
onPut(), onGet(), onDelete(),andonSetPath(). Only requests to
which a server wants to respond must be implemented.
The OBEX API also provides a mechanism for OBEX authentica-
tion. OBEX authentication works via a challenge and response
scheme using two OBEX headers. The AUTHENTICATION_CHALLENGE
header is sent when an application on one device wants to authenticate
an application on another device. When a device receives an
AUTHENTICATION_CHALLENGE header, it combines the shared
secret or password with the 16-byte challenge received in the
AUTHENTICATION_CHALLENGE header. The Message Digest 5 (MD5)
hash algorithm is applied to the combined password and challenge. The
resulting value is returned in an AUTHENTICATION_RESPONSE header.
When the challenger receives the AUTHENTICATION_RESPONSE header,
the challenger combines the 16-byte challenge sent in the original
AUTHENTICATION_CHALLENGE header and the shared secret and
applies the MD5 hash algorithm. The resulting value is compared with
the value received in the AUTHENTICATION_RESPONSE header. If the
two values are equal, the other device is authenticated.
OBEX authentication is different from Bluetooth authentication.
Bluetooth authentication authenticates two Bluetooth devices to each
other. OBEX authentication authenticates two users or applications to
each other. Although Bluetooth authentication is handled at the Blue-

tooth stack and radio layer, OBEX authentication is handled at the
application layer. OBEX authenticatio n and Bluetooth authentication
can be used at the same time.
The OBEX API uses an API similar to the Java SE authentication API
for OBEX authentication. The OBEX API defines the
javax.obex.
Authenticator
interface. When an AUTHENTICATION_CHALLENGE
header is received, the
onAuthenticationChallenge() method is
called. This method returns a
javax.obex.PasswordAuthentication
object with the user name and password pair that will be used in creating
94 Chapter Five: OBEX
the AUTHENTICATION_RESPONSE. When an AUTHENTICATION_
RESPONSE header is received, the
onAuthenticationResponse ( )
method is called. The shared secret or password is returned from the
onAuthenticationResponse () method. The OBEX API implementa-
tion handles all the hashing of challenges/passwords and validation of
the authentication request.
The OBEX API is based on the IrOBEX 1.2 version of the specification.
There have been updates to the IrOBEX specification that are not back-
wards compatible. In particular, values of some headers have been
changed. These changes have not been made to the OBEX API defined in
JSR-82.
5.3 Programming with the API
The OBEX API is built on the GCF defined in CLDC. The OBEX API adds
three new interfaces that extend the
javax.microedition.io.

Connection
interface. The javax.obex.ClientSession interface is
returned from
Connector.open() when a client connection string is
provided. The
javax.obex.SessionNotifier interface is returned
from the
Connector.open() method for server connections. Finally,
the
javax.obex.Operation interface is used to process PUT and GET
requests. The
javax.obex.Operation interface hides the back and
forth nature of the PUT and GET requests (Figure 5.7).
Connection
HttpConnection
StreamConnection
ContentConnection
Operation
DatagramConnectionStreamConnectionNotifier
SessionNotifierClientSession
Figure 5.7 GCF with OBEX API.
Programming with the API 95
In addition to these new interfaces, the OBEX API defines the
javax.obex.Authenticator and javax.obex.HeaderSet interfaces.
The
Authenticator interface is implemented by applications that want
to handle authentication challenges and responses (OBEX authentication
is fully explained in Section 5.3.5). The
HeaderSet interface encapsulates
a set of OBEX headers. All OBEX headers except for the BODY, END-OF-

BODY, CONNECTION-ID, AUTHENTICATION_CHALLENGE, and
AUTHENTICATION_RESPONSE headers can be set in a
HeaderSet
object. OBEX headers not set within the HeaderSet interface can be set
and retrieved by other methods.
The OBEX API introduces three new classes. The
javax.obex.
PasswordAuthentication
class keeps user name and password pairs
for OBEX authentication. The
javax.obex.ResponseCodes class
defines all the valid response codes that a server may send to a client.
Finally, servers extend the
javax.obex.ServerRequest Handler class.
This class defines the methods called when the server receives different
OBEX requests.
5.3.1 Establishing a Connection
For a client or a server to use the OBEX API, the client or server must first
provide a connection string to
Connector.open(). The OBEX API uses
the same connection URL definition as the CLDC specification:
{scheme}:[{target} ][{params}]
The OBEX connection string is slightly different from the connection
strings defined in MIDP and MIDP 2.0. Because OBEX can be used with a
number of different transports, the connection string needs to specify
the transport protocol in addition to specifying OBEX. The transport
protocol is specified within the {scheme}. With the exception of OBEX
over RFCOMM, the connection string defined by the OBEX API is
{transport}obex://{target}{params}
If TCP/IP is the transport protocol used for an OBEX connection, the

{scheme} is
tcpobex. When opening a tcpobex client connection to a
server, the {target} is the IP address and port number of the server. When
opening a server connection, the {target} is just the port number of the
96 Chapter Five: OBEX
server. In the TCP/IP case, there are no {params} defined for a client or
server connection.
If RFCOMM is the transport protocol, the connection string does
not follow t his rule. This is because the GOEP is the realization of OBEX
in the Bluetooth specification; therefore the {scheme} for OBEX over
RFCOMM connections is
btgoep. The {target} is the Bluetooth address
and RFCO MM channel number to establish a client connection. For
server connections, the {target} is the UUID of the service. All the valid
{params} for RFCOMM are valid for OBEX over RFCOMM (see Table 4.1
for the list of valid {params} for RFCOMM).
Some example client connection strings are
1. btgoep://00802d5b12af:1;authenticate=yes
2. tcpobex://163.10.70.75:1505
3. irdaobex://discover;ias=MyAppOBEX,OBEX,OBEX:IrXfer;
See the JAWBT specification [22] for an explanation of the connection
string for OBEX over IRDA.
Some server connection strings are
1. btgoep://localhost:1233212ADBAA9324BAFE23331231222C
2. tcpobex://:1801
3. irdaobex://localhost.0200
After
Connector.open() is called with a client connection string, a
ClientSession object is returned. A transport connection is estab-
lished by a call to

Connector.open(), but an OBEX layer connection
has not yet been established. To establish an OBEX layer connection,
ClientSession.connect() must be called. Before the transport layer
connection is closed,
ClientSession.disconnect ( ) must be called
to close the OBEX layer connection.
On the server side, the
SessionNotifier object returned by
Connector.open() is used to accept connections from clients by call-
ing
acceptAndOpen() on the SessionNotifier object. The accept-
AndOpen()
method takes a ServerRequestHandler argument and an
optional
Authenticator argument. A developer creates a new class that
extends the
ServerRequestHandler class and implements the meth-
ods for the type of requests the developer would like the server to handle.
Programming with the API 97
For example, onConnect() should be implemented for CONNECT
requests and
onGet() for GET requests. The call to acceptAndOpen()
does not return until a client connects. The acceptAndOpen() method
returns a
Connection object representing the transport layer connec-
tion to the client.
5.3.2 Manipulating OBEX Headers
OBEX communicates all of its information within headers. JABWT allows
headers to be written and read via different methods based on the header. Of
allthevalidheaders,theBODY,END-OF-BODY,AUTHENTICATION_

CHALLENGE, AUTHENTICATION_RESPONSE, and CONNECTION-ID
headers have specific m e thods that all o w developers to access them . All
other h eaders can be accessed through the
HeaderSet interface.
Developers are not allowed to define their own implementation for
the
HeaderSet interface. Instead, developers use implementations of the
interface found within the API implementation. OBEX clients use the
createHeaderSet() method defined in the ClientSession interface.
On the other hand, OBEX servers are passed
HeaderSet objects when
they override an
onXXX() method in the ServerRequestHandler
class (see Section 5.3.4 for more information on how to implement an
OBEX server).
Once a
HeaderSet object is created or received, it is very easy to
access different headers. Within the
HeaderSet interface are constants
defined for most of the headers in the OBEX specification. In addition to
these constants are 64 user-defined headers that can be used. To set a
header in the object, call the
setHeader() method with the header
identifier and the header’s value. The header’s value must be of the type
specified in the OBEX API. Table 5.1 is the full list of headers that can be
set with
setHeader(), their meaning according to the OBEX specifica-
tion, and the type of object to use. For example, the
COUNT header must
be set with a

java.lang.Long object, and the NAME header must be set
with a
java.lang.String.IfsetHeader() is called with a different
type,
IllegalArgumentException is thrown. Likewise, to retrieve a
header, use the
getHeader() method with the header identifier. The
getHeader() method also returns an object of the type specified in
Table 5.1.
98 Chapter Five: OBEX
Although some headers, such as NAME and COUNT, have a specific
meaning, 64 headers are defined in OBEX that have no general meaning
according to the OBEX specification. These are the user-defined headers.
These headers should be used by applications to exchange data if the
data does not fall into one of the defined OBEX headers.
The
HeaderSet interface also provides a getHeaderList()
method. This method returns an array of integers that represent the
header identifiers set within the
HeaderSet object. The getHeader-
List()
method never returns null. If no headers are available via the
getHeaders() method, getHeaderlist() returns an empty array.
Table 5.1 OBEX Header Constants in the HeaderSet Interface, Their Meaning, and Their Type
Value Meaning Type
COUNT Used by CONNECT to specify the number of
objects to be communicated during the session
java.lang.Long
NAME
Name of the object java.lang.String

TYPE
MIME type of the object java.lang.String
LENGTH
Size of the object java.lang.Long
TIME_ISO_8601
Time stamp of the object (recommended
header to use to time stamp an object)
java.util.Calendar
TIME_4_BYTE
Time stamp of the object java.util.Calendar
DESCRIPTION
Brief description of the object java.lang.St ring
TARGET
Target OBEX service byte[]
HTTP
Specifies an HTTP header byte[]
WHO
OBEX service processing the request byte[]
OBJECT_CLASS
OBEX object class of the object byte[]
APPLICATION_PARAMETER
Application-specific parameter byte[]
48 to 63 (0x30 to 0x3F) User-defined headers to send a string java.lang.String
112 to 127 (0x70 to 0x7F) User-defined headers to send a byte array byte[]
176 to 191 (0xB0 to 0xBF) User-defined headers to send a byte java.lang.Byte
240 to 255 (0xF0 to 0xFF) User-defined headers to send an unsigned
integer in the range of 0 to 2
32
À 1
java.lang.Long

Programming with the API 99

×