ble通信工具

package com.nobo.bluetooth;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.os.Build;
import android.os.Handler;
import android.util.Log;

import androidx.annotation.RequiresApi;

import com.blankj.utilcode.util.LogUtils;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.UUID;

/**
 * Created by MISHAOSHUAI
 * on 2021/8/17.
 */
public class BLEConnect
{
    private static BluetoothGattCharacteristic mNotifyCharacteristic;
    private static com.nobo.bluetooth.BtBase.Listener mListener;
    private String serviceUuid = "";
    private String characterUuid = "";
    private static final String TAG = "BLEConnect";
    private static BluetoothGatt mBluetoothGatt;
    private boolean isConnected;
    private Handler mDiscoverServiceHandler = new Handler();
    private Runnable mDisvoverServiceRunnable = new Runnable()
    {
        @Override
        public void run()
        {
            LogUtils.d("重新获取服务");
            disConn();

            connect(mBTmodel);
        }
    };

    private BTmodel mBTmodel;
    private static BLEConnect sInstance;

    private BLEConnect()
    {
    }

    public static BLEConnect getInstance(BtBase.Listener listener)
    {
        if (sInstance == null)
        {
            synchronized (BLEConnect.class)
            {
                if (sInstance == null)
                {
                    sInstance = new BLEConnect();
                }
            }
        }

        setListener(listener);
        return sInstance;
    }

    // 与服务端连接的Callback
    public BluetoothGattCallback mBluetoothGattCallback = new BluetoothGattCallback()
    {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState)
        {
            BluetoothDevice dev = gatt.getDevice();
            Log.i(TAG, String.format("onConnectionStateChange:%s,%s,%s,%s", dev.getName(), dev.getAddress(), status, newState));
            if (status == BluetoothGatt.GATT_SUCCESS &&
                newState == BluetoothProfile.STATE_CONNECTED)
            {
                isConnected = true;
                gatt.discoverServices(); //启动服务发现
                mDiscoverServiceHandler.postDelayed(mDisvoverServiceRunnable, 2000);
            }
            else
            {
                isConnected = false;
                disConn();

                notifyUI(BtBase.Listener.DISCONNECTED, mBTmodel);
                LogUtils.d("连接失败");
            }

            LogUtils.d(String.format(
                    status == 0 ? (newState == 2 ? "与[%s]连接成功" : "与[%s]连接断开") : ("与[%s]连接出错,错误码:" +
                                                                                 status), dev));
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status)
        {
            mDiscoverServiceHandler.removeCallbacksAndMessages(null);
            if (status == BluetoothGatt.GATT_SUCCESS)
            {
                LogUtils.d("发现服务成功,连接成功");
                notifyUI(BtBase.Listener.CONNECTED, mBTmodel);
                //BLE服务发现成功
                // 遍历获取BLE服务Services/Characteristics/Descriptors的全部UUID
                for (BluetoothGattService service : gatt.getServices())
                {
                    StringBuilder allUUIDs = new StringBuilder(
                            "UUIDs={\nS=" + service.getUuid().toString());
                    for (BluetoothGattCharacteristic characteristic : service.getCharacteristics())
                    {
                        allUUIDs.append(",\nC=").append(characteristic.getUuid());
                        for (BluetoothGattDescriptor descriptor : characteristic.getDescriptors())
                        {
                            allUUIDs.append(",\nD=").append(descriptor.getUuid());
                        }
                    }
                    allUUIDs.append("}");
                    LogUtils.d("发现服务" + allUUIDs);
                }

                //BLE服务发现成功
                serviceUuid = "your service uuid";
                characterUuid = "your character uuid";
                BluetoothGattService service = gatt.getService(UUID.fromString(serviceUuid));
                mNotifyCharacteristic = service.getCharacteristic(UUID.fromString(characterUuid));

                if (mNotifyCharacteristic != null)
                {
                    //使能Notify
                    setCharacteristicNotification(mNotifyCharacteristic, true);
                }

//                read();
            }
            else
            {
                LogUtils.d("发现服务失败,连接失败");
                disConn();
            }
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status)
        {
            UUID uuid = characteristic.getUuid();
            String valueStr = new String(characteristic.getValue());
            notifyUI(BtBase.Listener.READ, valueStr);
            LogUtils.d("读取Characteristic[" + uuid + "]:\n" + valueStr);
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status)
        {
            UUID uuid = characteristic.getUuid();
            String valueStr = new String(characteristic.getValue());
            notifyUI(BtBase.Listener.MSG, valueStr);
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)
        {
            UUID uuid = characteristic.getUuid();
            String valueStr = new String(characteristic.getValue());
            LogUtils.d("通知Characteristic[" + uuid + "]:\n" + valueStr);

            notifyUI(BtBase.Listener.READ, valueStr);
        }

