Android Ble蓝牙开发(服务器端)

版权声明:本文为博主收集的资料,欢迎参考。未经本人允许,禁止转载 https://blog.csdn.net/z302766296/article/details/77816960

最近项目里面需要集成一个蓝牙的连接功能,作为一枚刚刚毕业不久的新生,大学几年又白过的。只好在几天内搜搜百度,脑补一下。文章部分内容摘至各大Blog,加上本dust的见解,写了一份Client端和Service端的小呆毛。

这次的是Server端的实现

参考链接–Link:http://www.cnblogs.com/vir56k/p/6273241.html

————————————————————————-我是分割线————————————————————————-

上次聊过Gatt协议,以及几个API的使用并实现了Client端的代码。这次实现的是Server端,不叨叨,show me the code

**

一、Server端概念了解

**
之前说了Client端,这次Server端,Server端的实现比较简单。只是多了一个类似广播的东西,叫BluetoothLeAdvertiser,翻译广告…我还是用广播感觉合适点。Server端需要发射出广播,同时Server会暴露一个数据包出去。当Client开始扫描,Client扫描到Server端的数据包之后,就会请求连接。Server就做出反应,然后连接,开始传输数据。

  
**

二、API分析

**
 当前使用到的类包括:
   BluetoothManager
   BluetoothAdapter
   BluetoothService
   BluetoothGattCharacteristic
   
   BluetoothServer
   BluetoothAdvertiser
   AdvertiseSetting
   AdvertiseData
   BluetoothGattServerCallback

BluetoothManager,BluetoothService,BluetoothAdapter,BluetoothGattCharacteristic之前都说过了,可能需要补充的是BluetoothManager的一个API。

BluetoothManager.openGattServer

这里写图片描述

其他的,忘了的童鞋可以参考上一章 Android Ble蓝牙开发(客户端)

那么我就说下下面四个新的API

  
BluetoothServer
  我也想不到,Android是直接给出这样的一个Server的API可以供我们操作。这里的Server大家需要和Service区分,一个是服务器端,一个是Service服务。类似Android系统提供出形形色色的那些服务。
  
BluetoothServer

这里的猜测IPC其实是Application与蓝牙件程序的通信。我也没作深究了

BluetoothAdvertiser
  服务器广播,用于开启服务器广播以供Client端扫描发现

BluetoothAdvertiser

  
BluetoothAdvertiser

  
AdvertiseSetting
  这个类的创建需要用到Builder,其作用是设置Advertiser属性的,例如广播的Mode,连接时间,连接可用等等。

AdvertiseSetting

  
AdvertiseData
  这个类的作用就是配置广播的数据的,例如设置服务的UUID,传输的等级TxPowerLevel,还有设置设备名是否包含在传输数据里面。

这里写图片描述

  
BluetoothGattServerCallback
  这个接口里面实现的几个方法比较关键,里面有连接状态的回调,Client离服务器的距离RSSI,收到characteristic操作的请求回调,还有descriptor操作的请求回调等等。最关键的地方就是,我们收到了关于Characteristic和descriptor的操作请求的时候,都必须调用 BluetoothGattServer.sendResponse(BluetoothDevice device, int requestId,int status,int offset,byte[] value) 方法才能完成整个连接过程

BluetoothGattServerCallback API

BluetoothGattServerCallback  回调

BluetoothGattServer sendResponse函数

  
**

三、代码实现

**

实现思路大概如下:
  1.设置广播以及初始化广播数据
  2.开始广播
  3.配置Services以及Characteristic
  4.Server回调以及操作

  
设置广播以及初始化广播数据

/**
     * 1.初始化BLE蓝牙广播Advertiser,配置指定UUID的服务
     */
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void initGATTServer() {

        AdvertiseSettings settings = new AdvertiseSettings.Builder()
                .setConnectable(true)
                .build();

        AdvertiseData advertiseData = new AdvertiseData.Builder()
                .setIncludeDeviceName(true)
                .setIncludeTxPowerLevel(true)
                .build();

        //通过UUID_SERVICE构建
        AdvertiseData scanResponseData = new AdvertiseData.Builder()
                .addServiceUuid(new ParcelUuid(Const.UUID_SERVICE))
                .setIncludeTxPowerLevel(true)
                .build();

        //广播创建成功之后的回调
        AdvertiseCallback callback = new AdvertiseCallback() {
            @Override
            public void onStartSuccess(AdvertiseSettings settingsInEffect) {
                Log.d(TAG, "BLE advertisement added successfully");
                //showText("1. initGATTServer success");
                //println("1. initGATTServer success");
                //初始化服务
                initServices(BleService.this);
            }

            @Override
            public void onStartFailure(int errorCode) {
                Log.e(TAG, "Failed to add BLE advertisement, reason: " + errorCode);
                //showText("1. initGATTServer failure");
            }
        };

        //部分设备不支持Ble中心
        BluetoothLeAdvertiser bluetoothLeAdvertiser = mBlueToothAdapter.getBluetoothLeAdvertiser();
        if (bluetoothLeAdvertiser == null) {
            Log.i(TAG, "BluetoothLeAdvertiser为null");
        }

        //开始广播
        if (bluetoothLeAdvertiser != null) {
            bluetoothLeAdvertiser.startAdvertising(settings, advertiseData, scanResponseData, callback);
        }
    }

