最近看到使用java连接蓝牙设备的博客,想自己动手测试一下,下面是我自己的测试记录,同时分享我踩到的坑;
测试环境:带蓝牙的windows11 64位电脑、IOS、springboot、JDK1.8 、maven、
参考的博客:https://blog.csdn.net/Svizzera/article/details/77434917
①maven坐标(二选一)
<!-适用于64位windows系统->
<dependency>
<groupId>io.ultreia</groupId>
<artifactId>bluecove</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
<!-适用于32位windows系统->
<dependency>
<groupId>net.sf.bluecove</groupId>
<artifactId>bluecove</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
使用64位windows导入32位的坐标,导致报错如下:
Native Library intelbth_x64 not available
Native Library bluecove_x64 not availablejavax.bluetooth.
②开启服务端,供另一设备申请配对连接
前提先将我们的PC端的蓝牙功能开启(手动开关),不然运行代码会报错;
以下代码类似于将我们的电脑作为蓝牙服务端开启,同时提供URL供外界访问,可用另一蓝牙设备配对我们的PC端蓝牙服务器(用于其他设备主动申请配对PC端蓝牙),以流的方式通信并打印字符到控制台,具体我没测试(多开一个笔记本电脑,多搞一份代码,填URL申请连接);
package com.example.springbootquickstart.uitl.buletooth;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.LocalDevice;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.io.StreamConnectionNotifier;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class BluetoothServerTest extends Thread {
//本机蓝牙设备
private LocalDevice local = null;
// 流连接
private static StreamConnection streamConnection = null;
// 接受数据的字节流
private byte[] acceptdByteArray = new byte[1024];
// 输入流
private InputStream inputStream;
private OutputStream outputStream;
//接入通知
private StreamConnectionNotifier notifier;
private boolean stopFlag = false;
public final static String serverName = "Bluetooth Test";
public final static String serverUUID = "1000110100001000800000805F9B34FB";
public BluetoothServerTest() {
try {
local = LocalDevice.getLocalDevice();
if (!local.setDiscoverable(DiscoveryAgent.GIAC))
System.out.println("请将蓝牙设置为可被发现");
/**
* 作为服务端,被请求
*/
String url = "btspp://localhost:" + serverUUID + ";name=" + serverName;
notifier = (StreamConnectionNotifier) Connector.open(url);
} catch (IOException e) {
System.out.println(e.getMessage());
;
}
}
@Override
public void run() {
try {
String inStr = null;
streamConnection = notifier.acceptAndOpen(); //阻塞的,等待设备连接
inputStream = streamConnection.openDataInputStream();
int length;
while (true) {
if ((inputStream.available()) <= 0) { //不阻塞线程
if (stopFlag) //UI停止后,关闭
break;
Thread.sleep(800); //数据间隔比较长,手动堵塞线程
} else {
length = inputStream.read(acceptdByteArray);
if (length > 0) {
inStr = new String(acceptdByteArray, 0, length);
System.out.println(inStr);
}
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
try {
if (inputStream != null)
inputStream.close();
if (streamConnection != null)
streamConnection.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] argv) throws IOException, InterruptedException {
new BluetoothServerTest().start();
}
}
效果图
③发现附近的设备并申请配对
package com.example.springbootquickstart.uitl.buletooth;
import javax.bluetooth.*;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.Vector;
public class RemoteDeviceDiscovery {
public final static Set<RemoteDevice> devicesDiscovered = new HashSet<RemoteDevice>();
// 流连接
private static StreamConnection streamConnection = null;
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();
}
}
/*
* 设别发现
* */
@Override
public void deviceDiscovered(RemoteDevice remoteDevice, DeviceClass deviceClass) {
devicesDiscovered.add(remoteDevice);
try {
System.out.println("#发现设备" + remoteDevice.getFriendlyName(false)+" Address = "+remoteDevice.getBluetoothAddress());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public 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");
}
@Override
public void serviceSearchCompleted(int arg0, int arg1) {
System.out.println("#" + "serviceSearchCompleted");
synchronized (serviceSearchCompletedEvent) {
serviceSearchCompletedEvent.notifyAll();
}
}
};
/*
*发现设备并打印
*/
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());
}
}
}
public static Set<RemoteDevice> getDevices() throws IOException, InterruptedException {
findDevices();
return devicesDiscovered;
}
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 "";
}
}
public static void main(String[] args) throws IOException, InterruptedException {
//发现服务并打印控制台
//findDevices();
//假若已知手机蓝牙地址,直接连接,”:1“指定是蓝牙信道
//streamConnection = (StreamConnection) Connector.open("btspp://" + "9C9234534F7FHD72" + ":1");
//循环连接,已发现的蓝牙设备,连接失败的会抛异常打印到控制台
//电脑和手机靠近一点,多试几次,有可能PC端未能发现手机端的蓝牙
//PC端与手机端的首次连接才会有PIN配对
Set<RemoteDevice> devicesDiscovered = null;
try {
devicesDiscovered = RemoteDeviceDiscovery.getDevices();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
for (RemoteDevice remoteDevice : devicesDiscovered) {
try {
System.out.println("连接"+"btpp://" + remoteDevice.getBluetoothAddress() + ":1");
streamConnection = (StreamConnection) Connector.open("btspp://" + remoteDevice.getBluetoothAddress() + ":1");
} catch (BluetoothConnectionException e) {
e.printStackTrace();
} catch (RuntimeException | IOException e) {
e.printStackTrace();
}
}
}
}
}
发现附近的蓝牙设备,打印控制台
请求连接手机端蓝牙
第一次连接的配对码