PC端实现蓝牙开发
蓝牙作为一种短距离无线通讯技术,越来越融合到我们的生活当中,软件开发也是随处可见。本文介绍的是PC端与其他蓝牙设备建立通讯的一个案例。
蓝牙客户端,即是请求连接的一端,搜索会发现可连接的蓝牙设备名称。
蓝牙服务端,提供服务的一端。往往生活中使用到的蓝牙(比如手机是个双重角色),又是客户端又是服务端。
蓝牙通信的原理
蓝牙技术规定每一对设备之间进行蓝牙通讯时,必须一个为主角色,另一为从角色,才能进行通信,通信时,必须由主端进行查找,发起配对,建链成功后,双方即可收发数据。蓝牙主端设备发起呼叫,首先是查找,找出周围处于可被查找的蓝牙设备。主端设备找到从端蓝牙设备后,与从端蓝牙设备进行配对,此时需要输入从端设备的PIN码,也有设备不需要输入PIN码。
一、jar包
首先,在PC端实现蓝牙java并没有提供官方jar包,本文使用的是一个第三方库。需要手动导入到maven仓库,
不会导仓库的请参考https://www.cnblogs.com/zeussbook/p/9930679.htm。
第三方jar包下载地址:https://sourceforge.net/projects/bluecove/files/BlueCove/2.1.0/bluecove-2.1.0.jar/download
二、代码部分
2.1蓝牙服务端
package com.shunyutong.test.bluetooth;
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;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @Auther: lanhaifeng
* @Date: 2020/5/4 0004 16:28
* @Description: 蓝牙服务端
* @statement:
*/
public class BluetoothServer implements Runnable{
//本机蓝牙设备
private LocalDevice local = null;
// 流连接
private StreamConnection streamConnection = null;
// 输入流
private InputStream inputStream;
private OutputStream outputStream;
//接入通知
private StreamConnectionNotifier notifier;
//基于缓存的线程池
private final static ExecutorService service = Executors.newCachedThreadPool();
public String serverName;
public String serverUUID;
private OnServerListener mServerListener;
/**
* 服务监听接口
*/
public interface OnServerListener {
void onConnected(InputStream inputStream, OutputStream outputStream);
void onDisconnected();
void onClose();
}
/**
* 蓝牙服务有参构造函数
* @param serverUUID id
* @param serverName 名称
*/
public BluetoothServer(String serverUUID, String serverName) {
this.serverUUID = serverUUID;
this.serverName = serverName;
}
/**
* 启动
*/
public void start() {
try {
local = LocalDevice.getLocalDevice();
if (!local.setDiscoverable(DiscoveryAgent.GIAC))
System.out.println("请将蓝牙设置为可被发现");
//作为服务端,被请求
String url = "btspp://localhost:" + serverUUID+ ";name="+serverName;
notifier = (StreamConnectionNotifier) Connector.open(url);
service.submit(this);
} catch (IOException e) {
System.out.println(e.getMessage());;
}
}
/**
* 重写run()
*/
@Override
public void run() {
try {
streamConnection = notifier.acceptAndOpen(); //阻塞的,等待设备连接
inputStream = streamConnection.openInputStream();
outputStream = streamConnection.openOutputStream();
if (mServerListener != null) {
mServerListener.onConnected(inputStream, outputStream);
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
public OnServerListener getServerListener() {
return mServerListener;
}
public void setServerListener(OnServerListener mServerListener) {
this.mServerListener = mServerListener;
}
}2.2蓝牙客户端
package com.shunyutong.test.bluetooth;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.Set;
import javax.bluetooth.RemoteDevice;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
/**
* @Auther: lanhaifeng
* @Date: 2020/5/4 0004 15:37
* @Description:蓝牙客户端类
* @statement:
*/
public class BluetoothClient {
private StreamConnection streamConnection;//流连接
private OnDiscoverListener onDiscoverListener = null;//发现监听
private OnClientListener onClientListener = null;//客户端监听
/**
* 客户端监听
*/
public interface OnClientListener {
void onConnected(InputStream 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 {
//附近所有的蓝牙设备,必须先执行 runDiscovery
Set<RemoteDevice> devicesDiscovered = RemoteDeviceDiscovery.getDevices();
Iterator<RemoteDevice> itr = devicesDiscovered.iterator();
//连接
while (itr.hasNext()) {
RemoteDevice remoteDevice = itr.next();
onDiscoverListener.onDiscover(remoteDevice);
}
}
/**
* 启动连接
* @param remoteDevice
* @param serviceUUID
* @throws IOException
* @throws InterruptedException
*/
public void startClient(RemoteDevice remoteDevice, String serviceUUID) throws IOException, InterruptedException {
String url = RemoteDeviceDiscovery.searchService(remoteDevice, serviceUUID);
streamConnection = (StreamConnection) Connector.open(url);
if (this.onClientListener != null) {
this.onClientListener.onConnected(streamConnection.openInputStream(), streamConnection.openOutputStream());
}
}
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;
}
}2.3设备查找类
package com.shunyutong.test.bluetooth;
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;
/**
* @Auther: lanhaifeng
* @Date: 2020/5/4 0004 16:07
* @Description:设备查找类
* @statement:
*/
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
*/
@Override
public void deviceDiscovered(RemoteDevice remoteDevice, DeviceClass deviceClass) {
devicesDiscovered.add(remoteDevice);
try {
System.out.println("#发现设备" + remoteDevice.getFriendlyName(false));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 发现服务
* @param transID id
* @param servRecord 服务记录
*/
@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");
}
/**
* 服务搜索已完成
* @param arg0
* @param arg1
*/
@Override
public 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 "";
}
}
}2.4蓝牙服务端使用
package com.shunyutong.test.bluetoothService;
import com.shunyutong.test.bluetooth.BluetoothServer;
import java.io.InputStream;
import java.io.OutputStream;
/**
* @Auther: lanhaifeng
* @Date: 2020/5/4 0004 16:47
* @Description: 蓝牙服务端通信业务
* @statement:
*/
public class BluetoothServerService {
public static void main(String[] argv) {
final String serverName = "Bluetooth Server Test";
final String serverUUID = "1000110100001000800000805F9B34FB"; //根据需要自定义
BluetoothServer server = new BluetoothServer(serverUUID, serverName);
server.setServerListener(new BluetoothServer.OnServerListener() {
@Override
public void onConnected(InputStream inputStream, OutputStream outputStream) {
System.out.printf("Connected");
//添加通信代码
System.out.println(server.serverName);
System.out.println(server.serverUUID);
}
@Override
public void onDisconnected() {
}
@Override
public void onClose() {
}
});
server.start();
}
}2.5蓝牙客户端使用
package com.shunyutong.test.bluetoothService;
import com.shunyutong.test.bluetooth.BluetoothClient;
import javax.bluetooth.RemoteDevice;
import javax.microedition.io.ConnectionNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Vector;
/**
* @Auther: lanhaifeng
* @Date: 2020/5/4 0004 16:51
* @Description: 蓝牙客户端业务类
* @statement:
*/
public class BluetoothClientService {
public static void main(String[] argv) {
final String serverUUID = "1000110100001000800000805F9B34FB"; //需要与服务端相同
BluetoothClient client = new BluetoothClient();
Vector<RemoteDevice> remoteDevices = new Vector<>();
client.setOnDiscoverListener(new BluetoothClient.OnDiscoverListener() {
@Override
public void onDiscover(RemoteDevice remoteDevice) {
remoteDevices.add(remoteDevice);
}
});
client.setClientListener(new BluetoothClient.OnClientListener() {
@Override
public void onConnected(InputStream inputStream, OutputStream outputStream) {
System.out.printf("Connected");
//添加通信代码
}
@Override
public void onConnectionFailed() {
System.out.printf("Connection failed");
}
@Override
public void onDisconnected() {
}
@Override
public void onClose() {
}
});
try {
client.find();
if (remoteDevices.size() > 0 ) {
client.startClient(remoteDevices.firstElement(), serverUUID);
}
}catch (InterruptedException e) {
e.printStackTrace();
}catch (ConnectionNotFoundException e){
System.out.println("当前蓝牙不在线");
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
}
}测试效果

相关推荐
80296330 2020-09-15
SeetyST 2020-08-13
张俊杰 2020-08-02
浅梦墨汐 2020-07-28
北落不吉 2020-06-27
棋牌游戏开发 2020-06-11
greenpepper 2020-06-11
greenpepper 2020-06-13
seek 2020-06-10
dotstar 2020-06-02
hushijiao 2020-05-17
浅梦墨汐 2020-05-12
chinaycheng 2020-05-06
sixforone 2020-05-06
greenpepper 2020-04-29
greenpepper 2020-04-22
海豚的成长日记 2020-01-12
海豚的成长日记 2020-01-11