基于蓝牙适配器的PC与Android端通讯 迷南。 2022-05-21 11:25 385阅读 0赞 # Demo # 首先,直接给[Demo][],对于只想使用的朋友,直接下载使用即可。Demo其实也是从网上爬来的,之后做了各种调试和修改。 原有Demo代码下载,可见[地址][Link 1]。 修改后Demo效果如下。效果不太清晰,见谅。 (1)PC端 ![70][] (2)Android端 ![70 1][] # 细节实现 # ## Android端 ## android端做为客户端要与PC通讯,需要完成以下几步。 ### 添加蓝牙权限 ### <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> ### 注册广播接收器 ### 个人认为该步骤可选。但最好存在。 原因在于,虽然蓝牙适配器可以获取周围蓝牙设备的列表,但对于周围蓝牙设备的扫描比较耗时。 返回蓝牙设备列表时,可能仍处于搜索过程中。 当扫描完成时,广播接收器将受到action为ACTION\_DISCOVERY\_FINISHED的广播。此时,获取设备列表,将比较全面。 建议接收器监听,以下三个action。 IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(BluetoothDevice.ACTION_FOUND);//发现设备 intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//扫描完毕 intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);//扫描结束 registerReceiver(broadcastReceiver, intentFilter); ### 开启蓝牙 ### if (!bluetoothAdapter.isEnabled()) { bluetoothAdapter.enable(); } 开启适配器后,android将开始遍历周围可以被访问的蓝牙设备。该动作将触发广播。 当然,也可以通过触发bluetoothAdapter.startDiscovery()重新扫描。 ### 选定目标蓝牙设备 ### 由适配器获取设备列表,并根据PC的bluetooth MAC地址,选定目标蓝牙设备。SERVICE\_ADDRESS为PC端蓝牙mac地址,格式为XX:XX:XX:XX:XX:XX Set<BluetoothDevice> mySet = bluetoothAdapter.getBondedDevices(); for (BluetoothDevice device : mySet) { if (device.getAddress().equalsIgnoreCase(SERVICE_ADDRESS) ) { service = device; break; } } ### 创建RfcommSocket并建立连接 ### private static final String serverUUID = "00001101-0000-1000-8000-00805F9B34FB" private BluetoothSocket bluetoothSocket; bluetoothSocket = service.createRfcommSocketToServiceRecord(UUID.fromString(serverUUID)); bluetoothSocket.connect(); 这里需要说明的有两点。 1.连接操作比较耗时,视具体设备不同。所以,需要将连接操作放到子线程中完成。 2.在Android端,需要使用UUID,完成与其他蓝牙设备的连接。关于UUID,之后小结会提到。 ### 收发数据 ### 收发数据也较为耗时,需要放在子线程实现。 OutputStream outputStream; try { outputStream = bluetoothSocket.getOutputStream(); outputStream.write("A message from android device".getBytes()); showMessage("Successfully send message"); } catch (IOException e) { showMessage(e.getMessage()+", during output"); } InputStream inputStream; try { inputStream = bluetoothSocket.getInputStream(); byte[] buffer = new byte[200]; inputStream.read(buffer); showMessage("Concurrently receive message : " + new String(buffer)); } catch (IOException e) { showMessage(e.getMessage()+", during get input"); } ### 关闭RfcommSocket ### bluetoothSocket.close(); ## PC端 ## ### 设置PC蓝牙设备可见 ### LocalDevice.getLocalDevice().setDiscoverable(DiscoveryAgent.GIAC); ### 创建连接流监听器 ### private StreamConnectionNotifier streamConnectionNotifier; streamConnectionNotifier = (StreamConnectionNotifier) Connector.open("btspp://localhost:" + SERVER_UUID.toString()); 注意,此处使用的UUID,必须与android端的UUID一致。 ### 开启监听 ### StreamConnection streamConnection = null; streamConnection = streamConnectionNotifier.acceptAndOpen(); acceptAndOpen()方法调用后,将进入等待。 ### 获取输入流和输出流 ### while (isListening) { if ((inputStream.available()) <= 0) { Thread.sleep(1000); } System.out.println("message is comming"); outputStream.write("hello android BT".getBytes()); inputStream.read(buffer); String message = new String(buffer); System.out.println("Receive message : " + message); if (message.contains("EXIT_APP")) { System.out.println("Listener closed"); isListening = false; } } ### 关闭连接 ### inputStream.close(); outputStream.close(); streamConnection.close(); ## 问题 ## ### BUG ### java.io.IOException: read failed, socket might closed or timeout, read ret: -1 在连接时,常会遇到该BUG。网上很多方法说,可以通过修改UUID的方式,来FIX该BUG。 但翻看createRfcommSocketToServiceRecord方法的注释,发现该UUID不能随便修改。 * <p>Hint: If you are connecting to a Bluetooth serial board then try * using the well-known SPP UUID 00001101-0000-1000-8000-00805F9B34FB. * However if you are connecting to an Android peer then please generate * your own unique UUID. 因此,若是采用串口通信,必须使用“00001101-0000-1000-8000-00805F9B34FB”。 造成连接失败的另一原因,可能是channel ID的问题。 在创建Socket时,createRfcommSocketToServiceRecord使用UUID作为唯一传参,而默认channel为-1。 网上建议,通过反射使用BluetoothDevice的隐藏public createRfcommSocket方法,利用传参指定的channel值,创建Socket。 ![70 2][] channel的取值范围为1至30. Demo中给出了工具方法。 public BluetoothSocket cretateBluetoothSocketbyChannel(BluetoothDevice Device,int channel,boolean autoForward){ BluetoothSocket socket=null; try { showMessage("Trying fallback on channel "+channel); socket =(BluetoothSocket) Device.getClass().getMethod("createRfcommSocket", new Class[] {int.class}).invoke(Device,channel); socket.connect(); Log.d(TAG,"createRfcommSocket on channel "+channel); showMessage("Successfully connect"); } catch (Exception e) { showMessage(e.getMessage()); if(channel<30){ if(autoForward){ socket=cretateBluetoothSocketbyChannel(Device,channel+1,autoForward); }else { showMessage("Connect Failed"); } } } return socket; } 另外,就该问题,吐槽一下适配器。适配器的性能也是参差不齐。此前摁着绿联的蓝牙适配器,试了3天。同样的代码,问题百出。后来转用奥视通(ost108),几分钟便过了。不管是添加设备时的认证过程的人性化设计,还是设备服务驱动的安装速度,天壤之别~ ### 驱动 ### Demo在实现时,遇到找不到设备的情况。个人感觉是由于适配器所提供的驱动问题造成的。在卸载后,使用通用驱动可以解决该问题。 ![70 3][] ### Bluecove版本 ### 在64位OS下开发,需要使用Bluecove 64bit版本,本Demo使用为64bit。[下载地址][Link 2] # 参考文献 # 在开发过程中,以下文章给予了很多帮助,一并列下。 https://blog.csdn.net/tingfengzheshuo/article/details/45292201 http://royal2xiaose.iteye.com/blog/1420138 https://blog.csdn.net/old\_me\_mory/article/details/18962701 https://blog.csdn.net/peceoqicka/article/details/51979469(着重感谢) # 结语 # 第一次涉及蓝牙项目,耗时较长,且深入不够,若有疏漏,还望提出。 [Demo]: https://download.csdn.net/download/daihuimaozideren/10524308 [Link 1]: https://download.csdn.net/download/peceoqicka/9582062 [70]: /images/20220521/519284e81f0646829be758d14b6f753e.png [70 1]: /images/20220521/cbf8c3a3376b4615a761dfd3b573af12.png [70 2]: /images/20220521/425fe99f4f674bd3a70c0afd3610cc1a.png [70 3]: /images/20220521/a9d0af2de99648e58d92f932c9408e34.png [Link 2]: http://snapshot.bluecove.org/distribution/download/2.1.1-SNAPSHOT/2.1.1-SNAPSHOT.63/
相关 手机和蓝牙通讯实验 手机和蓝牙通讯实验 实验现象 使用android手机控制继电器的开关 理论学习 实验采用BT-HC05蓝牙模块,该模块主从一体,可以软件设置是主机还是从机。 浅浅的花香味﹌/ 2022年12月19日 08:43/ 0 赞/ 197 阅读
相关 PC之间蓝牙互联 1,蓝牙名称确认 默认情况下,蓝牙名称为电脑名称,如果在查找蓝牙设备时发生多个同名名称时,可对蓝牙名称做修改,修改方式有两个, 1,修改电脑名称; 2,修改蓝牙名称, 我就是我/ 2022年12月01日 09:59/ 0 赞/ 191 阅读
相关 android 蓝牙触屏,android开发:与蓝牙的第一次接触 蓝牙开发从无到有: 蓝牙开发分为两种,一种是传统蓝牙开发,耗电量比较大。另一种是android4.3中引入的低功耗蓝牙开发。无论是哪一种,都要从无到有,从少到多的渐进开发。本 深藏阁楼爱情的钟/ 2022年10月05日 12:46/ 0 赞/ 263 阅读
相关 iOS--MultipeerConnectivity蓝牙通讯 iOS–通过MultipeerConnectivity完成蓝牙通讯 iOS蓝牙通讯的三种方式: GameKit.framework:iOS7之前的蓝牙通讯框架 傷城~/ 2022年08月05日 07:52/ 0 赞/ 252 阅读
相关 android 蓝牙客户端与服务端通信 ![Center][] 首先介绍基本类及方法 一,BlueboothAdapter这个就是表示本机,里面几个常用的方法如下。 1,getDefaultAdapt 叁歲伎倆/ 2022年07月14日 08:20/ 0 赞/ 515 阅读
相关 Android Ble蓝牙开发(服务器端) 最近项目里面需要集成一个蓝牙的连接功能,作为一枚刚刚毕业不久的新生,大学几年又白过的。只好在几天内搜搜百度,脑补一下。文章部分内容摘至各大Blog,加上本dust的见解,写了一 妖狐艹你老母/ 2022年06月09日 10:07/ 0 赞/ 617 阅读
相关 Android Ble蓝牙开发(客户端) 最近项目里面需要集成一个蓝牙的连接功能,作为一枚刚刚毕业不久的新生,大学几年又白过的。只好在几天内搜搜百度,脑补一下。文章部分内容摘至各大Blog,加上本dust的见解,写了一 野性酷女/ 2022年06月09日 07:57/ 0 赞/ 606 阅读
相关 基于蓝牙适配器的PC与Android端通讯 Demo 首先,直接给[Demo][],对于只想使用的朋友,直接下载使用即可。Demo其实也是从网上爬来的,之后做了各种调试和修改。 原有Demo代码下载,可见[地址] 迷南。/ 2022年05月21日 11:25/ 0 赞/ 386 阅读
相关 2、初始化蓝牙适配器(wx.openBluetoothAdapter) 官方文档连接:[https://developers.weixin.qq.com/miniprogram/dev/api/wx.openBluetoothAdapter.htm 迷南。/ 2022年02月21日 14:27/ 0 赞/ 759 阅读
还没有评论,来说两句吧...