配置Services以及Characteristic

/**
     * 初始化Gatt服务,主要是配置Gatt服务各种UUID
     *
     * @param context
     */
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    private void initServices(Context context) {
        //创建GattServer服务器
        mGattServer = mBluetoothManager.openGattServer(context, bluetoothGattServerCallback);

        //这个指定的创建指定UUID的服务
        BluetoothGattService service = new BluetoothGattService(Const.UUID_SERVICE, BluetoothGattService.SERVICE_TYPE_PRIMARY);

        //添加指定UUID的可读characteristic
        characteristicRead = new BluetoothGattCharacteristic(
                Const.UUID_CHARACTERISTIC_READ,
                BluetoothGattCharacteristic.PROPERTY_READ,
                BluetoothGattCharacteristic.PERMISSION_READ);
        //添加可读characteristic的descriptor
        BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(UUID_DESCRIPTOR, BluetoothGattCharacteristic.PERMISSION_WRITE);
        characteristicRead.addDescriptor(descriptor);
        service.addCharacteristic(characteristicRead);


        //添加指定UUID的可写characteristic
        BluetoothGattCharacteristic characteristicWrite = new BluetoothGattCharacteristic(Const.UUID_CHARACTERISTIC_WRITE,
                BluetoothGattCharacteristic.PROPERTY_WRITE |
                        BluetoothGattCharacteristic.PROPERTY_READ |
                        BluetoothGattCharacteristic.PROPERTY_NOTIFY,
                BluetoothGattCharacteristic.PERMISSION_WRITE);
        service.addCharacteristic(characteristicWrite);

        mGattServer.addService(service);
        Log.e(TAG, "2. initServices ok");
        //showText("2. initServices ok");
    }

到这里,Server的配置算是完成了。之后就是等待BluetoothGattServerCallback的回调了

Server回调以及操作

     /**
     * 服务事件的回调
     */
    private BluetoothGattServerCallback bluetoothGattServerCallback = new BluetoothGattServerCallback() {

        /**
         * 1.连接状态发生变化时
         * @param device
         * @param status
         * @param newState
         */
        @Override
        public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
            Log.e(TAG, String.format("1.onConnectionStateChange:device name = %s, address = %s", device.getName(), device.getAddress()));
            Log.e(TAG, String.format("1.onConnectionStateChange:status = %s, newState =%s ", status, newState));
            super.onConnectionStateChange(device, status, newState);
        }

        @Override
        public void onServiceAdded(int status, BluetoothGattService service) {
            super.onServiceAdded(status, service);
            Log.e(TAG, String.format("onServiceAdded:status = %s", status));
        }

        @Override
        public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
            Log.e(TAG, String.format("onCharacteristicReadRequest:device name = %s, address = %s", device.getName(), device.getAddress()));
            Log.e(TAG, String.format("onCharacteristicReadRequest:requestId = %s, offset = %s", requestId, offset));

            mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, characteristic.getValue());
