Android 蓝牙

Bluetooth

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 throughthe Android Bluetooth APIs. These APIs let applications wirelesslyconnect to other Bluetooth devices, enabling point-to-point and multipointwireless features.

Using the Bluetooth APIs, an Android application can perform thefollowing:

  • 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 use the Android Bluetooth APIs to accomplishthe four major tasks necessary to communicate using Bluetooth: setting upBluetooth, finding devices that are either paired or available in the localarea, connecting devices, and transferring data between devices.

All of the Bluetooth APIs are available in the android.bluetoothpackage. Here's a summary of the classes and interfaces you will need to create Bluetoothconnections:

BluetoothAdapter
Represents the local Bluetooth adapter (Bluetooth radio). The BluetoothAdapter is the entry-point for all Bluetoothinteraction. Using this,you can discover other Bluetooth devices, query a list of bonded (paired)devices, instantiate a BluetoothDevice using a knownMAC address, and create a BluetoothServerSocket tolisten for communicationsfrom other devices.
BluetoothDevice
Represents a remote Bluetooth device. Use this to request a connectionwith a remote device through a BluetoothSocket orquery information about thedevice 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 allowsan application to exchange data with another Bluetooth device via InputStreamand OutputStream.
BluetoothServerSocket
Represents an open server socket that listens for incoming requests(similar to a TCP ServerSocket). In order to connect twoAndroid devices, one device must open a server socket with this class. When aremote Bluetooth device makes a connection request to the this device, the BluetoothServerSocket will return a connected BluetoothSocket when theconnection is accepted.
BluetoothClass
Describes the general characteristics and capabilities of a Bluetoothdevice. This is a read-only set of properties that define the device's major andminor device classes and its services. However, this does not reliably describeall Bluetooth profiles and services supported by the device, but is useful as ahint to the device type.
BluetoothProfile
An interface thatrepresents a Bluetooth profile. A Bluetooth profile is a wirelessinterface specification for Bluetooth-based communication between devices. Anexample is the Hands-Free profile. For more discussion of profiles, see Working with Profiles
BluetoothHeadset
Provides support forBluetooth headsets to be used with mobile phones. This includes both BluetoothHeadset and Hands-Free (v1.5) profiles.
BluetoothA2dp
Defines how high qualityaudio can be streamed from one device to another over a Bluetooth connection."A2DP" stands for Advanced Audio Distribution Profile.
BluetoothProfile.ServiceListener
An interface that notifies BluetoothProfile IPCclients when they have been connected to or disconnected from the service (thatis, the internal service that runs a particular profile).

Bluetooth Permissions

In order to use Bluetooth features in your application, you need to declareat least one of two Bluetooth permissions:BLUETOOTH andBLUETOOTH_ADMIN.

You must request the BLUETOOTH permissionin order to perform any Bluetooth communication, such as requesting aconnection, accepting a connection, and transferring data.

You must request the BLUETOOTH_ADMINpermission in order to initiate device discovery or manipulate Bluetoothsettings. Most applications need this permission solely for theability to discover local Bluetooth devices. The other abilities granted by thispermission should not be used, unless the application is a "power manager" thatwill modify Bluetooth settings upon user request.Note: If youuse BLUETOOTH_ADMIN permission, then mustalso have theBLUETOOTH permission.

Declare the Bluetooth permission(s) in your application manifest file. Forexample:

 
<manifest ... >
  <uses-permission android:name="android.permission.BLUETOOTH" />
  ...
</manifest>

See the <uses-permission> reference for more information about declaring application permissions.

Setting Up Bluetooth

  Figure 1: The enabling Bluetooth dialog.

Before your application can communicate over Bluetooth, you need to verifythat Bluetooth is supported on the device, and if so, ensure that it is enabled.

