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.
Android平台包含技持蓝牙网络,它允许一个设备与另一个设备进无线数据传输。这个程序框架提供了API访问蓝牙的函数。让这些程序无线去连接蓝牙设备,应用与点对点和多个点无线特征.
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 建立RFCOMM通道
- 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 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.
这个文档用于描述如何去使用Android 蓝牙API去完成自四个主要的任务。1、设置蓝牙 2、发现本地可用设备或已配对设备 3、连接设备 4、传输数据
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.
这个类主要是代表本机的蓝牙适配器。蓝牙适配器是所有蓝牙设备数据交换的入口。使用这个类你可以发现其它蓝牙设备,查询已配对设备列表,已知MAC(硬件地址)实例化一个设备对象,创建一个BluetoothServerSocket 对象去监听来自其它蓝牙设备的连接。
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.
代表一个远程蓝牙设备。用这个类通过一个 BlueSocket(相当于TCP/IP里面的Socket) 可去请求一个与远程设备的连接,或者可以查询以下信息:设备名称、硬件地址、类及连接状态。
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.
代表BluetoothSocket的接口(类似于TCPSocket).这是一个连接点,它允许程序通过输入输出流进行数据交换
BluetoothServerSocket
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.
代表一个开放的服务Socket去监听进来的请求(类似于一个TCP ServerSocket).为了连接两个Android设备,一个设备必须打开一个ServerSocket的服务。当一个远程的蓝牙设备发一个连接请求与这个打开ServerSocket设备,如果接受请求将返回 BluetoothServerSocket 将返回一个 BluetoothSocke t的实例。
BluetoothClass
描述一个通用的蓝牙设备。这是一个定义了设备主要功能、次要功能和它的服务的只读属性集合。但是这并不影响描述蓝牙的概况和服务。
BluetoothProfile
一个接口:它代表了一个蓝牙的简介。一个蓝牙简介是一个基于两个蓝牙设备通信的无线接口说明。
BluetoothHeadset
提供一个蓝牙耳机的支持。
BluetoothA2dp
BluetoothProfile.ServiceListener
BluetoothProfile
IPC clients when they have been connected to or disconnected from the service (that is, the internal service that runs a particular profile).
in order to use Bluetooth features in your application, you need to declare at least one of two Bluetooth permissions:
BLUETOOTH
and
BLUETOOTH_ADMIN
.
为了在你的程序里能使用蓝牙特性,你需要声明至少一个或两个蓝牙Permissions-------------->BLUETHOOTH and BLUETOOTH_ADMIN
You must request the
BLUETOOTH_ADMIN
permission in order to initiate device discovery or manipulate Bluetooth settings. 为了实例化一个device 搜索 或者操控蓝牙设置,就得有BLUETHOOTH_ADMIN 这个 Permission.You must request the
BLUETOOTH
permission in order to perform any Bluetooth communication, such as requesting a connection, accepting a connection, and transferring data. 为了执行蓝牙通信比如:请求一个连接、接受一个连接及传输数据,就得有 BLUETOOTH 这个 Permission.例如 :
<manifest ... > <uses-permission android:name="android.permission.BLUETOOTH" /> ...</manifest>
Setting Up Bluetooth
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
.
如果你的机器不支持蓝牙,这个时候就不用再考虑蓝牙这个问题了。如果你的机器支持蓝牙但是不能用,这个时候你可请求使用蓝牙。你无需离开程序,通过使用BluetoothAdapter这个类两步就搞定了。
1、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.
对于任务Bluetooth activity都是必须的。通过静态方法 getDefaultAdapter() 方法就可以得到一个你自己设备的蓝牙适配器。整个系统有一个蓝牙适配器就可以用这个对象进行沟通。
For example:
// Get local Bluetooth adapter 得到本机的蓝牙适配器
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// If the adapter is null, then Bluetooth is not supported 如果为空,就是不支持蓝牙设备
if (mBluetoothAdapter == null) {
Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
finish();
return;
}
2、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).
接下来,你需要确定蓝牙是可以用的。使用isEnabled() 方法去检查当前蓝牙设备是否可用,如果这个方法返回 false 蓝牙不可用。去请求开启蓝牙设备。To request that Bluetooth be enabled.通过系统发出一个请求去开启蓝牙(不用停止你的的应用程序)
for example:
//开始显示在屏目上,可以onStop()重新回到onStart() 可以参看Activity的生命周期
@Override
protected void onStart() {
super.onStart();
if(D) Log.e(TAG, "++ 开始蓝牙设备 (ON START) ++");
if(!mBluetoothAdapter.isEnabled()){
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent,REQUEST_ENABLE_BT);
}else {
if(mChatService == null) setupChat();
}
}
使用BluetoothAdapter类,你能够在Android设备上查找周边的蓝牙设备然后配对(绑定),蓝牙通讯是基于唯一地址MAC来相互传输的,考虑到安全问题Bluetooth通讯时需要先配对。然后开始相互连接,连接后设备将会共享同一个RFCOMM通道以便相互传输数据,目前这些实现在Android 2.0或更高版本SDK上实现。
一、查找发现 findding/discovering devices
对于Android查找发现蓝牙设备使用BluetoothAdapter类的startDiscovery()方法就可以执行一个异步方式获取周边的蓝牙设备,因为是一个异步的方法所以我们不需要考虑线程被阻塞问题,整个过程大约需要12秒时间,这时我们紧接着注册一个BroadcastReceiver 对象来接收查找到的蓝牙设备信息,我们过滤ACTION_FOUND这个 Intent动作来获取每个远程设备的详细信息,通过附加参数在Intent字段EXTRA_DEVICE 和 EXTRA_CLASS, 中包含了每个BluetoothDevice 对象和对象的该设备类型 BluetoothClass ,示例代码
01 | private final BroadcastReceiver cwjReceiver = new BroadcastReceiver() { |
02 | public void onReceive(Context context, Intent intent) { |
03 | String action = intent.getAction(); |
04 | if (BluetoothDevice.ACTION_FOUND.equals(action)) { |
05 | BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); |
06 | myArrayAdapter.add(device.getName() + " " + device.getAddress()); //获取设备名称和mac地址 |
07 | } |
08 | } |
09 | }; |
10 | // 注册这个 BroadcastReceiver |
11 | IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); |
12 | registerReceiver(cwjReceiver, filter); |
最后提醒大家需要注意的是,记住在Service或Activity中重写onDestory()方法,使用unregisterReceiver方法反注册这个BroadcastReceiver对象保证资源被正确回收。
一些其他的状态变化有 ACTION_SCAN_MODE_CHANGED 额外参数 EXTRA_SCAN_MODE 和 EXTRA_PREVIOUS_SCAN_MODE以及SCAN_MODE_CONNECTABLE_DISCOVERABLE、SCAN_MODE_CONNECTABLE和SCAN_MODE_NONE,
二、配对绑定 bnded/paired device
在Android中配对一个蓝牙设备可以调用BluetoothAdapter类的getBondedDevices()方法可以获取已经配对的设备,该方法将会返回一个BluetoothDevice数组来区分每个已经配对的设备,示例代码如下:
1 | Set<BluetoothDevice> pairedDevices = cwjBluetoothAdapter.getBondedDevices(); |
2 |
3 | if (pairedDevices.size() > 0 ) //如果获取的结果大于0,则开始逐个解析 |
4 | { |
5 | for (BluetoothDevice device : pairedDevices) { |
6 | myArrayAdapter.add(device.getName() + ":" + device.getAddress()); |
7 | //获取每个设备的名称和MAC地址添加到数组适配器myArrayAdapter中。 |
8 | } |
9 | } |
很多网友不明白如何让自己的手机被其他蓝牙设备发现如何设置,下面我们就一起来说说
三、允许发现 enabling discoverability
如果需要用户确认操作,不需要获取底层蓝牙服务实例,可以通过一个Intent来传递ACTION_REQUEST_DISCOVERABLE参数
, 这里通过startActivityForResult来强制获取一个结果,重写startActivityForResult()方法获取执行结果,返 回结果有RESULT_OK和RESULT_CANCELLED分别代表开启和取消(失败),当然最简单的方法是直接执行,示例代码如下
1 | Intent cwjIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); |
2 | cwjIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300 ); |
3 | startActivity(cwjIntent); |
接下来系统会提示用户是否允许,对话框如下
从Android 2.0开始提供最全面的蓝牙开发接口,API Level为5的系统才能调用,目前Android Bluetooth API包含了主要以下几类:BluetoothAdapter
BluetoothDevice、BluetoothSocket 、BluetoothServerSocket 和BluetoothClass 它们均在android.bluetooth这个包中出现。
我们调用时除了需要考虑API Level至少为5外,还需注意添加相应的权限,比如使用通讯需要在androidmanifest.xml加入<uses-permission android:name="android.permission.BLUETOOTH" />,而开关蓝牙需要android.permission.BLUETOOTH_ADMIN权限。
三、建立通讯 establishing
对于建立一个蓝牙通讯,必须经过以下四个步骤:获取本地蓝牙设备、查找远程设备、配对(已配对设备将会忽略这步的细节)、连接设备和传输数据.
在Android平台中首先我们需要查找本地活动的蓝牙适配器,通过BluetoothAdapter类的getDefaultAdapter() 方法获得一个系统默认可用的蓝牙设备,示例代码如下
1 | BluetoothAdapter cwjBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); |
2 | if (cwjBluetoothAdapter == null ) { |
3 | // Android开发网提示大家本机没有找到蓝牙硬件或驱动存在问题 |
4 | } |
当然有了这步仍然不能建立连接,因为我们还不知道手机中的蓝牙功能是否被开启,可以通过cwjBluetoothAdapter的.isEnabled方法来判断,如果没有开启,我们可以通过下面的代码提醒用户启用:
1 | if (!cwjBluetoothAdapter.isEnabled()) { |
2 | Intent TurnOnBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); |
3 | startActivityForResult(TurnOnBtIntent, REQUEST_ENABLE_BT); |
4 | } |
这时用户会收到类似下面的窗口:
我们通过startActivityForResult()方法发起的Intent将会在onActivityResult()回调方法中获取用户的选 择,比如用户单击了Yes开启,那么将会收到RESULT_OK 的结果,如果RESULT_CANCELED则代表用户不愿意开启蓝牙,当然android123提醒大家还可以通过其他方式来开启,比如说用 BluetoothDevice获取蓝牙服务接口对象,是用enable()方法来开启,无需询问用户,这时就需要用到 android.permission.BLUETOOTH_ADMIN权限。
如何判断系统蓝牙的状态呢? 建立BroadcastReceiver对象,接收ACTION_STATE_CHANGED动作,在EXTRA_STATE和 EXTRA_PREVIOUS_STATE包含了现在状态和过去的状态,最终的结果定义是STATE_TURNING_ON正在开启, STATE_ON已经开启, STATE_TURNING_OFF正在关闭和 STATE_OFF已经关闭,如果有什么不明白的可以在我们的论坛中交流。