//            super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
        }

        /**
         * 3. onCharacteristicWriteRequest,接收具体的字节
         * @param device
         * @param requestId
         * @param characteristic
         * @param preparedWrite
         * @param responseNeeded
         * @param offset
         * @param requestBytes
         */
        @Override
        public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] requestBytes) {
            Log.e(TAG, String.format("3.onCharacteristicWriteRequest:device name = %s, address = %s", device.getName(), device.getAddress()));
            Log.e(TAG, String.format("3.onCharacteristicWriteRequest:requestId = %s, preparedWrite=%s, responseNeeded=%s, offset=%s, value=%s", requestId, preparedWrite, responseNeeded, offset, requestBytes.toString()));
            mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, requestBytes);
            //4.处理响应内容
            onResponseToClient(requestBytes, device, requestId, characteristic);
        }

        /**
         * 2.描述被写入时,在这里执行 bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS...  收,触发 onCharacteristicWriteRequest
         * @param device
         * @param requestId
         * @param descriptor
         * @param preparedWrite
         * @param responseNeeded
         * @param offset
         * @param value
         */
        @Override
        public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
            Log.e(TAG, String.format("2.onDescriptorWriteRequest:device name = %s, address = %s", device.getName(), device.getAddress()));
            Log.e(TAG, String.format("2.onDescriptorWriteRequest:requestId = %s, preparedWrite = %s, responseNeeded = %s, offset = %s, value = %s,", requestId, preparedWrite, responseNeeded, offset, value.toString()));

            // now tell the connected device that this was all successfull
            mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value);
        }

        /**
         * 5.特征被读取。当回复响应成功后,客户端会读取然后触发本方法
         * @param device
         * @param requestId
         * @param offset
         * @param descriptor
         */
        @Override
        public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {
            Log.e(TAG, String.format("onDescriptorReadRequest:device name = %s, address = %s", device.getName(), device.getAddress()));
            Log.e(TAG, String.format("onDescriptorReadRequest:requestId = %s", requestId));
//            super.onDescriptorReadRequest(device, requestId, offset, descriptor);
            mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, null);
        }

        @Override
        public void onNotificationSent(BluetoothDevice device, int status) {
            super.onNotificationSent(device, status);
            Log.e(TAG, String.format("5.onNotificationSent:device name = %s, address = %s", device.getName(), device.getAddress()));
            Log.e(TAG, String.format("5.onNotificationSent:status = %s", status));
        }

        @Override
        public void onMtuChanged(BluetoothDevice device, int mtu) {
            super.onMtuChanged(device, mtu);
            Log.e(TAG, String.format("onMtuChanged:mtu = %s", mtu));
        }

        @Override
        public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
            super.onExecuteWrite(device, requestId, execute);
            Log.e(TAG, String.format("onExecuteWrite:requestId = %s", requestId));
        }
    };

    /**
     * 4.处理响应内容
     *
     * @param reqeustBytes
     * @param device
     * @param requestId
     * @param characteristic
     */
    private void onResponseToClient(byte[] reqeustBytes, BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic) {
        Log.e(TAG, String.format("4.onResponseToClient:device name = %s, address = %s", device.getName(), device.getAddress()));
        Log.e(TAG, String.format("4.onResponseToClient:requestId = %s", requestId));
//        String msg = OutputStringUtil.transferForPrint(reqeustBytes);
        Log.e(TAG, "4.收到:");
        //println("4.收到:" + msg);
        //showText("4.收到:" + msg);

        String str = new String(reqeustBytes) + " hello>";
        characteristicRead.setValue(str.getBytes());
        mGattServer.notifyCharacteristicChanged(device, characteristicRead, false);

        Log.i(TAG, "4.响应:" + str);
        MainActivity.handler.obtainMessage(MainActivity.DEVICE, new String(reqeustBytes)).sendToTarget();
        //println("4.响应:" + str);
        //showText("4.响应:" + str);
    }

上面代码中需要注意的地方是,当我们收到了Characteristic和Descriptor操作请求后,一定需要调用BluetoothGattServer.sendResponse(BluetoothDevice device, int requestId,int status,int offset,byte[] value) 方法才能完成整个连接过程。

onResponseToClient
  我们在onCharacteristicWriteRequest回调里面对数据进行了提取,然后还需要调用BluetoothGattServer.notifyCharacteristicChanged(device, characteristic, false) 通知Client端Characteristic已经发生了变化。

/**
     * 4.处理响应内容
     *
     * @param reqeustBytes
     * @param device
     * @param requestId
     * @param characteristic
     */
    private void onResponseToClient(byte[] reqeustBytes, BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic) {
        Log.e(TAG, String.format("4.onResponseToClient:device name = %s, address = %s", device.getName(), device.getAddress()));
        Log.e(TAG, String.format("4.onResponseToClient:requestId = %s", requestId));
        //String msg = OutputStringUtil.transferForPrint(reqeustBytes);
        Log.e(TAG, "4.收到:");
        //println("4.收到:" + msg);
        //showText("4.收到:" + msg);

        String str = new String(reqeustBytes) + " hello>";
       /* characteristicRead.setValue(str.getBytes());
        mGattServer.notifyCharacteristicChanged(device, characteristicRead, false);*/
        characteristic.setValue(str.getBytes());
        mGattServer.notifyCharacteristicChanged(device, characteristic, false);

        Log.i(TAG, "4.响应:" + str);
        MainActivity.handler.obtainMessage(MainActivity.DEVICE, new String(reqeustBytes)).sendToTarget();
        //println("4.响应:" + str);
        //showText("4.响应:" + str);
    }

  
到上面为止,BLE两demo已经完成了,不过服务器端的Manifest也需要配置,和BleClient一样就好了。同时注意操作最好都放到Service中完成。下面放个源码,希望大家多多支持吧~







源码下载

猜你喜欢

转载自blog.csdn.net/z302766296/article/details/77816960