If Bluetooth is not supported, then you should gracefully disable anyBluetooth features. If Bluetooth is supported, but disabled, then you can request that theuser enable Bluetooth without leaving your application. This setup isaccomplished in two steps, using the BluetoothAdapter.

  1. Get the BluetoothAdapter

    The BluetoothAdapter is required for any and all Bluetoothactivity. To get theBluetoothAdapter, call the staticgetDefaultAdapter() method. This returns aBluetoothAdapter that represents the device's ownBluetooth adapter (the Bluetooth radio). There's one Bluetooth adapter for theentire system, and your application can interact with it using this object. IfgetDefaultAdapter() 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
    }
  2. Enable Bluetooth

    Next, you need to ensure that Bluetooth is enabled. Call isEnabled() to check whether Bluetooth iscurrently enable. If this method returns false, then Bluetooth is disabled. Torequest that Bluetooth be enabled, call startActivityForResult()with theACTION_REQUEST_ENABLE action Intent.This will issue a request to enable Bluetooth through the system settings (withoutstopping 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 shownin Figure 1. If the user responds "Yes," the system will begin to enable Bluetoothand 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 theonActivityResult()callback. If Bluetooth was not enableddue to an error (or the user responded "No") then the result code will beRESULT_CANCELED.

Optionally, your application can also listen for theACTION_STATE_CHANGED broadcast Intent, whichthe system will broadcast whenever the Bluetooth state has changed. This broadcast containsthe extra fields EXTRA_STATE andEXTRA_PREVIOUS_STATE, containing the new and oldBluetooth states, respectively. Possible values for these extra fields areSTATE_TURNING_ON,STATE_ON,STATE_TURNING_OFF, andSTATE_OFF. Listening for thisbroadcast can be useful to detect changes made to the Bluetooth state while yourapp is running.

Tip: Enabling discoverability will automaticallyenable Bluetooth. If you plan to consistently enable device discoverability beforeperforming Bluetooth activity, you can skipstep 2 above. Read aboutenabling discoverability,below.

Finding Devices

Using the BluetoothAdapter, you can find remote Bluetoothdevices either through device discovery or by querying the list of paired (bonded)devices.

Device discovery is a scanning procedure that searches the local area forBluetooth 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 discoveryrequest only if it is currently enabled to be discoverable. If a device isdiscoverable, it will respond to the discovery request by sharing someinformation, such as the device name, class, and its unique MAC address. Usingthis information, the device performing discovery can then choose to initiate aconnection to the discovered device.

Once a connection is made with a remote device for the first time, a pairingrequest is automatically presented to the user. When a device ispaired, 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 theknown MAC address for a remote device, a connection can be initiated with it atany time without performing discovery (assuming the device is within range).

Remember there is a difference between being paired and being connected. Tobe paired means that two devices are aware of each other's existence, have ashared link-key that can be used for authentication, and are capable ofestablishing an encrypted connection with each other. To be connected means thatthe devices currently share an RFCOMM channel and are able to transmit data witheach other. The current Android Bluetooth API's require devices to be pairedbefore an RFCOMM connection can be established. (Pairing is automatically performedwhen you initiate an encrypted connection with the Bluetooth APIs.)

The following sections describe how to find devices that have been paired, ordiscover new devices using device discovery.

Note: Android-powered devices are notdiscoverable by default. A user can makethe device discoverable for a limited time through the system settings, or anapplication can request that the user enable discoverability without leaving theapplication. How to enable discoverability is discussed below.

Querying paired devices

Before performing device discovery, its worth querying the setof paired devices to see if the desired device is already known. To do so,callgetBondedDevices(). Thiswill return a Set ofBluetoothDevices representingpaired devices. For example, you can query all paired devices and thenshow 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 objectin order to initiate a connection is the MAC address. In this example, it's savedas a part of an ArrayAdapter that's shown to the user. The MAC address can laterbe extracted in order to initiate the connection. You can learn more about creatinga connection in the section aboutConnecting Devices.

Discovering devices

To start discovering devices, simply call startDiscovery(). Theprocess is asynchronous and the method will immediately return with a booleanindicating whether discovery has successfully started. The discovery processusually involves an inquiry scan of about 12 seconds, followed by a page scan ofeach found device to retrieve its Bluetooth name.

Your application must register a BroadcastReceiver for theACTION_FOUND Intent inorder to receive information about eachdevice discovered. For each device, the system will broadcast theACTION_FOUND Intent. ThisIntent carries the extra fieldsEXTRA_DEVICE andEXTRA_CLASS, containing aBluetoothDevice and a BluetoothClass, respectively. For example, here's how you canregister 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 objectin order to initiate aconnection is the MAC address. In this example, it's saved as a part of anArrayAdapter that's shown to the user. The MAC address can later be extracted inorder to initiate the connection. You can learn more about creating a connectionin the section aboutConnecting Devices.

Caution: Performing device discovery isa heavy procedure for the Bluetoothadapter and will consume a lot of its resources. Once you have found a device toconnect, be certain that you always stop discovery withcancelDiscovery() beforeattempting a connection. Also, if youalready hold a connection with a device, then performing discovery cansignificantly reduce the bandwidth available for the connection, so you shouldnot perform discovery while connected.

Enabling discoverability

If you would like to make the local device discoverable to other devices,call startActivityForResult(Intent, int) with theACTION_REQUEST_DISCOVERABLE actionIntent. This will issue a request to enable discoverable mode through the systemsettings (without stopping your application). By default, the device will becomediscoverable for 120 seconds. You can define a different duration by adding theEXTRA_DISCOVERABLE_DURATION Intentextra. The maximum duration an app can set is 3600 seconds, and a value of 0means the device is always discoverable. Any value below 0 or above 3600 isautomatically set to 120 secs). For example, this snippet sets the duration to300:

Intent discoverableIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
  Figure 2: The enabling discoverability dialog.

A dialog will be displayed, requesting user permission to make the devicediscoverable, as shown in Figure 2. If the user responds "Yes," then the devicewill become discoverable for the specified amount of time. Your Activity willthen receive a call to theonActivityResult()) callback, with the result code equal to the duration that the deviceis discoverable. If the user responded "No" or if an error occurred, the result code willbe 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 canregister a BroadcastReceiver for theACTION_SCAN_MODE_CHANGEDIntent. This will contain the extra fieldsEXTRA_SCAN_MODE andEXTRA_PREVIOUS_SCAN_MODE, which tell you thenew and old scan mode, respectively. Possible values for each areSCAN_MODE_CONNECTABLE_DISCOVERABLE,SCAN_MODE_CONNECTABLE, or SCAN_MODE_NONE,which indicate that the device is either in discoverable mode, not indiscoverable mode but still able to receive connections, or not in discoverablemode and unable to receive connections, respectively.

You do not need to enable device discoverability if you will be initiatingthe connection to a remote device. Enabling discoverability is only necessary whenyou want your application to host a server socket that will accept incomingconnections, because the remote devices must be able to discover the devicebefore it can initiate the connection.

Connecting Devices

In order to create a connection between your application on two devices, youmust implement both the server-side and client-side mechanisms, because onedevice 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 andclient are considered connected to each other when they each have a connectedBluetoothSocket on the same RFCOMM channel. At thispoint, each device can obtain input and output streams and data transfer canbegin, which is discussed in the section aboutManaging a Connection. This section describes howto 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 itwhen an incoming connection is accepted. The client will receive it when itopens an RFCOMM channel to the server.

  Figure 3: The Bluetooth pairing dialog.

One implementation technique is to automatically prepare each device as aserver, 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 theclient. Alternatively, one device can explicitly "host" the connection and opena server socket on demand and the other device can simply initiate theconnection.

Note: If the two devices have not been previously paired,then the Android framework will automatically show a pairing request notification ordialog to the user during the connection procedure, as shown in Figure 3. Sowhen attempting to connect devices,your application does not need to be concerned about whether or not the devices arepaired. 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 anopenBluetoothServerSocket. The purpose of the serversocket is to listen for incoming connection requests and when one is accepted,provide a connectedBluetoothSocket. When theBluetoothSocket is acquired from theBluetoothServerSocket,theBluetoothServerSocket can (and should) bediscarded, unless you want to accept more connections.

Here's the basic procedure to set up a server socket and accept aconnection:

  1. Get a BluetoothServerSocket by calling thelistenUsingRfcommWithServiceRecord(String, UUID).

    The string is an identifiable name of your service, which the system willautomatically write to a new Service Discovery Protocol (SDP) database entry onthe device (the name is arbitrary and can simply be your application name). TheUUID is also included in the SDP entry and will be the basis for the connectionagreement with the client device. That is, when the client attempts to connectwith this device, it will carry a UUID that uniquely identifies the service withwhich it wants to connect. These UUIDs must match in order for the connection tobe accepted (in the next step).

  2. Start listening for connection requests by callingaccept().

    This is a blocking call. It will return when either a connection has beenaccepted or an exception has occurred. A connection is accepted only when aremote device has sent a connection request with a UUID matching the oneregistered with this listening server socket. When successful, accept() willreturn a connectedBluetoothSocket.

  3. Unless you want to accept additional connections, callclose().

    This releases the server socket and all its resources, but does not close theconnectedBluetoothSocket that's been returned byaccept(). Unlike TCP/IP, RFCOMM only allows oneconnected client per channel at a time, so in most cases it makes sense to callclose() on theBluetoothServerSocket immediately after accepting a connectedsocket.

