经典蓝牙【bt】 封装帮助类

封装一个Bluetooth帮助类 , 最近在做蓝牙,用到了最老的bt。么办法,硬件端限制。

蓝牙类型: 经典蓝牙 【bt】 、低功耗蓝牙 【ble】

传统蓝牙通讯图:

蓝牙UUID备份

  1. 蓝牙串口服务
SerialPortServiceClass_UUID = '{00001101-0000-1000-8000-00805F9B34FB}'
LANAccessUsingPPPServiceClass_UUID = '{00001102-0000-1000-8000-00805F9B34FB}'
  1. 拨号网络服务
    DialupNetworkingServiceClass_UUID = '{00001103-0000-1000-8000-00805F9B34FB}'
    
  2. 信息同步服务
    IrMCSyncServiceClass_UUID = '{00001104-0000-1000-8000-00805F9B34FB}'
    SDP_OBEXObjectPushServiceClass_UUID = '{00001105-0000-1000-8000-00805F9B34FB}'
    
  3. 文件传输服务
    OBEXFileTransferServiceClass_UUID = '{00001106-0000-1000-8000-00805F9B34FB}'
    IrMCSyncCommandServiceClass_UUID = '{00001107-0000-1000-8000-00805F9B34FB}'
    SDP_HeadsetServiceClass_UUID = '{00001108-0000-1000-8000-00805F9B34FB}'
    CordlessTelephonyServiceClass_UUID = '{00001109-0000-1000-8000-00805F9B34FB}'
    SDP_AudioSourceServiceClass_UUID = '{0000110A-0000-1000-8000-00805F9B34FB}'
    SDP_AudioSinkServiceClass_UUID = '{0000110B-0000-1000-8000-00805F9B34FB}'
    SDP_AVRemoteControlTargetServiceClass_UUID = '{0000110C-0000-1000-8000-00805F9B34FB}'
    SDP_AdvancedAudioDistributionServiceClass_UUID = '{0000110D-0000-1000-8000-00805F9B34FB}'
    SDP_AVRemoteControlServiceClass_UUID = '{0000110E-0000-1000-8000-00805F9B34FB}'
    VideoConferencingServiceClass_UUID = '{0000110F-0000-1000-8000-00805F9B34FB}'
    IntercomServiceClass_UUID = '{00001110-0000-1000-8000-00805F9B34FB}'
    
  4. 蓝牙传真服务
    FaxServiceClass_UUID = '{00001111-0000-1000-8000-00805F9B34FB}'
    HeadsetAudioGatewayServiceClass_UUID = '{00001112-0000-1000-8000-00805F9B34FB}'
    WAPServiceClass_UUID = '{00001113-0000-1000-8000-00805F9B34FB}'
    WAPClientServiceClass_UUID = '{00001114-0000-1000-8000-00805F9B34FB}'
    
  5. 个人局域网服务
    PANUServiceClass_UUID = '{00001115-0000-1000-8000-00805F9B34FB}'
    
  6. 个人局域网服务
    NAPServiceClass_UUID = '{00001116-0000-1000-8000-00805F9B34FB}'
    
  7. 个人局域网服务
    GNServiceClass_UUID = '{00001117-0000-1000-8000-00805F9B34FB}'
    DirectPrintingServiceClass_UUID = '{00001118-0000-1000-8000-00805F9B34FB}'
    ReferencePrintingServiceClass_UUID = '{00001119-0000-1000-8000-00805F9B34FB}'
    ImagingServiceClass_UUID = '{0000111A-0000-1000-8000-00805F9B34FB}'
    ImagingResponderServiceClass_UUID = '{0000111B-0000-1000-8000-00805F9B34FB}'
    ImagingAutomaticArchiveServiceClass_UUID = '{0000111C-0000-1000-8000-00805F9B34FB}'
    ImagingReferenceObjectsServiceClass_UUID = '{0000111D-0000-1000-8000-00805F9B34FB}'
    SDP_HandsfreeServiceClass_UUID = '{0000111E-0000-1000-8000-00805F9B34FB}'
    HandsfreeAudioGatewayServiceClass_UUID = '{0000111F-0000-1000-8000-00805F9B34FB}'
    DirectPrintingReferenceObjectsServiceClass_UUID = '{00001120-0000-1000-8000-00805F9B34FB}'
    ReflectedUIServiceClass_UUID = '{00001121-0000-1000-8000-00805F9B34FB}'
    BasicPringingServiceClass_UUID = '{00001122-0000-1000-8000-00805F9B34FB}'
    PrintingStatusServiceClass_UUID = '{00001123-0000-1000-8000-00805F9B34FB}'
    
  8. 人机输入服务
    HumanInterfaceDeviceServiceClass_UUID = '{00001124-0000-1000-8000-00805F9B34FB}'
    HardcopyCableReplacementServiceClass_UUID = '{00001125-0000-1000-8000-00805F9B34FB}'
    
  9. 蓝牙打印服务
    HCRPrintServiceClass_UUID = '{00001126-0000-1000-8000-00805F9B34FB}'
    HCRScanServiceClass_UUID = '{00001127-0000-1000-8000-00805F9B34FB}'
    CommonISDNAccessServiceClass_UUID = '{00001128-0000-1000-8000-00805F9B34FB}'
    VideoConferencingGWServiceClass_UUID = '{00001129-0000-1000-8000-00805F9B34FB}'
    UDIMTServiceClass_UUID = '{0000112A-0000-1000-8000-00805F9B34FB}'
    UDITAServiceClass_UUID = '{0000112B-0000-1000-8000-00805F9B34FB}'
    AudioVideoServiceClass_UUID = '{0000112C-0000-1000-8000-00805F9B34FB}'
    SIMAccessServiceClass_UUID = '{0000112D-0000-1000-8000-00805F9B34FB}'
    PnPInformationServiceClass_UUID = '{00001200-0000-1000-8000-00805F9B34FB}'
    GenericNetworkingServiceClass_UUID = '{00001201-0000-1000-8000-00805F9B34FB}'
    GenericFileTransferServiceClass_UUID = '{00001202-0000-1000-8000-00805F9B34FB}'
    GenericAudioServiceClass_UUID = '{00001203-0000-1000-8000-00805F9B34FB}'
    GenericTelephonyServiceClass_UUID = '{00001204-0000-1000-8000-00805F9B34FB}'
    

    开始封装

