蓝牙设备连接
蓝牙的连接过程
获取
->配对
->连接
权限
首先需要AndroidManifest.xml
文件中添加操作蓝牙的权限。
1 | <uses-permissionandroid:name="android.permission.BLUETOOTH" /> |
允许程序连接到已配对的蓝牙设备。
1 | <uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN" /> |
获取可用蓝牙设备
引包
操作蓝牙主要用到的类 BluetoothAdapter
类,使用时导包
1 | import android.bluetooth.BluetoothAdapter; |
BluetoothAdapter
代表本地设备的蓝牙适配器。
该BluetoothAdapter可以执行基本的蓝牙任务,例如启动设备发现,查询配对的设备列表,使用已知的MAC地址实例化一个BluetoothDevice类,并创建一个BluetoothServerSocket监听来自其他设备的连接请求
获取蓝牙适配器
1 | BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); |
判断蓝牙是否开启 并启动蓝牙
1 | if(!mBluetoothAdapter.isEnabled()){ |
获取本地蓝牙信息和已配对设备
连接中的设备不能在搜索回调中获取
只能在以配对设备中获取
1 | //获取本机蓝牙名称 |
搜索设备
1 | mBluetoothAdapter.startDiscovery(); |
搜索蓝牙设备,该过程是异步的,通过下面注册广播接受者,可以监听是否搜到设备。
1 | IntentFilter filter = new IntentFilter(); |
监听扫描结果
通过广播接收者查看扫描到的蓝牙设备,每扫描到一个设备,系统都会发送此广播(BluetoothDevice.ACTION_FOUNDE
)。
其中参数intent可以获取蓝牙设备BluetoothDevice
。
1 | private BroadcastReceiver mBluetoothReceiver = new BroadcastReceiver(){ |
停止搜索
1 | mBluetoothAdapter.cancelDiscovery(); |
设置蓝牙可见性
有时候扫描不到某设备,这是因为该设备对外不可见或者距离远,需要设备该蓝牙可见,这样该才能被搜索到。
可见时间默认值为120s,最多可设置300。
1 | if (mBluetoothAdapter.isEnabled()) { |
配对
1 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { |
取消配对
1 | static public boolean removeBond(BluetoothDevice btDevice) |
服务端
android 蓝牙之间可以通过SDP协议建立连接进行通信,通信方式类似于平常使用socket。
首先创建BluetoothServerSocket ,BluetoothAdapter中提供了两种创建BluetoothServerSocket 方式,如下图所示为创建安全的RFCOMM Bluetooth socket,该连接是安全的需要进行配对。而通过listenUsingInsecureRfcommWithServiceRecord创建的RFCOMM Bluetooth socket是不安全的,连接时不需要进行配对。
其中的uuid需要服务器端和客户端进行统一。
1 | private class AcceptThread extends Thread { |
客户端
客户端主要用来创建RFCOMM socket,并连接服务端。
先扫描周围的蓝牙设备,如果扫描到指定设备则进行连接。mBlthChatUtil.connect(scanDevice)连接到设备,
连接过程主要在ConnectThread线程中进行,先创建socket,方式有两种,
如下代码中是安全的(createRfcommSocketToServiceRecord)。另一种不安全连接对应的函数是createInsecureRfcommSocketToServiceRecord。
1 | private class ConnectThread extends Thread { |
数据传输
客户端与服务端连接成功后都会调用connected(mmSocket, mmDevice),创建一个ConnectedThread线程()。
该线程主要用来接收和发送数据。客户端和服务端处理方式一样。该线程通过socket获得输入输出流。
1 | private InputStream mmInStream = socket.getInputStream(); |
发送数据
1 | public void write(byte[] buffer) { |
接收数据
线程循环进行接收数据。
1 | public void run() { |