The accept() call should notbe executed in the main Activity UI thread because it is a blocking call andwill prevent any other interaction with the application. It usually makessense to do all work with a BluetoothServerSocket orBluetoothSocket in a newthread managed by your application. To abort a blocked call such asaccept(), callclose() on theBluetoothServerSocket (orBluetoothSocket) from another thread and the blocked call willimmediately return. Note that all methods on aBluetoothServerSocket orBluetoothSocketare thread-safe.

Example

Here's a simplified thread for the server component that accepts incomingconnections:

 
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 = mBluetoothAdapter.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 aconnection is accepted and theBluetoothSocket isacquired, the applicationsends the acquiredBluetoothSocket to a separatethread, closes theBluetoothServerSocket and breaks the loop.

Note that when accept()returns theBluetoothSocket, the socket is alreadyconnected, so you shouldnot call connect() (as you do from theclient-side).

manageConnectedSocket() is a fictional method in the applicationthat willinitiate the thread for transferring data, which is discussed in the sectionaboutManaging a Connection.

You should usually close your BluetoothServerSocketas soon as you are done listening for incoming connections. In this example,close() is called as soonas theBluetoothSocket is acquired. You may also wantto provide a public method in your thread that can close the privateBluetoothSocket in the event that you need to stop listening on theserver socket.

Connecting as a client

In order to initiate a connection with a remote device (a device holding anopenserver socket), you must first obtain aBluetoothDevice object that represents the remote device.(Getting aBluetoothDevice is covered in the abovesection aboutFinding Devices.) You must then use theBluetoothDevice to acquire aBluetoothSocket and initiate the connection.

Here's the basic procedure:

  1. Using the BluetoothDevice, get aBluetoothSocket by callingcreateRfcommSocketToServiceRecord(UUID).

    This initializes a BluetoothSocket that willconnect to theBluetoothDevice. The UUID passed heremust match the UUID used by the server device when it opened itsBluetoothServerSocket (withlistenUsingRfcommWithServiceRecord(String, UUID)). Using the same UUID is simply a matter of hard-coding the UUID stringinto your application and then referencing it from both the server and clientcode.

  2. Initiate the connection by calling connect().

    Upon this call, the system will perform an SDP lookup on the remote device inorder to match the UUID. If the lookup is successful and the remote deviceaccepts the connection, it will share the RFCOMM channel to use during theconnection andconnect() will return. This method is ablocking call. If, forany reason, the connection fails or theconnect() method times out (after about12 seconds), then it will throw an exception.

    Because connect() is a blocking call, this connectionprocedure should always be performed in a thread separate from the main Activitythread.

    Note: You should always ensure that the device is not performingdevice discovery when you callconnect(). If discovery is in progress, thentheconnection attempt will be significantly slowed and is more likely to fail.

Example

Here is a basic example of a thread that initiates a Bluetoothconnection:

 
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
        mBluetoothAdapter.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 calledbefore the connection is made. You should always do this before connecting and it is safeto call without actually checking whether it is running or not (but if you do want tocheck, callisDiscovering()).

manageConnectedSocket() is a fictional method in the applicationthat will initiate the thread for transferring data, which is discussed in the sectionaboutManaging a Connection.

When you're done with your BluetoothSocket, alwayscallclose() to clean up.Doing so will immediately close the connected socket and clean up all internalresources.

Managing a Connection