首先在全局定义一个Handler 用于处理消息以及在子线程更新UI

val hander =  Handler() 

定义一个线程 ,用来接收硬件发来的数据

var acceptThread = AcceptThread()

广播接收处理数据

    private val broadcastReceiver: BroadcastReceiver by lazy {... }

定义各种回调方法

var searchList: ((array: List<BluetoothDevice>) -> Unit)? = null //搜索到设备列表
var searchStop: (() -> Unit)? = null  //停止搜索
var bleMsg: ((msg: String) -> Unit)? = null //接收消息
var bleStatus: ((code: BluetoothMode) -> Unit)? = null//状态消息

检查是否支持蓝牙

bluetoothAdapter?:false
return true

得到已经配对设备

    fun getPairingDevices(): List<BluetoothDevice> {
        val deviceSet = bluetoothAdapter?.bondedDevices
        val list = arrayListOf<BluetoothDevice>()
        deviceSet?.forEach {
            list.add(it)
        }
        return list
    }

打开蓝牙

 bluetoothAdapter?.run {
            //打开蓝牙
            if (!isEnabled) {
                enable()
                cancelDiscovery()
            }
        }

关闭蓝牙

 bluetoothAdapter?.disable()

得到蓝牙是否打开


    /**
     * 得到蓝牙是否打开
     */
    fun isBluetoothOpen(): Boolean {
        bluetoothAdapter?.run {
            return isEnabled
        }
        return false
    }

得到蓝牙连接状态

/**
     * 得到蓝牙连接状态
     */
    fun isConnected(): Boolean {
        return bluetoothSocket?.isConnected ?: false
    }

断开当前连接蓝牙

  bluetoothSocket?.run {
            Thread(Runnable {
                if (isConnected) {
                    try {
                        close()
                    } catch (e: IOException) {
                        e.printStackTrace()
                    }

                }
            }).start()
        }

这里一定要在子线程断开

连接蓝牙

 bluetoothDevice = bluetoothAdapter?.getRemoteDevice(address)
        Thread(Runnable {
            try {
                hander.post {
                    bleStatus?.run {
                        invoke(BluetoothMode.CONNECTING)
                    }
                }
                //获得设备
                bluetoothSocket = bluetoothDevice?.createRfcommSocketToServiceRecord(uuid)
                bluetoothSocket?.connect()
                outputStream = bluetoothSocket?.outputStream
                inputStream = bluetoothSocket?.inputStream
                Timber.d("蓝牙  连接成功")
                blueToothDeviceName = bluetoothDevice!!.name
                blueToothDeviceAddress = bluetoothDevice!!.address
                hander.post {
                    bleStatus?.run {
                        invoke(BluetoothMode.CONNECT_SUCCESS)
                    }
                }
            } catch (e: IOException) {
                Timber.e("蓝牙  连接失败")
                hander.post {
                    bleStatus?.run {
                        invoke(BluetoothMode.CONNECT_ERR)
                    }
                }
                e.printStackTrace()
            }
        }).start()

搜索设备

  while (!bluetoothAdapter!!.startDiscovery()) {
            try {
                Thread.sleep(100)
            } catch (e: InterruptedException) {
                Timber.e("蓝牙 搜索异常")
                e.printStackTrace()
            }
        }

这里startDiscovery方法是异步的

服务端接收消息

 while (!isStop!!) {
                while (inputStream != null)
                    try {
                        len = inputStream!!.read(buf)
                        val msg = Message.obtain()
                        msg.what = MESSAGE_DATA
                        msg.obj = String(buf, 0, len)
                        Timber.i("蓝牙原始收到数据 ${String(buf, 0, len)}")
                        myHandler.sendMessage(msg)
                    } catch (e: IOException) {
                        e.printStackTrace()
                    }

            }

使用方法

在全局定义封装的这个类

val bleHelper by lazy {
    BluttoothHelper()
}

之后就可以随意发挥咯 ,前面封装的方法 在APP任何地方都可以使用哦! 像这样:

bleHelper.openBlueTooth()

回调方法在任何地方都可以调用哦! 像这样:

  bleHelper.let {//此处在别的方法里哦
            it.bleStatus = this::bleStatus
        }

  private fun bleStatus(code: BluetoothMode) {
   //这里就是我们接收的状态code咯
    }