        @Override
        public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status)
        {
            UUID uuid = descriptor.getUuid();
            String valueStr = Arrays.toString(descriptor.getValue());
            LogUtils.d("读取Descriptor[" + uuid + "]:\n" + valueStr);
        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status)
        {
            UUID uuid = descriptor.getUuid();
            String valueStr = Arrays.toString(descriptor.getValue());
            LogUtils.d("写入Descriptor[" + uuid + "]:\n" + valueStr);
            //询问状态
            write("A");
        }

        @Override
        public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status)
        {
            super.onReadRemoteRssi(gatt, rssi, status);
            LogUtils.d("RSSI:" + rssi);
        }
    };

    /**
     * BLE中心设备连接外围设备的数量有限(大概2~7个),
     * 在建立新连接之前必须释放旧连接资源,否则容易出现连接错误133
     */
    public void disConn()
    {
        if (mBluetoothGatt != null)
        {
            mBluetoothGatt.disconnect();
            mBluetoothGatt.close();

            mBluetoothGatt = null;
            mNotifyCharacteristic = null;
        }
    }

    // 注意:连续频繁读写数据容易失败,读写操作间隔最好200ms以上,或等待上次回调完成后再进行下次读写操作!
    // 读取数据成功会回调->onCharacteristicChanged()
    public void read()
    {
        BluetoothGattService service = getGattService(UUID.fromString(serviceUuid));
        if (service != null)
        {
            BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString(characterUuid));//通过UUID获取可读的Characteristic
            mBluetoothGatt.readCharacteristic(characteristic);
        }
    }

    // 注意:连续频繁读写数据容易失败,读写操作间隔最好200ms以上,或等待上次回调完成后再进行下次读写操作!
    // 写入数据成功会回调->onCharacteristicWrite()
    public void write(String data)
    {
        BluetoothGattService service = getGattService(UUID.fromString(serviceUuid));
        if (service != null)
        {
            BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString(characterUuid));//通过UUID获取可写的Characteristic
            characteristic.setValue(data.getBytes(StandardCharsets.UTF_8)); //单次最多20个字节
            mBluetoothGatt.writeCharacteristic(characteristic);
        }
    }

    // 获取Gatt服务
    private BluetoothGattService getGattService(UUID uuid)
    {
        if (!isConnected)
        {
            ToastyUtils.toastWarn("没有连接", true);
            return null;
        }
        BluetoothGattService service = mBluetoothGatt.getService(uuid);
        if (service == null)
        {
            ToastyUtils.toastWarn(
                    NoboApplication.getContext().getString(R.string.cant_find_service_uuid) +
                    uuid, true);
        }
        return service;
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    public void connect(BTmodel dev)
    {
        LogUtils.d("BLE connect");
        mBTmodel = dev;
        mBluetoothGatt = dev.getDevice()
                .connectGatt(NoboApplication.getContext(),
                             false,
                             mBluetoothGattCallback,
                             2,
                             BluetoothDevice.PHY_LE_1M_MASK); // 连接蓝牙设备
    }

    public void notifyUI(final int state, final BTmodel obj)
    {
        NoboApplication.runUi(() -> {
            try
            {
                if (mListener != null)
                {
                    mListener.socketNotify(state, obj);
                }
                else
                {
                    LogUtils.d("mListener == null");
                }
            }
            catch (Throwable e)
            {
                LogUtils.d("回调异常");
                e.printStackTrace();
            }
        });
    }

    public void notifyUI(final int state, final String obj)
    {
        NoboApplication.runUi(() -> {
            try
            {
                if (mListener != null)
                {
                    mListener.socketNotify(state, obj);
                }
                else
                {
                    LogUtils.d("mListener == null");
                }
            }
            catch (Throwable e)
            {
                LogUtils.d("回调异常");
                e.printStackTrace();
            }
        });
    }

    /**
     * 释放监听引用(例如释放对Activity引用,避免内存泄漏)
     */
    public void unListener()
    {
        mListener = null;
        LogUtils.d("mListener置空");
    }

    public boolean isConnected()
    {
        return isConnected;
    }

    public void setConnected(boolean connected)
    {
        isConnected = connected;
    }

    public BtBase.Listener getListener()
    {
        return mListener;
    }

    public static void setListener(BtBase.Listener listener)
    {
        mListener = listener;
    }

    public static String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";

    public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
            boolean enabled)
    {
        mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);

        // This is specific to BLE SPP Notify.
//        if (characterUuid.equals(characteristic.getUuid()))
        {
            BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
                    UUID.fromString(CLIENT_CHARACTERISTIC_CONFIG));
            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
            mBluetoothGatt.writeDescriptor(descriptor);
        }
    }
}

要交互,就要像上面那样setCharacteristicNotification才能收到消息

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值