Android 蓝牙连接
一、概述
蓝牙是一种无线技术标准,可实现固定设备、移动设备和楼宇个人域网之间的短距离数据交换。最多可以同时和7个其它蓝牙设备建立连接,进行通信。蓝牙可分为两大类:传统蓝牙(蓝牙3.0规范之前),低功耗蓝牙(蓝牙4.0规范之后)。
Android 从4.3版本(API Level 18)开始支持低功耗蓝牙Bluetooth Low Energy(BLE)通信。Android提供了相应的 API, 应用程序通过这些 API 可以实现 蓝牙设备扫描、配对、连接、传输数据等功能。
二、Android BLE API几个重要类
1、BluetoothAdapter
本地的蓝牙适配器。是所有蓝牙交互操作的入口点。通过这个类可以发现其他蓝牙设备,查询已配对的设备列表,使用一个已知的MAC地址来实例化一个BluetoothDevice,以及创建一个BluetoothServerSocket来为监听与其他设备的通信。
2、BluetoothDevice
远程蓝牙设备。使用这个类来请求一个与远程设备的BluetoothSocket连接,或者查询关于设备名称、地址、类和连接状态等设备信息。
3、BluetoothSocket
代表一个蓝牙socket的接口(和TCP Socket类似)。这是一个连接点,它允许一个应用与其他蓝牙设备通过InputStream和OutputStream交换数据。
4、BluetoothServerSocket
代表一个开放的服务器socket,它监听接受的请求(与TCP ServerSocket类似)。为了连接两台Android设备,一个设备必须使用这个类开启一个服务器socket。当一个远程蓝牙设备开始一个和该设备的连接请求,BluetoothServerSocket将会返回一个已连接的BluetoothSocket,接受该连接。
三、蓝牙开发
1、流程
2、开启权限
//开启蓝牙时,mBluetoothAdapter.enable()需要以下权限
3、开启蓝牙
public void isBluetoothEnable() { //获取蓝牙适配器mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();if (mBluetoothAdapter != null){// 蓝牙已打开if (mBluetoothAdapter.isEnabled()){}else{//未打开则开启,此处可以通过弹框提示来提示用户开启 mBluetoothAdapter.enable() } }}
4、搜索附近蓝牙设备
/** * 注册搜索蓝牙设备的广播 */private void startDiscovery() { IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(receiver, filter); IntentFilter filter1 = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); registerReceiver(receiver, filter1); startScanBluetooth();}private void startScanBluetooth() { // 判断是否在搜索,如果在搜索,就取消搜索 if (bluetoothAdapter.isDiscovering()) { bluetoothAdapter.cancelDiscovery(); } // 开始搜索 bluetoothAdapter.startDiscovery();}/** * 蓝牙广播接收 */private final BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); //蓝牙rssi参数,代表蓝牙强度 short rssi = intent.getExtras().getShort(BluetoothDevice.EXTRA_RSSI); //蓝牙设备名称 String name = device.getName(); //蓝牙设备连接状态 int status = device.getBondState(); ... } else if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) { ... } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { Toast.makeText(context, "蓝牙设备搜索完成", Toast.LENGTH_SHORT).show(); } }};
关于蓝牙连接状态:
BluetoothDevice.BOND_BONDED:已配对
BluetoothDevice.BOND_BONDING:配对中
BluetoothDevice.BOND_NONE:未配对或取消配对
关于蓝牙强度rssi:
单位是dbm,蓝牙信号的强度RSSI = 10*log P,P代表接收到的信号功率。蓝牙会发送广播,距离大小会影响信号功率强弱。假设发射功率取最大值为1mw,那么RSSI的值为0,也就是说你的距离离蓝牙最近时在理想状态下所获取的RSSI的值为0,但在实际中基本不会存在这个理想状态,因此RSSI的值基本都为负数。
一般说来,在BLE中,假设信号强度按强、中、弱、差4个等级划分,rssi范围依次是:-60 ~ 0 、-70 ~ -60、-80 ~ -70、<-80。
5、配对
//获取已配对设备信息public List getPairedBluetoothDevices() {List deviceList = new ArrayList<>();Set pairedDevices = mBluetoothAdapter.getBondedDevices();if (pairedDevices.size() > 0) {for (BluetoothDevice device : pairedDevices) {deviceList.add(device);}}return deviceList;}
//若已配对设备数为0,跳转到手机系统蓝牙设置界面Intent enableBtIntent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);mContext.startActivity(enableBtIntent);
//手动配对,完成配对后重新扫描即可Method method = BluetoothDevice.class.getMethod("createBond");method.invoke(itemlist.get(position).getDevice());
6、连接
蓝牙连接需要在子线程中完成
public class BluetoothConnectThread extends Thread { private static final UUID BluetoothUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); BluetoothSocket bluetoothSocket; BluetoothDevice bluetoothDevice; private boolean connected = false; private Object lock = new Object(); //蓝牙连接回调接口 private BluetoothConnectCallback connectCallback; public BluetoothConnectThread(BluetoothDevice device, BluetoothConnectCallback callback) { try { bluetoothDevice = device; bluetoothSocket = bluetoothDevice.createInsecureRfcommSocketToServiceRecord(BluetoothUUID); connectCallback = callback; } catch (Exception e) { e.printStackTrace(); } } @Override public void run() { if (bluetoothSocket != null) { if (connected) { cancel2(); connected = false; } } new Thread() { @Override public void run() { connect(); if (connected) { if (connectCallback != null){ connectCallback.connectSuccess(bluetoothSocket); } } } }.start(); } public void connect() { try { synchronized (lock) { bluetoothSocket.connect(); connected = true; } } catch (Exception connectException) { connectException.printStackTrace(); cancel(); try { Method m; m = bluetoothDevice.getClass().getMethod("createRfcommSocket", new Class[]{int.class}); bluetoothSocket = (BluetoothSocket) m.invoke(bluetoothDevice, Integer.valueOf(1)); bluetoothSocket.connect(); connected = true; } catch (Exception ex) { ex.printStackTrace(); if (connectCallback != null){ connectCallback.connectFailed(ex.getMessage()); } } } } public void cancel() { try { synchronized (lock) { if (connected) { bluetoothSocket.close(); connected = false; } } } catch (IOException e) { } } public void cancel2() { try { synchronized (lock) { bluetoothSocket.close(); connected = false; } } catch (IOException e) { } }}
public interface BluetoothConnectCallback { void connectSuccess(BluetoothSocket socket); void connectFailed(String errorMsg); void connectCancel();}
注意以上,BluetoothUUID一般为固定的,connect()放在子线程中可以提高连接成功率(不明所以),注意connect失败需要通过反射createRfcommSocket该方法完成,自验目前连接成功率较高。
7、传输数据
//获取BluetoothSocket输出流OutputStream outputStream = bluesocket.getOutputStream();//之后将数据写入输出流完成传输outputStream.write(data);outputStream.flush();
更多相关文章
- Android设备连接Unity Profiler性能分析器
- [Android] ubuntu 下不识别 Android 设备
- Android系统移植与调试之------->如何修改Android设备存储盘符名
- [转载] 解决AndroidStudio连不上Android设备真机的问题
- [置顶] Android系统移植与调试之------->如何修改Android设备存
- Android6.0修改设备设置中kernel信息
- 查看当前android设备api版本
- Android设备抓包命令
- Android 实现蓝牙打印的功能