The Android platform includes support for the Bluetooth network
stack,
which allows a device to wirelessly exchange data with other Bluetooth
devices.
The application framework provides access to the Bluetooth functionality
through
the Android Bluetooth APIs. These APIs let applications wirelessly
connect to other Bluetooth devices, enabling point-to-point and
multipoint
wireless features.
Using the Bluetooth APIs, an Android application can perform the
following:
- Scan for other Bluetooth devices
- Query the local Bluetooth adapter for paired Bluetooth devices
- Establish RFCOMM channels
- Connect to other devices through service discovery
- Transfer data to and from other devices
- Manage multiple connections
The Basics
This document describes how to us the Android Bluetooth APIs to
accomplish
the four major tasks necessary to communicate using Bluetooth: setting
up
Bluetooth, finding devices that are either paired or available in the
local
area, connecting devices, and transferring data between devices.
All of the Bluetooth APIs are available in the android.bluetooth
package. Here's a summary of the classes you will need to create
Bluetooth
connections:
BluetoothAdapter
- Represents the local Bluetooth adapter (Bluetooth radio). The
BluetoothAdapter
is the entry-point for all Bluetooth
interaction. Using this,
you can discover other Bluetooth devices, query a list of bonded
(paired)
devices, instantiate a BluetoothDevice
using a known
MAC address, and create a BluetoothServerSocket
to
listen for communications
from other devices.
BluetoothDevice
- Represents a remote Bluetooth device. Use this to request a
connection
with a remote device through a
BluetoothSocket
or
query information about the
device such as its name, address, class, and bonding state.
BluetoothSocket
- Represents the interface for a Bluetooth socket (similar to a TCP
Socket
).
This is the connection point that allows
an application to exchange data with another Bluetooth device via
InputStream
and OutputStream.
BluetoothServerSocket
- Represents an open server socket that listens for incoming requests
(similar to a TCP
ServerSocket
).
In order to connect two
Android devices, one device must open a server socket with this class.
When a
remote Bluetooth device makes a connection request to the this device,
the
BluetoothServerSocket
will return a connected BluetoothSocket
when the
connection is accepted.
BluetoothClass
- Describes the general characteristics and capabilities of a
Bluetooth
device. This is a read-only set of properties that define the device's
major and
minor device classes and its services. However, this does not reliably
describe
all Bluetooth profiles and services supported by the device, but is
useful as a
hint to the device type.
Bluetooth Permissions
In order to use Bluetooth features in your application, you need to
declare
at least one of two Bluetooth permissions: BLUETOOTH
and BLUETOOTH_ADMIN
.
You must request the BLUETOOTH
permission
in order to perform any Bluetooth communication, such as requesting a
connection, accepting a connection, and transferring data.
You must request the BLUETOOTH_ADMIN
permission in order to initiate device discovery or manipulate Bluetooth
settings. Most applications need this permission solely for the
ability to discover local Bluetooth devices. The other abilities granted
by this
permission should not be used, unless the application is a "power
manager" that
will modify Bluetooth settings upon user request. Note:
If you
use BLUETOOTH_ADMIN
permission, then must
also have the BLUETOOTH
permission.
Declare the Bluetooth permission(s) in your application manifest
file. For
example:
<manifest
...
>
<uses-permission
android:name
=
"android.permission.BLUETOOTH"
/>
...
</manifest>
See the <uses-permission>
reference for more information about declaring application permissions.
Setting Up Bluetooth
Before your application can communicate over Bluetooth, you need to
verify
that Bluetooth is supported on the device, and if so, ensure that it is
enabled.
If Bluetooth is not supported, then you should gracefully disable any
Bluetooth features. If Bluetooth is supported, but disabled, then you
can request that the
user enable Bluetooth without leaving your application. This setup is
accomplished in two steps, using the BluetoothAdapter
.
- Get the
BluetoothAdapter
The BluetoothAdapter
is required for any and all Bluetooth
activity. To get the BluetoothAdapter
,
call the static getDefaultAdapter()
method. This returns a
BluetoothAdapter
that represents the device's own
Bluetooth adapter (the Bluetooth radio). There's one Bluetooth adapter
for the
entire system, and your application can interact with it using this
object. If
getDefaultAdapter()
returns null,
then the device does not support Bluetooth and your story ends here. For
example:
BluetoothAdapter
mBluetoothAdapter
=
BluetoothAdapter
.
getDefaultAdapter
();
if
(
mBluetoothAdapter
==
null
)
{
// Device does not support Bluetooth
}
- Enable Bluetooth
Next, you need to ensure that Bluetooth is enabled. Call isEnabled()
to check whether Bluetooth is
currently enable. If this method returns false, then Bluetooth is
disabled. To
request that Bluetooth be enabled, call startActivityForResult()
with the ACTION_REQUEST_ENABLE
action Intent.
This will issue a request to enable Bluetooth through the system
settings (without
stopping your application). For example:
if
(!
mBluetoothAdapter
.
isEnabled
())
{
Intent
enableBtIntent
=
new
Intent
(
BluetoothAdapter
.
ACTION_REQUEST_ENABLE
);
startActivityForResult
(
enableBtIntent
,
REQUEST_ENABLE_BT
);
}
A dialog will appear requesting user permission to enable Bluetooth,
as shown
in Figure 1. If the user responds "Yes," the system will begin to enable
Bluetooth
and focus will return to your application once the process completes (or
fails).
If enabling Bluetooth succeeds, your Activity will receive the RESULT_OK
result code in the onActivityResult()
callback. If Bluetooth was not enabled
due to an error (or the user responded "No") then the result code will
be RESULT_CANCELED
.
Optionally, your application can also listen for the
ACTION_STATE_CHANGED
broadcast Intent, which
the system will broadcast whenever the Bluetooth state has changed. This
broadcast contains
the extra fields EXTRA_STATE
and EXTRA_PREVIOUS_STATE
,
containing the new and old
Bluetooth states, respectively. Possible values for these extra fields
are
STATE_TURNING_ON
,
STATE_ON
,
STATE_TURNING_OFF
,
and STATE_OFF
.
Listening for this
broadcast can be useful to detect changes made to the Bluetooth state
while your
app is running.
Tip:
Enabling discoverability will
automatically
enable Bluetooth. If you plan to consistently enable device
discoverability before
performing Bluetooth activity, you can skip
step 2 above. Read about enabling
discoverability
,
below.
Finding Devices
Using the BluetoothAdapter
,
you can find remote Bluetooth
devices either through device discovery or by querying the list of
paired (bonded)
devices.
Device discovery is a scanning procedure that searches the local area
for
Bluetooth enabled devices and then requesting some information about
each one
(this is sometimes referred to as "discovering," "inquiring" or
"scanning").
However, a Bluetooth device within the local area will respond to a
discovery
request only if it is currently enabled to be discoverable. If a device
is
discoverable, it will respond to the discovery request by sharing some
information, such as the device name, class, and its unique MAC address.
Using
this information, the device performing discovery can then choose to
initiate a
connection to the discovered device.
Once a connection is made with a remote device for the first time, a
pairing
request is automatically presented to the user. When a device is
paired, the basic information about that device (such as the device
name, class,
and MAC address) is saved and can be read using the Bluetooth APIs.
Using the
known MAC address for a remote device, a connection can be initiated
with it at
any time without performing discovery (assuming the device is within
range).
Remember there is a difference between being paired and being
connected. To
be paired means that two devices are aware of each other's existence,
have a
shared link-key that can be used for authentication, and are capable of
establishing an encrypted connection with each other. To be connected
means that
the devices currently share an RFCOMM channel and are able to transmit
data with
each other. The current Android Bluetooth API's require devices to be
paired
before an RFCOMM connection can be established. (Pairing is
automatically performed
when you initiate an encrypted connection with the Bluetooth APIs.)
The following sections describe how to find devices that have been
paired, or
discover new devices using device discovery.
Note:
Android-powered devices are not
discoverable by default. A user can make
the device discoverable for a limited time through the system settings,
or an
application can request that the user enable discoverability without
leaving the
application. How to enable
discoverability
is discussed below.
Querying paired devices
Before performing device discovery, its worth querying the set
of paired devices to see if the desired device is already known. To do
so,
call getBondedDevices()
.
This
will return a Set of BluetoothDevice
s
representing
paired devices. For example, you can query all paired devices and then
add then
show the name of each device to the user, using an ArrayAdapter:
Set
<
BluetoothDevice
>
pairedDevices
=
mBluetoothAdapter
.
getBondedDevices
();
// If there are paired devices
if
(
pairedDevices
.
size
()
>
0
)
{
// Loop through paired devices
for
(
BluetoothDevice
device
:
pairedDevices
)
{
// Add the name and address to an array adapter to show in a ListView
mArrayAdapter
.
add
(
device
.
getName
()
+
"\n"
+
device
.
getAddress
());
}
}
All that's needed from the BluetoothDevice
object
in order to initiate a connection is the MAC address. In this example,
it's saved
as a part of an ArrayAdapter that's shown to the user. The MAC address
can later
be extracted in order to initiate the connection. You can learn more
about creating
a connection in the section about Connecting
Devices
.
Discovering devices
To start discovering devices, simply call startDiscovery()
.
The
process is asynchronous and the method will immediately return with a
boolean
indicating whether discovery has successfully started. The discovery
process
usually involves an inquiry scan of about 12 seconds, followed by a page
scan of
each found device to retrieve its Bluetooth name.
Your application must register a BroadcastReceiver for the
ACTION_FOUND
Intent in
order to receive information about each
device discovered. For each device, the system will broadcast the
ACTION_FOUND
Intent. This
Intent carries the extra fields
EXTRA_DEVICE
and
EXTRA_CLASS
,
containing a
BluetoothDevice
and a BluetoothClass
,
respectively. For example, here's how you can
register to handle the broadcast when devices are discovered:
// Create a BroadcastReceiver for ACTION_FOUND
private
final
BroadcastReceiver
mReceiver
=
new
BroadcastReceiver
()
{
public
void
onReceive
(
Context
context
,
Intent
intent
)
{
String
action
=
intent
.
getAction
();
// When discovery finds a device
if
(
BluetoothDevice
.
ACTION_FOUND
.
equals
(
action
))
{
// Get the BluetoothDevice object from the Intent
BluetoothDevice
device
=
intent
.
getParcelableExtra
(
BluetoothDevice
.
EXTRA_DEVICE
);
// Add the name and address to an array adapter to show in a ListView
mArrayAdapter
.
add
(
device
.
getName
()
+
"\n"
+
device
.
getAddress
());
}
}
};
// Register the BroadcastReceiver
IntentFilter
filter
=
new
IntentFilter
(
BluetoothDevice
.
ACTION_FOUND
);
registerReceiver
(
mReceiver
,
filter
);
// Don't forget to unregister during onDestroy
All that's needed from the BluetoothDevice
object
in order to initiate a
connection is the MAC address. In this example, it's saved as a part of
an
ArrayAdapter that's shown to the user. The MAC address can later be
extracted in
order to initiate the connection. You can learn more about creating a
connection
in the section about Connecting
Devices
.
Caution:
Performing device discovery
is
a heavy procedure for the Bluetooth
adapter and will consume a lot of its resources. Once you have found a
device to
connect, be certain that you always stop discovery with
cancelDiscovery()
before
attempting a connection. Also, if you
already hold a connection with a device, then performing discovery can
significantly reduce the bandwidth available for the connection, so you
should
not perform discovery while connected.
Enabling discoverability
If you would like to make the local device discoverable to other
devices,
call startActivityForResult(Intent,
int)
with the
ACTION_REQUEST_DISCOVERABLE
action Intent.
This will issue a request to enable discoverable mode through the system
settings (without
stopping your application). By default, the device will become
discoverable for
120 seconds. You can define a different duration by adding the
EXTRA_DISCOVERABLE_DURATION
Intent extra
(maximum duration is 300 seconds). For example:
Intent
discoverableIntent
=
new
Intent
(
BluetoothAdapter
.
ACTION_REQUEST_DISCOVERABLE
);
discoverableIntent
.
putExtra
(
BluetoothAdapter
.
EXTRA_DISCOVERABLE_DURATION
,
300
);
startActivity
(
discoverableIntent
);
A dialog will be displayed, requesting user permission to make the
device
discoverable, as shown in Figure 2. If the user responds "Yes," then the
device
will become discoverable for the specified amount of time. Your Activity
will
then receive a call to the onActivityResult())
callback, with the result code equal to the duration that the device
is discoverable. If the user responded "No" or if an error occurred, the
result code will
be Activity.RESULT_CANCELLED.
Note:
If Bluetooth has not been enabled
on the device,
then enabling device discoverability will automatically enable
Bluetooth.
The device will silently remain in discoverable mode for the allotted
time.
If you would like to be notified when the discoverable mode has changed,
you can
register a BroadcastReceiver for the ACTION_SCAN_MODE_CHANGED
Intent. This will contain the extra fields EXTRA_SCAN_MODE
and
EXTRA_PREVIOUS_SCAN_MODE
,
which tell you the
new and old scan mode, respectively. Possible values for each are
SCAN_MODE_CONNECTABLE_DISCOVERABLE
,
SCAN_MODE_CONNECTABLE
,
or SCAN_MODE_NONE
,
which indicate that the device is either in discoverable mode, not in
discoverable mode but still able to receive connections, or not in
discoverable
mode and unable to receive connections, respectively.
You do not need to enable device discoverability if you will be
initiating
the connection to a remote device. Enabling discoverability is only
necessary when
you want your application to host a server socket that will accept
incoming
connections, because the remote devices must be able to discover the
device
before it can initiate the connection.
Connecting Devices
In order to create a connection between your application on two
devices, you
must implement both the server-side and client-side mechanisms, because
one
device must open a server socket and the other one must initiate the
connection
(using the server device's MAC address to initiate a connection). The
server and
client are considered connected to each other when they each have a
connected
BluetoothSocket
on the same RFCOMM channel. At this
point, each device can obtain input and output streams and data transfer
can
begin, which is discussed in the section about Managing
a Connection
. This section describes how
to initiate the connection between two devices.
The server device and the client device each obtain the required BluetoothSocket
in different ways. The server will receive it
when an incoming connection is accepted. The client will receive it when
it
opens an RFCOMM channel to the server.
One implementation technique is to automatically prepare each device
as a
server, so that each one has a server socket open and listening for
connections.
Then either device can initiate a connection with the other and become
the
client. Alternatively, one device can explicitly "host" the connection
and open
a server socket on demand and the other device can simply initiate the
connection.
Note:
If the two devices have not been
previously paired,
then the Android framework will automatically show a pairing request
notification or
dialog to the user during the connection procedure, as shown in Figure
3. So
when attempting to connect devices,
your application does not need to be concerned about whether or not the
devices are
paired. Your RFCOMM connection attempt will block until the user has
successfully paired,
or will fail if the user rejects pairing, or if pairing fails or times
out.
Connecting as a server
When you want to connect two devices, one must act as a server by
holding an
open BluetoothServerSocket
.
The purpose of the server
socket is to listen for incoming connection requests and when one is
accepted,
provide a connected BluetoothSocket
.
When the BluetoothSocket
is acquired from the BluetoothServerSocket
,
the BluetoothServerSocket
can (and should) be
discarded, unless you want to accept more connections.
About UUID
A Universally Unique Identifier (UUID) is a standardized 128-bit
format for a string
ID used to uniquely identify information. The point of a UUID is that
it's big
enough that you can select any random and it won't clash. In this case,
it's
used to uniquely identify your application's Bluetooth service. To get a
UUID to
use with your application, you can use one of the many random UUID
generators on
the web, then initialize a UUID
with fromString(String)
.
Here's the basic procedure to set up a server socket and accept a
connection:
- Get a
BluetoothServerSocket
by calling the
listenUsingRfcommWithServiceRecord(String,
UUID)
.
The string is an identifiable name of your service, which the system
will
automatically write to a new Service Discovery Protocol (SDP) database
entry on
the device (the name is arbitrary and can simply be your application
name). The
UUID is also included in the SDP entry and will be the basis for the
connection
agreement with the client device. That is, when the client attempts to
connect
with this device, it will carry a UUID that uniquely identifies the
service with
which it wants to connect. These UUIDs must match in order for the
connection to
be accepted (in the next step).
- Start listening for connection requests by calling
accept()
.
This is a blocking call. It will return when either a connection has
been
accepted or an exception has occurred. A connection is accepted only
when a
remote device has sent a connection request with a UUID matching the one
registered with this listening server socket. When successful, accept()
will
return a connected BluetoothSocket
.
- Unless you want to accept additional connections, call
close()
.
This releases the server socket and all its resources, but does not
close the
connected BluetoothSocket
that's been returned by accept()
.
Unlike TCP/IP, RFCOMM only allows one
connected client per channel at a time, so in most cases it makes sense
to call close()
on the BluetoothServerSocket
immediately after accepting a connected
socket.
The accept()
call should not
be executed in the main Activity UI thread because it is a blocking call
and
will prevent any other interaction with the application. It usually
makes
sense to do all work with a BluetoothServerSocket
or BluetoothSocket
in a new
thread managed by your application. To abort a blocked call such as accept()
,
call close()
on the BluetoothServerSocket
(or BluetoothSocket
)
from another thread and the blocked call will
immediately return. Note that all methods on a BluetoothServerSocket
or BluetoothSocket
are thread-safe.
Example
Here's a simplified thread for the server component that accepts
incoming
connections:
private
class
AcceptThread
extends
Thread
{
private
final
BluetoothServerSocket
mmServerSocket
;
public
AcceptThread
()
{
// Use a temporary object that is later assigned to mmServerSocket,
// because mmServerSocket is final
BluetoothServerSocket
tmp
=
null
;
try
{
// MY_UUID is the app's UUID string, also used by the client code
tmp
=
mAdapter
.
listenUsingRfcommWithServiceRecord
(
NAME
,
MY_UUID
);
}
catch
(
IOException
e
)
{
}
mmServerSocket
=
tmp
;
}
public
void
run
()
{
BluetoothSocket
socket
=
null
;
// Keep listening until exception occurs or a socket is returned
while
(
true
)
{
try
{
socket
=
mmServerSocket
.
accept
();
}
catch
(
IOException
e
)
{
break
;
}
// If a connection was accepted
if
(
socket
!=
null
)
{
// Do work to manage the connection (in a separate thread)
manageConnectedSocket
(
socket
);
mmServerSocket
.
close
();
break
;
}
}
}
/** Will cancel the listening socket, and cause the thread to finish */
public
void
cancel
()
{
try
{
mmServerSocket
.
close
();
}
catch
(
IOException
e
)
{
}
}
}
In this example, only one incoming connection is desired, so as soon
as a
connection is accepted and the BluetoothSocket
is
acquired, the application
sends the acquired BluetoothSocket
to a separate
thread, closes the
BluetoothServerSocket
and breaks the loop.
Note that when accept()
returns the BluetoothSocket
,
the socket is already
connected, so you should not
call connect()
(as you do from the
client-side).
manageConnectedSocket()
is a fictional method in the
application
that will
initiate the thread for transferring data, which is discussed in the
section
about Managing
a Connection
.
You should usually close your BluetoothServerSocket
as soon as you are done listening for incoming connections. In this
example, close()
is called as soon
as the BluetoothSocket
is acquired. You may also want
to provide a public method in your thread that can close the private BluetoothSocket
in the event that you need to stop listening on the
server socket.
Connecting as a client
In order to initiate a connection with a remote device (a device
holding an
open
server socket), you must first obtain a BluetoothDevice
object that represents the remote device.
(Getting a BluetoothDevice
is covered in the above
section about Finding
Devices
.) You must then use the
BluetoothDevice
to acquire a BluetoothSocket
and initiate the connection.
Here's the basic procedure:
- Using the
BluetoothDevice
,
get a BluetoothSocket
by calling createRfcommSocketToServiceRecord(UUID)
.
This initializes a BluetoothSocket
that will
connect to the BluetoothDevice
.
The UUID passed here
must match the UUID used by the server device when it opened its
BluetoothServerSocket
(with listenUsingRfcommWithServiceRecord(String,
UUID)
). Using the same UUID is simply a matter of
hard-coding the UUID string
into your application and then referencing it from both the server and
client
code.
- Initiate the connection by calling
connect()
.
Upon this call, the system will perform an SDP lookup on the remote
device in
order to match the UUID. If the lookup is successful and the remote
device
accepts the connection, it will share the RFCOMM channel to use during
the
connection and connect()
will return. This method is a
blocking call. If, for
any reason, the connection fails or the connect()
method times out (after about
12 seconds), then it will throw an exception.
Because connect()
is a blocking call, this connection
procedure should always be performed in a thread separate from the main
Activity
thread.
Note: You should always ensure that the device is not
performing
device discovery when you call connect()
.
If discovery is in progress, then
the
connection attempt will be significantly slowed and is more likely to
fail.
Example
Here is a basic example of a thread that initiates a Bluetooth
connection:
private
class
ConnectThread
extends
Thread
{
private
final
BluetoothSocket
mmSocket
;
private
final
BluetoothDevice
mmDevice
;
public
ConnectThread
(
BluetoothDevice
device
)
{
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket
tmp
=
null
;
mmDevice
=
device
;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try
{
// MY_UUID is the app's UUID string, also used by the server code
tmp
=
device
.
createRfcommSocketToServiceRecord
(
MY_UUID
);
}
catch
(
IOException
e
)
{
}
mmSocket
=
tmp
;
}
public
void
run
()
{
// Cancel discovery because it will slow down the connection
mAdapter
.
cancelDiscovery
();
try
{
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket
.
connect
();
}
catch
(
IOException
connectException
)
{
// Unable to connect; close the socket and get out
try
{
mmSocket
.
close
();
}
catch
(
IOException
closeException
)
{
}
return
;
}
// Do work to manage the connection (in a separate thread)
manageConnectedSocket
(
mmSocket
);
}
/** Will cancel an in-progress connection, and close the socket */
public
void
cancel
()
{
try
{
mmSocket
.
close
();
}
catch
(
IOException
e
)
{
}
}
}
Notice that cancelDiscovery()
is called
before the connection is made. You should always do this before
connecting and it is safe
to call without actually checking whether it is running or not (but if
you do want to
check, call isDiscovering()
).
manageConnectedSocket()
is a fictional method in the
application
that will initiate the thread for transferring data, which is discussed
in the section
about Managing
a Connection
.
When you're done with your BluetoothSocket
,
always
call close()
to clean up.
Doing so will immediately close the connected socket and clean up all
internal
resources.
Managing a Connection
When you have successfully connected two (or more) devices, each one
will
have a connected BluetoothSocket
.
This is where the fun
begins because you can share data between devices. Using the BluetoothSocket
,
the general procedure to transfer arbitrary data is
simple:
- Get the
InputStream
and OutputStream
that
handle transmissions through the socket, via getInputStream()
and
getOutputStream()
,
respectively.
- Read and write data to the streams with
read(byte[])
and write(byte[])
.
That's it.
There are, of course, implementation details to consider. First and
foremost,
you should use a dedicated thread for all stream reading and writing.
This is
important because both read(byte[])
and write(byte[])
methods are blocking calls. read(byte[])
will block until there is something to read
from the stream. write(byte[])
does not usually
block, but can block for flow control if the remote device is not
calling read(byte[])
quickly enough and the intermediate buffers are full.
So, your main loop in the thread should be dedicated to reading from the
InputStream
.
A separate public method in the thread can be used to initiate
writes to the OutputStream
.
Example
Here's an example of how this might look:
private
class
ConnectedThread
extends
Thread
{
private
final
BluetoothSocket
mmSocket
;
private
final
InputStream
mmInStream
;
private
final
OutputStream
mmOutStream
;
public
ConnectedThread
(
BluetoothSocket
socket
)
{
mmSocket
=
socket
;
InputStream
tmpIn
=
null
;
OutputStream
tmpOut
=
null
;
// Get the input and output streams, using temp objects because
// member streams are final
try
{
tmpIn
=
socket
.
getInputStream
();
tmpOut
=
socket
.
getOutputStream
();
}
catch
(
IOException
e
)
{
}
mmInStream
=
tmpIn
;
mmOutStream
=
tmpOut
;
}
public
void
run
()
{
byte
[]
buffer
=
new
byte
[
1024
];
// buffer store for the stream
int
bytes
;
// bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while
(
true
)
{
try
{
// Read from the InputStream
bytes
=
mmInStream
.
read
(
buffer
);
// Send the obtained bytes to the UI Activity
mHandler
.
obtainMessage
(
MESSAGE_READ
,
bytes
,
-
1
,
buffer
)
.
sendToTarget
();
}
catch
(
IOException
e
)
{
break
;
}
}
}
/* Call this from the main Activity to send data to the remote device */
public
void
write
(
byte
[]
bytes
)
{
try
{
mmOutStream
.
write
(
bytes
);
}
catch
(
IOException
e
)
{
}
}
/* Call this from the main Activity to shutdown the connection */
public
void
cancel
()
{
try
{
mmSocket
.
close
();
}
catch
(
IOException
e
)
{
}
}
}
The constructor acquires the necessary streams and once executed, the
thread
will wait for data to come through the InputStream. When read(byte[])
returns with
bytes from the stream, the data is sent to the main Activity using a
member
Handler from the parent class. Then it goes back and waits for more
bytes from
the stream.
Sending outgoing data is as simple as calling the thread's
write()
method from the main Activity and passing in the
bytes to
be sent. This method then simply calls write(byte[])
to send the data to the remote device.
The thread's cancel()
method is important so that the
connection
can be
terminated at any time by closing the BluetoothSocket
.
This should always be called when you're done using the Bluetooth
connection.