zoukankan      html  css  js  c++  java
  • PC端实现蓝牙开发

    蓝牙作为一种短距离无线通讯技术,越来越融合到我们的生活当中,软件开发也是随处可见。本文介绍的是PC端与其他蓝牙设备建立通讯的一个案例。

      蓝牙客户端,即是请求连接的一端,搜索会发现可连接的蓝牙设备名称。

      蓝牙服务端,提供服务的一端。往往生活中使用到的蓝牙(比如手机是个双重角色),又是客户端又是服务端。

    蓝牙通信的原理

      蓝牙技术规定每一对设备之间进行蓝牙通讯时,必须一个为主角色,另一为从角色,才能进行通信,通信时,必须由主端进行查找,发起配对,建链成功后,双方即可收发数据。蓝牙主端设备发起呼叫,首先是查找,找出周围处于可被查找的蓝牙设备。主端设备找到从端蓝牙设备后,与从端蓝牙设备进行配对,此时需要输入从端设备的PIN码,也有设备不需要输入PIN码。

    蓝牙流程

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

    因此又可以视为一个短连接。

    一、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();
            }
        }
    }

    测试效果

  • 相关阅读:
    js 函数定义的方式
    JS闭包的理解及常见应用场景
    requireJS的基本使用
    Zepto.js简介
    石川es6课程---1-2、ES6简介
    黑马lavarel教程---8、session
    Git使用操作指南和GitHub
    构建自己的Java并发模型框架
    对象的创建和存在时间(持续更新)
    iOS 通过HEX(十六进制)得到一个UIColor的对象
  • 原文地址:https://www.cnblogs.com/zeussbook/p/12827479.html
Copyright © 2011-2022 走看看