When you have successfully connected two (or more) devices, each one willhave a connectedBluetoothSocket. This is where the funbegins because you can share data between devices. Using theBluetoothSocket, the general procedure to transfer arbitrary data issimple:

  1. Get the InputStream andOutputStream thathandle transmissions through the socket, viagetInputStream() andgetOutputStream(), respectively.
  2. Read and write data to the streams with read(byte[]) andwrite(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 isimportant because bothread(byte[]) andwrite(byte[]) methods are blocking calls.read(byte[]) will block until there is something to readfrom the stream.write(byte[]) does not usuallyblock, but can block for flow control if the remote device is not callingread(byte[]) quickly enough and the intermediate buffers are full.So, your main loop in the thread should be dedicated to reading from theInputStream. A separate public method in the thread can be used to initiatewrites to theOutputStream.

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 threadwill wait for data to come through the InputStream. Whenread(byte[]) returns withbytes from the stream, the data is sent to the main Activity using a memberHandler from the parent class. Then it goes back and waits for more bytes fromthe stream.

Sending outgoing data is as simple as calling the thread'swrite() method from the main Activity and passing in the bytes tobe sent. This method then simply callswrite(byte[]) to send the data to the remote device.

The thread's cancel() method is important so that the connectioncan beterminated at any time by closing theBluetoothSocket.This should always be called when you're done using the Bluetoothconnection.

For a demonstration of using the Bluetooth APIs, see the Bluetooth Chat sample app.

Working with Profiles

Starting in Android 3.0, the Bluetooth API includes support for working withBluetooth profiles. ABluetooth profile is a wireless interfacespecification for Bluetooth-based communication between devices. An exampleis the Hands-Free profile. For a mobile phone to connect to a wireless headset,both devices must support the Hands-Free profile.

You can implement the interface BluetoothProfile to writeyour own classes to support a particular Bluetooth profile. The AndroidBluetooth API provides implementations for the following Bluetoothprofiles:

  • Headset. The Headset profile provides support forBluetooth headsets to be used with mobile phones. Android provides theBluetoothHeadset class, which is a proxy for controlling theBluetooth Headset Service via interprocess communication (IPC). This includes both Bluetooth Headset and Hands-Free (v1.5) profiles. TheBluetoothHeadset class includes support for AT commands.For more discussion of this topic, seeVendor-specific AT commands
  • A2DP. The Advanced Audio Distribution Profile (A2DP)profile defines how high quality audio can be streamed from one device toanother over a Bluetooth connection. Android provides theBluetoothA2dp class, which is a proxy for controllingthe Bluetooth A2DP Service via IPC.

Here are the basic steps for working with a profile:

  1. Get the default adapter, as described in Setting Up Bluetooth.
  2. Use getProfileProxy() toestablish a connection to the profile proxy object associated with the profile.In the example below, the profile proxy object is an instance ofBluetoothHeadset.
  3. Set up a BluetoothProfile.ServiceListener. Thislistener notifiesBluetoothProfile IPC clients whenthey have been connected to or disconnected from the service.
  4. In onServiceConnected(), get a handleto the profile proxy object.
  5. Once you have the profile proxy object, you can use it to monitor thestate of the connection and perform other operations that are relevant to thatprofile.

For example, this code snippet shows how to connect to a BluetoothHeadset proxy object so that you can control theHeadset profile:

BluetoothHeadset mBluetoothHeadset;
 
// Get the default adapter
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
 
// Establish connection to the proxy.
mBluetoothAdapter.getProfileProxy(context, mProfileListener, BluetoothProfile.HEADSET);
 
private BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() {
    public void onServiceConnected(int profile, BluetoothProfile proxy) {
        if (profile == BluetoothProfile.HEADSET) {
            mBluetoothHeadset = (BluetoothHeadset) proxy;
        }
    }
    public void onServiceDisconnected(int profile) {
        if (profile == BluetoothProfile.HEADSET) {
            mBluetoothHeadset = null;
        }
    }
};
 
// ... call functions on mBluetoothHeadset
 
// Close proxy connection after use.
mBluetoothAdapter.closeProfileProxy(mBluetoothHeadset);

Vendor-specific AT commands

Starting in Android 3.0, applications can register to receive systembroadcasts of pre-defined vendor-specific AT commands sent by headsets (such asa Plantronics +XEVENT command). For example, an application could receivebroadcasts that indicate a connected device's battery level and could notify theuser or take other action as needed. Create a broadcast receiver for theACTION_VENDOR_SPECIFIC_HEADSET_EVENT intentto handle vendor-specific AT commands for the headset.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值