感谢:(1)PC端蓝牙开发  https://www.cnblogs.com/zeussbook/p/12827479.html

https://blog.csdn.net/svizzera/article/details/77434917

(2)解决数据读取乱序  https://blog.csdn.net/clliu_hust/article/details/80874272

一、蓝牙流程

蓝牙客户端Socket的与Sokcet流程是一样的,只不过参数不同而已。如下:
1、创建客户端蓝牙Sokcet
2、创建连接
3、读写数据
4、关闭

二、导入jar包

需要导入第三方的蓝牙bluecove.jar包。其中32位系统和64位系统所导的包不同,需要区分。否则会报错。BlueCove还需要Apache的commons-io包,这个顺便下就可以的。

PS:如果启动报错:bluecove native library version mismatch,可尝试把commons-io包去掉。

链接:https://pan.baidu.com/s/1tFixZRIRaN4HdlslDlKhuQ 
提取码:rr12

三、代码部分

3.1设备查找类

package com.jcsim;/*** Created with IntelliJ IDEA.** @Author: Jcsim* @Date: 2020/11/25 15:15* @Description:设备查找类*/
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.Vector;import javax.bluetooth.DataElement;
import javax.bluetooth.DeviceClass;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.ServiceRecord;
import javax.bluetooth.UUID;
public class RemoteDeviceDiscovery {public final static Set<RemoteDevice> devicesDiscovered = new HashSet<RemoteDevice>();public final static Vector<String> serviceFound = new Vector<String>();final static Object serviceSearchCompletedEvent = new Object();final static Object inquiryCompletedEvent = new Object();/*** 发现监听*/private static DiscoveryListener listener = new DiscoveryListener() {public void inquiryCompleted(int discType) {System.out.println("#" + "搜索完成");synchronized (inquiryCompletedEvent) {inquiryCompletedEvent.notifyAll();}}/*** 发现设备* @param remoteDevice* @param deviceClass*/@Overridepublic void deviceDiscovered(RemoteDevice remoteDevice, DeviceClass deviceClass) {devicesDiscovered.add(remoteDevice);try {System.out.println("#发现设备" + remoteDevice.getFriendlyName(false)+"   设备地址:"+remoteDevice.getBluetoothAddress());} catch (IOException e) {e.printStackTrace();}}/*** 发现服务* @param transID id* @param servRecord 服务记录*/@Overridepublic void servicesDiscovered(int transID, ServiceRecord[] servRecord) {for (int i = 0; i < servRecord.length; i++) {String url = servRecord[i].getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);if (url == null) {continue;}serviceFound.add(url);DataElement serviceName = servRecord[i].getAttributeValue(0x0100);if (serviceName != null) {System.out.println("service " + serviceName.getValue() + " found " + url);} else {System.out.println("service found " + url);}}System.out.println("#" + "servicesDiscovered");}/*** 服务搜索已完成* @param arg0* @param arg1*/@Overridepublic void serviceSearchCompleted(int arg0, int arg1) {System.out.println("#" + "serviceSearchCompleted");synchronized(serviceSearchCompletedEvent){serviceSearchCompletedEvent.notifyAll();}}};/*** 查找设备* @throws IOException* @throws InterruptedException*/private static void findDevices() throws IOException, InterruptedException {devicesDiscovered.clear();synchronized (inquiryCompletedEvent) {LocalDevice ld = LocalDevice.getLocalDevice();System.out.println("#本机蓝牙名称:" + ld.getFriendlyName());boolean started = LocalDevice.getLocalDevice().getDiscoveryAgent().startInquiry(DiscoveryAgent.GIAC,listener);if (started) {System.out.println("#" + "等待搜索完成...");inquiryCompletedEvent.wait();LocalDevice.getLocalDevice().getDiscoveryAgent().cancelInquiry(listener);System.out.println("#发现设备数量:" + devicesDiscovered.size());}}}/*** 获取设备* @return* @throws IOException* @throws InterruptedException*/public static Set<RemoteDevice> getDevices() throws IOException, InterruptedException {findDevices();return devicesDiscovered;}/*** 查找服务* @param btDevice* @param serviceUUID* @return* @throws IOException* @throws InterruptedException*/public static String searchService(RemoteDevice btDevice, String serviceUUID) throws IOException, InterruptedException {UUID[] searchUuidSet = new UUID[] { new UUID(serviceUUID, false) };int[] attrIDs =  new int[] {0x0100 // Service name};synchronized(serviceSearchCompletedEvent) {System.out.println("search services on " + btDevice.getBluetoothAddress() + " " + btDevice.getFriendlyName(false));LocalDevice.getLocalDevice().getDiscoveryAgent().searchServices(attrIDs, searchUuidSet, btDevice, listener);serviceSearchCompletedEvent.wait();}if (serviceFound.size() > 0) {return serviceFound.elementAt(0);} else {return "";}}
}

3.2蓝牙客户端类

package com.jcsim;/*** Created with IntelliJ IDEA.** @Author: Jcsim* @Date: 2020/11/25 15:14* @Description:蓝牙客户端类*/
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.bluetooth.BluetoothConnectionException;
import javax.bluetooth.RemoteDevice;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
public class BluetoothClient {private StreamConnection streamConnection;//流连接private OnDiscoverListener onDiscoverListener = null;//发现监听private OnClientListener onClientListener = null;//客户端监听/*** 客户端监听*/public interface OnClientListener {void onConnected(DataInputStream inputStream, OutputStream outputStream);void onConnectionFailed();void onDisconnected();void onClose();}/*** 发现监听*/public interface OnDiscoverListener {void onDiscover(RemoteDevice remoteDevice);}/*** 无参构造函数*/public BluetoothClient() {}/*** 查找所有* @throws IOException* @throws InterruptedException*/public void find() throws IOException, InterruptedException {//附近所有的蓝牙设备,必须先执行 runDiscoverySet<RemoteDevice> devicesDiscovered = RemoteDeviceDiscovery.getDevices();Iterator<RemoteDevice> itr = devicesDiscovered.iterator();//连接while (itr.hasNext()) {RemoteDevice remoteDevice = itr.next();onDiscoverListener.onDiscover(remoteDevice);}}/*** 启动连接* @param remoteDevice* @throws IOException* @throws InterruptedException*/public void startClient(RemoteDevice remoteDevice) throws IOException, InterruptedException {
//        String url = RemoteDeviceDiscovery.searchService(remoteDevice, serviceUUID);
//        System.out.println("url=="+url);
//        1 为通道;authenticate=true;encrypt=true表示需要验证pin码
//        btspp://<蓝牙设备地址>:<通道号>String url = "btspp://"+remoteDevice.getBluetoothAddress()+":1;authenticate=true;encrypt=true";try{streamConnection = (StreamConnection) Connector.open(url);if (this.onClientListener != null) {this.onClientListener.onConnected(streamConnection.openDataInputStream(), streamConnection.openOutputStream());}else{System.out.println("请打开蓝牙");}} catch (BluetoothConnectionException e){e.printStackTrace();System.out.println("蓝牙连接错误,请查看蓝牙是否打开。");}catch (Exception e){e.printStackTrace();}}public OnDiscoverListener getOnDiscoverListener() {return onDiscoverListener;}public void setOnDiscoverListener(OnDiscoverListener onDiscoverListener) {this.onDiscoverListener = onDiscoverListener;}public OnClientListener getClientListener() {return onClientListener;}public void setClientListener(OnClientListener onClientListener) {this.onClientListener = onClientListener;}}

3.3 蓝牙客户端业务类

package com.jcsim;/*** Created with IntelliJ IDEA.** @Author: Jcsim* @Date: 2020/11/25 15:17* @Description:蓝牙客户端业务类*/import javax.bluetooth.RemoteDevice;
import javax.microedition.io.ConnectionNotFoundException;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Vector;public class BluetoothClientService {public static void main(String[] argv) {final String serverUUID = "1000110100001000800000805F9B34FB"; //需要与服务端相同BluetoothClient client = new BluetoothClient();Vector<RemoteDevice> remoteDevices = new Vector<>();Boolean isConnect = false;client.setOnDiscoverListener(new BluetoothClient.OnDiscoverListener() {@Overridepublic void onDiscover(RemoteDevice remoteDevice) {remoteDevices.add(remoteDevice);}});client.setClientListener(new BluetoothClient.OnClientListener() {@Overridepublic void onConnected(DataInputStream inputStream, OutputStream outputStream) {System.out.printf("Connected");// 开启线程读写蓝牙上接收和发送的数据。new Thread(new Runnable() {@Overridepublic void run() {try {System.out.println("客户端开始监听...");//                            System.out.println("接收连接");
//                            System.out.println("开始读数据...");SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");while (true) {byte[] buffer = new byte[1024];int bytes=0;int ch;
//                                inputStream.read(buffer)while ((ch = inputStream.read()) != '\n') {// 读数据。
//                                    String s = new String(buffer);
//                                    System.out.println("===========start=============");
//                                    System.out.println(s.trim());
//                                    System.out.println("------------end------------");
//                                    Thread.sleep(1000);if(ch!=-1){buffer[bytes] = (byte) ch;bytes++;}}buffer[bytes] = (byte)'\n';bytes++;String s = new String(buffer);System.out.println("===========start=============");System.out.println(df.format(new Date())+"->"+s.trim());System.out.println("------------end------------");//                                inputStream.close();
//                                onClose();}} catch (Exception e) {e.printStackTrace();}}}).start();}@Overridepublic void onConnectionFailed() {System.out.printf("Connection failed");}@Overridepublic void onDisconnected() {}@Overridepublic void onClose() {}});try {client.find();if (remoteDevices.size() > 0 ) {for(int i=0;i<remoteDevices.size();i++){System.out.println("第"+i+"个地址为:"+remoteDevices.get(i).getBluetoothAddress());if( "所要连接的蓝牙的地址".equals(remoteDevices.get(i).getBluetoothAddress())){isConnect = true;client.startClient(remoteDevices.get(i));break;}}if (!isConnect){System.out.println("请打开传感器蓝牙设备。");}
//                System.out.println("remoteDevices.firstElement="+remoteDevices.firstElement());}else {System.out.println("附件没有蓝牙设备");}} catch (ConnectionNotFoundException e){System.out.println("当前蓝牙不在线");e.printStackTrace();} catch (InterruptedException | IOException e) {e.printStackTrace();}}
}

四、读数据

之前读取数据的时候,一直乱码或乱序(一段字符被分成几段)。

乱码解决方法:蓝牙发送的波特率问题,一般为9600。

乱序:使用InputStream读取时不能和串口一样设置一个结束符(串口的结束符一般是换行符'\r\n'),于是线程读取就很随机性了,你不知道它在什么时候就读完一刀下去,你的字符串就不完整了。

旧方法(乱序):

while (true) {byte[] buffer = new byte[1024];//                                while (inputStream.read(buffer) != -1) {// 读数据。String s = new String(buffer);System.out.println("===========start=============");System.out.println(s.trim());System.out.println("------------end------------");Thread.sleep(1000);}// inputStream.close();
// onClose();
}

乱序解决方法:使用InputStream.read()逐个读取字符,判读是不是结束符,如果没到结束符就一直读取写入

SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");while (true) {byte[] buffer = new byte[1024];int bytes = 0; //字符串长度int ch;  // 读取字符的变量while ((ch = inputStream.read()) != '\n') {// 读数据。if(ch!=-1){buffer[bytes] = (byte) ch; // 将读取到的字符写入bytes++;}}buffer[bytes] = (byte)'\n'; //最后加上一个换行bytes++;String s = new String(buffer);System.out.println("===========start=============");System.out.println(df.format(new Date())+"->"+s.trim());System.out.println("------------end------------");}

五、GitHub地址

https://github.com/jiancong952/bluetooth_java.git

Java:PC端作为客户端连接蓝牙设备并接收蓝牙发送的数据相关推荐

  1. Java PC端微信、支付宝扫码支付(二)

    Java PC端微信.支付宝扫码支付(二) 前几天写了微信支付,附上链接 https://blog.csdn.net/qq_43494610/article/details/90411391 ,今天抽 ...

  2. java实现socket连接,向指定主机指定端口发送socket数据,并获取响应数据

    全栈工程师开发手册 (作者:栾鹏) java教程全解 java实现socket连接,向指定主机指定端口发送socket数据,并获取响应数据 测试代码 public static void main(S ...

  3. java学习(166):socket服务端和客户端连接

    socket服务端 import java.io.IOException; import java.net.ServerSocket; import java.net.Socket;//socket服 ...

  4. Qt TCP服务端和客户端连接

    前言 传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的.可靠的.基于字节流的传输层通信协议. TCP旨在适应支持多网络应用的分层协议层次结构. 连接到 ...

  5. JAVA PC端扫码支付(一)微信支付

    微信支付从配置到开发 一.配置 1.开通公众平台支付功能 商户号 微信支付功能先要申请微信(企业)公众平台,然后开通企业公众平台付功能.下图为微信(企业)公众平台页面,可以看到商户号等信息 微信公众号 ...

  6. JAVA PC端美颜相机

    这是我在蓝杰做的第一个项目:PC端美颜相机.这个小程序的本质就是对一张图像做处理.存储在计算机的图像信息实际上是一个个像素点,不同的像素点有不同的rgb值,修改像素点的rgb值我们就可以将图像处理成我 ...

  7. vue+antd搭建后台管理界面模版(PC端),适配中文、英文、日文 mock数据,开箱即用

    vue+antd搭建后台管理界面模版(PC端) 完整代码下载地址:vue+antd搭建后台管理界面模版(PC端) 技术栈 vue2 + vuex + vue-router + webpack + ES ...

  8. [笨木头FireFly01]入门篇1·最简单的服务端和客户端连接

    最近一直在写游戏,几乎没有来写教程了,打算放慢一下脚步,学学新东西. 那为嘛我要学FireFly呢? 之前我自己写了一个网络游戏,服务端和客户端都自己写,虽然运行起来没什么大碍,但毕竟我对服务端没什么 ...

  9. java使用 Socket 作为客户端连接网络键盘 实操

    项目情境: 有一个第三方的网络键盘(键盘按键连接后会发送指令)配置到项目上,实现键盘按键,发送的指令经服务层接收封装后发送给各个业务线,实现键盘的交互. 解决思路: 因为交互是持久的,键盘操作命令是断 ...

最新文章

  1. 深度卷积生成对抗网络
  2. 599元的智能视频音箱发布,百度准备补贴几个亿?
  3. Java 垃圾回收机制概念梳理
  4. Leetcode 583.两个字符串的删除操作
  5. LINUX之samba服务器的安装与配置(基于redhat 6.3发行版)
  6. 硬件基础知识(13)---模拟电路中大量使用的滤波和隔直LC网络的值计算
  7. Java多线程归纳总结
  8. Custom Components 翻译
  9. 181031每日一句
  10. Halcon标定系列(3):我个人总结的“眼在手外“和“眼在手上”的心得笔记
  11. cmd检查java_如何通过cmd查看java环境
  12. 百度贴吧签到(基于python3)
  13. PING命令结果中的TTL是什么?
  14. prop-types详解
  15. JetBrains全系列破解
  16. sudo apt-get install package时出现E:无法定位软件包
  17. 解决合并单元格筛选时只出现首行的小技巧
  18. 智能车浅谈——抗干扰技术硬件篇
  19. fragment添加失败错误查找
  20. 从概念到底层技术,区块链一站式分析和汇总(附知识图谱)

热门文章

  1. 让你的网站(MAXCMS4_0)按地区、年份、语言生成分页面(已经修正) -
  2. Unity 导航寻路快速上手
  3. kali rtl8812 使用airodump破解wifi密码
  4. ubuntu18.04 (melodic)cartographer安装(详细)
  5. K-近邻算法(KNN) 预测电影类型
  6. python猜一个数猜对为止_python猜数字游戏while
  7. Thinkphp内核高仿拼多多拼团源码 完美运营级商城系统
  8. 高斯消元法求逆矩阵 matlab,高斯消元法求逆矩阵
  9. 什么台灯护眼效果好?适合暑假学习护眼灯推荐
  10. jsp标签jsp:useBean用法