Connect Bluetooth devices | Android Developers
To create a connection between two devices, you must implement both server-side and client-side mechanisms because one device must open a server socket and the other must initiate the connection using the server device’s mac address. the server device and the client device each obtain the required bluetoothsocket in different ways. the server receives socket information when an incoming connection is accepted. the client provides socket information when it opens an rfcomm channel to the server.
Server and client are considered to be connected to each other when they each have a bluetooth socket connected on the same rfcomm channel. At this point, each device can get input and output streams, and can begin data transfer, which is discussed in the section on bluetooth data transfer. This section describes how to start the connection between two devices.
make sure you have the proper bluetooth permissions and configure your app for bluetooth before trying to find bluetooth devices.
connection techniques
One implementation technique is to automatically set up each device as a server so that each device has a server socket open and listening for connections. in this case, either device can initiate a connection to the other and become the client. alternatively, one device can explicitly host the connection and open a server socket on request, and the other device initiates the connection.
Figure 1: The Bluetooth pairing dialog.
connect as server
When you want to connect two devices, one must act as a server by keeping a bluetooth server socket open. the purpose of the server socket is to listen for incoming connection requests and provide a connected bluetoothsocket after a request is accepted. when the bluetoothsocket is acquired from the bluetoothservocket, the bluetoothservocket can (and should) be discarded, unless you want the device to accept more connections.
To set up a server socket and accept a connection, complete the following sequence of steps:
-
Get a bluetooth server socket by calling listenusingrfcommwithservicerecord(string, uuid).
The string is an identifiable name of your service, which is automatically written by the system to a new Service Discovery Protocol (sdp) database entry on the device. the name is arbitrary and can just be the name of your application. the universally unique identifier (uuid) is also included in the sdp entry and forms the basis for the connection agreement with the client device. that is, when the client attempts to connect to this device, it carries a uuid that uniquely identifies the service it wishes to connect to. these uuids must match for the connection to be accepted.
A uuid is a standardized 128-bit format for a string identification used to uniquely identify information. A uuid is used to identify information that must be unique within a system or network because the probability of a uuid repeating itself is effectively zero. it is generated independently, without the use of a centralized authority. in this case, it is 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, and then initialize a uuid with fromstring(string).
start listening for connection requests by calling accept().
this is a blocking call. returns when a connection has been accepted or an exception has occurred. a connection is accepted only when a remote device has sent a connection request that contains a uuid that matches the one registered with this listening server socket. when successful, accept() returns a connected bluetooth socket.
Unless you want to accept additional connections, call close().
This method call releases the server socket and all its resources, but does not close the connected bluetoothsocket returned by accept(). Unlike tcp/ip, rfcomm allows only one connected client per channel at a time, so in most cases it makes sense to call close() on the bluetoothservocket immediately after accepting a connected socket.
Because the accept() call is a blocking call, don’t run it on the main activity’s UI thread. running it on another thread ensures that your app can still respond to other user interactions. it usually makes sense to do all the work involving a bluetoothservocket or bluetoothsocket in a new thread managed by your application. To abort a blocked call like accept(), call close() on the bluetoothservocket or bluetoothsocket from another thread. note that all methods in a bluetoothservocket or bluetoothsocket are thread-safe.
example
The following is a simplified thread for the server component that accepts incoming connections:
In this example, only one incoming connection is desired, so as soon as a connection is accepted and the bluetoothsocket is acquired, the application passes the acquired bluetoothsocket to a separate thread, closes the bluetoothservocket, and exits the loop.
Note that when accept() returns the bluetoothsocket, the socket is already connected. therefore, you should not call connect(), as you do from the client side.
The application-specific managemyconnectedsocket() method is designed to start the thread to transfer data, which is discussed in bluetooth data transfer.
Usually you should close your bluetoothservocket as soon as you finish 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 bluetooth socket in case you need to stop listening on that server socket.
connect as client
To initiate a connection to a remote device that accepts connections on an open server socket, you must first obtain a bluetoothdevice object that represents the remote device. For information on how to create a bluetooth device, see find bluetooth devices. then you need to use the bluetooth device to acquire a bluetooth plug and start the connection.
The basic procedure is as follows:
-
Using the bluetooth device, get a bluetoothsocket by calling createrfcommsockettoservicerecord(uuid).
This method initializes a bluetoothsocket object that allows the client to connect to a bluetooth device. the uuid passed here must match the uuid used by the server device when it called listenusingrfcommwithservicerecord(string, uuid) to open its bluetoothserversocket. To use a matching uuid, encode the uuid string in your application and then reference it from both server and client code.
start the connection by calling connect(). note that this method is a blocking call.
after a client calls this method, the system performs an sdp lookup to find the remote device with the matching uuid. if the lookup is successful and the remote device accepts the connection, it shares the rfcomm channel to use during the connection and the connect() method returns. if the connection fails, or if the connect() method times out (after about 12 seconds), then the method throws an ioexception.
Because connect() is a blocking call, you should always perform this connection procedure on a thread that is separate from the main activity (ui) thread.
example
The following is a basic example of a client thread initiating a bluetooth connection:
Notice that in this snippet, canceldiscovery() is called before the connection attempt occurs. you should always call canceldiscovery() before connect(), especially since canceldiscovery() succeeds regardless of whether device discovery is currently in progress. if your app needs to determine if device discovery is in progress, you can check using isdiscovering().
The application-specific managemyconnectedsocket() method is designed to start the thread to transfer data, which is discussed in the section on bluetooth data transfer.
When you’re done with your bluetoothsocket, always call close(). doing so immediately closes the connected socket and releases all related internal resources.
-