题引:
最近项目上涉及与硬件相关的功能,需要通过蓝牙进行消息收发。项目已完成,这里做下记录。
通信步骤:
初始化BluetoothAdapter.getDefaultAdapter()获取BluetoothAdapter对象
2.判断蓝牙是否开启bluetoothAdapter.isEnabled()
3.未开启,进行开启操作bluetoothAdapter.enable();有返回值,为true证明开启成功
4.注册蓝牙开关广播 BluetoothAdapter.ACTION_STATE_CHANGED 监听开关等状态
5.搜索蓝牙设备 bluetoothAdapter.startDiscovery();
6.点击对配,需要判断是是否有过配对,有则连接;无则配对
7.依据广播状态改变文字描述BluetoothDevice.ACTION_BOND_STATE_CHANGED
8.配对成功,自动连接需要开子线程device.getClass().getMethod("createRfcommSocket", new Class[]{int.class}).invoke(device, 1);
9.监听连接广播,成功开启子线程接收数据,失败点击重连
10.开启子线程发送消息
1.开启或关闭蓝牙
1通过BluetoothAdapter.getDefaultAdapter();拿到蓝牙适配器,其中isEnabled()可直接返回当前蓝牙状态。
public boolean getBluetoothSwitchState() { if (bluetoothAdapter != null) { return bluetoothAdapter.isEnabled(); } return false; }
2返回为false时,蓝牙处于关闭状态。通过bluetoothAdapter.enable();方法打开蓝牙,同样,bluetoothAdapter.disable();方法可关闭蓝牙。这两个方法均有返回值,可通过返回值判断是否开启成功!
public boolean startBlueTooth() { if (bluetoothAdapter == null) { return false; } return bluetoothAdapter.enable(); } public void closeBlueToothDevice() { if (bluetoothAdapter == null) { return; } bluetoothAdapter.disable(); }
3 注意:用户可将程序挂起,从设置页或下拉状态栏进行打开关闭蓝牙。如蓝牙关闭,此时APP需要通过广播进行监听,关闭则提示用户打开蓝牙,或退出程序。我讲所需要的广播先都提前写出!
receiver = new BluetoothReceiver();IntentFilter filter = new IntentFilter();filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); //监听蓝牙关闭和打开状态filter.addAction(BluetoothDevice.ACTION_FOUND); //搜索发现设备filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); //搜索完毕filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); //配对状态filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);//蓝牙连接成功filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); //蓝牙连接失败context.registerReceiver(receiver, filter);
2. 设备搜索
1 蓝牙开启后,自动进行设备搜索
public void searchBluetooth() { if (bluetoothAdapter == null) { return; } bluetoothAdapter.startDiscovery();}
2广播监听搜索到的设备,进行列表展示(单个设备引入第二个重要类BluetoothDevice)
注意:搜索到设备可能存在空值,或重复搜索。需要自己在adpter或list中筛选。
3蓝牙搜索会后自动停止,对应停止广播BluetoothAdapter.ACTION_DISCOVERY_FINISHED:可在停止后进行配对,若没有扫描到对应设备则再次进行重新搜索
3.蓝牙配对
1蓝牙连接分配对与连接两个过程,如果未配对,则必须先进行配对,如果之前配对成功,并且没有取消配对,可直接进行连接;有三个参数,可判断对应设备与当前设备之间的关联
2 假设之前配对成功,该设备device.getBondState()为BOND_BONDED,以此来判断是否配对
public boolean isPaired(BluetoothDevice device) { if (device.getBondState() == BluetoothDevice.BOND_BONDED) { return true; } return false;}
3.1配过对直接连接,当前写未配对情况。配对代码:
public void pairBluetoothDevice(BluetoothDevice device) { try { Method method = BluetoothDevice.class.getMethod("createBond"); method.invoke(device); } catch (Exception e) { LogUtils.error("pairBluetoothDeviceException : {}", e.getMessage()); }}
3.2 既然可以配对,当前可取消配对,将取消配对代码也给出:需要先判断下,之前是否配对成功,条件同3.2;
public void canlePairBluetoothDevice(BluetoothDevice device) { try { Method method = BluetoothDevice.class.getMethod("removeBond"); method.invoke(device); } catch (Exception e) { LogUtils.error("canlePairBluetoothDeviceException : {}", e.getMessage()); } }
3.4 配对状态通过广播监听,监听后,改变状态展示给用户
5 参照系统蓝牙配对成功后需要自己连接设备。失败则刷新adapter,更新至最新状态等待用户下一步操作。
4.蓝牙连接
1蓝牙连接代码:(需要在子线程中操作)
public void connBluetoothDevice(BluetoothDevice device) { new Thread() { @Override public void run() { super.run(); try { mBluetoothSocket = (BluetoothSocket) device.getClass().getMethod("createRfcommSocket", new Class[]{int.class}).invoke(device, 1); if (mBluetoothSocket != null) { if (!mBluetoothSocket.isConnected()) {mBluetoothSocket.connect(); } } } catch (Exception e) { LogUtils.error("connectException:{}", e.getMessage()); mBluetoothSocket = null; } } }.start(); }
2连接成功或失败在广播中进行监听
3成功,需要开启子线程进行数据接收操作,失败,自行处理;
public void reviceMsg(Consumer consumer) { if (mBluetoothSocket == null) { LogUtils.error("reviceMsg socket is null"); return; } new Thread() { @Override public void run() { super.run(); while (true) { char [] buffer = new char[1024]; try { InputStream is = mBluetoothSocket.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(is, "GBK"); int read = inputStreamReader.read(buffer); String readStr = new String(buffer, 0, read); LogUtils.info("reviceMsg:Msg ={};",readStr); consumer.accept(readStr);// is.close();// bluetoothSocket.close(); } catch (Exception e) { LogUtils.error("reviceMsgException: {}", e.getMessage()); } } } }.start(); }
4.4 同理,连接成功也需要像对应设备发送消息,代码如下:
public void sendMsg(int msg) { if (mBluetoothSocket == null) { LogUtils.error("sendMsg socket is null"); return; } new Thread() { @Override public void run() { super.run(); try { byte[] buffer = Integer.toHexString(msg).getBytes(); OutputStream outputStream = mBluetoothSocket.getOutputStream(); outputStream.write(buffer); outputStream.flush(); LogUtils.info("sendMsg msg = {}",Integer.toHexString(msg)); } catch (Exception e) { LogUtils.error("sendMsgException : {}", e.getMessage()); } } }.start(); }
5.后记
至此,蓝牙通信功能基本实现,其中需要在清单文件配置权限,在此给出;目前还不知道怎么网CSDN放自己的代码类,回头知道了进行补齐!
6.补充
上面蓝牙开启时会弹出一个询问是否想要开启蓝牙,如果选择拒接是没有回调的。处理不友好,查阅资料发现有个带回调的开启蓝牙方法贴出:
public void startBlueToothCallBack(Activity activity){ if (bluetoothAdapter == null) { return; } if (!bluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); activity.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); } }
在onActivityResult中进行回调操作:
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == BluetoothUtils.getInstance().REQUEST_ENABLE_BT && resultCode == RESULT_OK) { //蓝牙已开启 searchBluetooth(); } else { finish(); } }
来源地址:https://blog.csdn.net/a1436237789/article/details/129180813