健康一贴灵,专注医药行业管理信息化

ANDROID STUDIO操作蓝牙打印机(转)

前言

工作中或多或少都会遇到困扰自己很久的问题,我也毫无例外,曾经在项目中对蓝牙打印这一块也困惑和迷茫过,最近在做项目重构的时候,翻看了之前写的代码,还是决定通过两篇文章详细阐述蓝牙连接打印机完成整个打印流程的操作,目的是对工作的一种总结,其次是输出。好比玩个压缩,又是绿叉又是无尽,一身暴击 装,却不知怎么打输出,好像特无语,工作中应该也是一样,学会总结和输出这样才能提升自己,当然也希望能帮助在蓝牙打印方面存在疑惑和困扰的同学,希望在看完这两篇文章后能对经典蓝牙有更多了解和认识。

概述

我将通过上下两部分,详细阐述蓝牙打印功能整体思路以及流程,上部分主要是阐述如何通过协程开启子任务连接蓝牙,以及如何通过系统广播建立心跳包,实现断线重连机制,下部分主要阐述应用和蓝牙打印机间的通信。

基本了解

1,了解经典蓝牙和低功耗蓝牙的区别,太必要了,当初我就走了弯路,如果你对这两种蓝牙有了解,那实在是太好了。
2,协程相关知识,如何建立耗时任务等,如果你不了解协程,你也可以使用RxJava实现,或者直接开启线程建立耗时任务,姿势很多。
3,对Service和Broadcast有一定了解,当然我相信你对这两大组件一定再熟悉不过了。

UML类图

类图.png

实现过程

  • 1,准备工作
    在我们日常开发中,对整个功能的需求把控设计,应该是首当其冲的必要条件,所以通过类图我们大致定义了两个功能接口,BlueClient和BlueConnector,BlueClient接口大致包含开启蓝牙,关闭,扫描周围蓝牙设备,连接蓝牙,断开蓝牙设备等功能,具体功能细节类图或者代码都做了详细说明,BlueConnector接口主要是用来定义蓝牙设备连接,断开和重连等,BlueClient中的功能定义依赖BlueConnector
  • 2,具体实现
    定义BlueClient接口 主要用来打开蓝牙,连接蓝牙设备等功能
/**
 *author  : Frank
 *e-mail  : zhuhuitao_struggle@163.com
 *date    : 2021/1/15 14:40
 *desc    :
 *version :
 */
interface BlueClient {
    /**
     * 根据传入状态 打开和关闭蓝牙
     *
     * @param state 蓝牙状态
     */
    fun onBlueState(state: Int)
<span class="token comment">/**
 * 开始扫描蓝牙设备
 *
 * @param callback 扫描结果回调
 * @throws NotInitException 回调异常捕获
 * @throws BlueScanException    蓝牙扫描异常捕获
 */</span>
<span class="token annotation builtin">@Throws</span><span class="token punctuation">(</span>NotInitException<span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span> BlueScanException<span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span>
<span class="token keyword">fun</span> <span class="token function">onStartScan</span><span class="token punctuation">(</span>callback<span class="token operator">:</span> ScanCallback<span class="token punctuation">)</span>

<span class="token comment">/**
 * 停止或者终止扫描设备后回调
 *
 * @throws NotInitException 异常捕获
 */</span>
<span class="token annotation builtin">@Throws</span><span class="token punctuation">(</span>NotInitException<span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span>
<span class="token keyword">fun</span> <span class="token function">onStopScan</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">/**
 * 停止或者终止扫描
 */</span>
<span class="token keyword">fun</span> <span class="token function">cancelScan</span><span class="token punctuation">(</span><span class="token punctuation">)</span>


<span class="token comment">/**
 * 发现新设备
 *
 * @param device 发现的新设备
 * @throws NotInitException 回调异常捕获
 */</span>
<span class="token annotation builtin">@Throws</span><span class="token punctuation">(</span>NotInitException<span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span>
<span class="token keyword">fun</span> <span class="token function">onFind</span><span class="token punctuation">(</span>device<span class="token operator">:</span> BluetoothDevice<span class="token operator">?</span><span class="token punctuation">)</span>


<span class="token comment">/**
 * 连接一个设备
 *
 * @param device 所需要连接的设备
 * @return 返回连接结果
 */</span>
<span class="token keyword">fun</span> <span class="token function">connect</span><span class="token punctuation">(</span>device<span class="token operator">:</span> BluetoothDevice<span class="token punctuation">,</span> callback<span class="token operator">:</span> BlueConnectCallback<span class="token punctuation">)</span>

<span class="token comment">/**
 * 指定mac地址连接一台蓝牙设备
 *
 * @param mac             mac地址
 * @param connectCallback 连接结果回调
 */</span>
<span class="token keyword">fun</span> <span class="token function">connect</span><span class="token punctuation">(</span>mac<span class="token operator">:</span> String<span class="token punctuation">,</span> connectCallback<span class="token operator">:</span> BlueConnectCallback<span class="token punctuation">)</span>


<span class="token comment">/**
 * 断开一个设备
 *
 * @param device 所需要断开的设备
 * @return 返回断开结果
 */</span>
<span class="token keyword">fun</span> <span class="token function">disConnect</span><span class="token punctuation">(</span>device<span class="token operator">:</span> BluetoothDevice<span class="token punctuation">,</span> callback<span class="token operator">:</span> DisconnectCallback<span class="token punctuation">)</span>

<span class="token comment">/**
 * 设备主动断开后重连,此过程由于蓝牙设备间通信出现异常断开,不存在人为操作
 */</span>
<span class="token keyword">fun</span> <span class="token function">onReconnect</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">/**
 * 打开蓝牙
 */</span>
<span class="token keyword">fun</span> <span class="token function">openBlue</span><span class="token punctuation">(</span>callback<span class="token operator">:</span> BlueSwitchCallback<span class="token punctuation">)</span>

<span class="token comment">/**
 * 关闭蓝牙
 */</span>
<span class="token keyword">fun</span> <span class="token function">closeBlue</span><span class="token punctuation">(</span>callback<span class="token operator">:</span> BlueSwitchCallback<span class="token punctuation">)</span>

<span class="token comment">/**
 * 获取上下文
 *
 * @return
 */</span>
<span class="token keyword">fun</span> <span class="token function">getContext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> Context

<span class="token comment">/**
 * 初始化相关工作
 */</span>
<span class="token keyword">fun</span> <span class="token keyword">init</span><span class="token punctuation">(</span>context<span class="token operator">:</span> Context<span class="token punctuation">)</span><span class="token operator">:</span> BlueClient

<span class="token comment">/**
 * 成功连接了一台蓝牙设备
 *
 * @param device 连接的蓝牙设备
 */</span>
<span class="token keyword">fun</span> <span class="token function">onConnected</span><span class="token punctuation">(</span>device<span class="token operator">:</span> BluetoothDevice<span class="token punctuation">)</span>

<span class="token comment">/**
 * 成功断开一台设备
 *
 * @param device
 */</span>
<span class="token keyword">fun</span> <span class="token function">onDisconnect</span><span class="token punctuation">(</span>device<span class="token operator">:</span> BluetoothDevice<span class="token punctuation">)</span>


<span class="token comment">/**
 * 蓝牙配对状态
 *
 * @param device 蓝牙配对状态回调
 */</span>
<span class="token keyword">fun</span> <span class="token function">bondStatus</span><span class="token punctuation">(</span>device<span class="token operator">:</span> BluetoothDevice<span class="token punctuation">)</span>

<span class="token comment">/**
 * 获取已绑定的蓝牙设备
 *
 * @return
 */</span>
<span class="token keyword">fun</span> <span class="token function">getBondedDevices</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> List<span class="token operator">&lt;</span>BluetoothDevice<span class="token operator">?</span><span class="token operator">&gt;</span>


<span class="token comment">/**
 * 是否开启日志功能
 * @param isDebug 日志开关
 */</span>
<span class="token keyword">fun</span> <span class="token function">enableDebug</span><span class="token punctuation">(</span>isDebug<span class="token operator">:</span>Boolean<span class="token punctuation">)</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137

定义BlueClint具体实现类BlueClientImpl

/**
 *author  : Frank
 *e-mail  : zhuhuitao_struggle@163.com
 *date    : 2021/1/15 15:12
 *desc    :
 *version :
 */
class BlueClientImpl : BlueClient {
    private lateinit var mCtx: Context
<span class="token comment">//蓝牙适配器</span>
<span class="token keyword">private</span> <span class="token keyword">var</span> mBlueAdapter<span class="token operator">:</span> BluetoothAdapter<span class="token operator">?</span> <span class="token operator">=</span> <span class="token keyword">null</span>

<span class="token comment">//连接状态回调</span>
<span class="token keyword">private</span> <span class="token keyword">var</span> mConnectCallback<span class="token operator">:</span> BlueConnectCallback<span class="token operator">?</span> <span class="token operator">=</span> <span class="token keyword">null</span>

<span class="token comment">//断开状态回调</span>
<span class="token keyword">private</span> <span class="token keyword">var</span> mDisconnectCallback<span class="token operator">:</span> DisconnectCallback<span class="token operator">?</span> <span class="token operator">=</span> <span class="token keyword">null</span>

<span class="token comment">//开启关闭蓝牙状态回调</span>
<span class="token keyword">private</span> <span class="token keyword">var</span> mBlueSwitchCallback<span class="token operator">:</span> BlueSwitchCallback<span class="token operator">?</span> <span class="token operator">=</span> <span class="token keyword">null</span>

<span class="token comment">//扫描周围蓝牙设备回调</span>
<span class="token keyword">private</span> <span class="token keyword">var</span> mScanCallback<span class="token operator">:</span> ScanCallback<span class="token operator">?</span> <span class="token operator">=</span> <span class="token keyword">null</span>

<span class="token comment">//存放周围扫描到的蓝牙设备,已去除重复设备</span>
<span class="token keyword">private</span> <span class="token keyword">var</span> mDeviceList<span class="token operator">:</span> MutableList<span class="token operator">&lt;</span>BluetoothDevice<span class="token operator">&gt;</span><span class="token operator">?</span> <span class="token operator">=</span> <span class="token keyword">null</span>

<span class="token comment">//蓝牙广播接收者</span>
<span class="token keyword">private</span> <span class="token keyword">var</span> mBlueReceiver<span class="token operator">:</span> BluetoothReceiver<span class="token operator">?</span> <span class="token operator">=</span> <span class="token keyword">null</span>

<span class="token keyword">companion</span> <span class="token keyword">object</span> <span class="token punctuation">{<!-- --></span>
    <span class="token comment">//标识当前的蓝牙设备是否已连接</span>
    <span class="token keyword">var</span> connected <span class="token operator">=</span> <span class="token boolean">false</span>

    <span class="token comment">//用于标识蓝牙开关状态</span>
    <span class="token keyword">var</span> isOPen <span class="token operator">=</span> <span class="token boolean">false</span>

    <span class="token comment">//用于标识是否是人为断开</span>
    <span class="token keyword">var</span> isArtifical <span class="token operator">=</span> <span class="token boolean">false</span>

    <span class="token comment">//伴生对象</span>
    <span class="token keyword">val</span> instance <span class="token operator">=</span> <span class="token function">BlueClientImpl</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">onBlueState</span><span class="token punctuation">(</span>state<span class="token operator">:</span> Int<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token comment">//通知UI层当前的蓝牙开启状态</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>state <span class="token operator">==</span> BluetoothAdapter<span class="token punctuation">.</span>STATE_ON<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        <span class="token comment">//已打开</span>
        mBlueSwitchCallback<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">onStateChange</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>state <span class="token operator">==</span> BluetoothAdapter<span class="token punctuation">.</span>STATE_OFF<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        <span class="token comment">//已关闭</span>
        mBlueSwitchCallback<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">onStateChange</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">)</span>
        <span class="token comment">//将连接状态置为false</span>
        connected <span class="token operator">=</span> <span class="token boolean">false</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">onStartScan</span><span class="token punctuation">(</span>callback<span class="token operator">:</span> ScanCallback<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token comment">//初始化callback对象</span>
    mScanCallback <span class="token operator">=</span> callback
    <span class="token keyword">if</span> <span class="token punctuation">(</span>mBlueAdapter <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        <span class="token comment">//如果正在扫描周围的蓝牙设备,则返回</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>mBlueAdapter<span class="token operator">?</span><span class="token punctuation">.</span>isDiscovering <span class="token operator">==</span> <span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
            <span class="token keyword">return</span>
        <span class="token punctuation">}</span>
        <span class="token comment">//初始化集合,用于存放周围发现的蓝牙设备</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>mDeviceList <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> mDeviceList <span class="token operator">=</span> <span class="token function">arrayListOf</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token comment">//开始扫描</span>
        mBlueAdapter<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">startDiscovery</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token comment">//通知ui层正在扫描</span>
        mScanCallback<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">onStartScan</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">onStopScan</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token comment">//当停止扫描后把当前的设备集合返回到UI层</span>
    mScanCallback<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">onStopScan</span><span class="token punctuation">(</span>mDeviceList<span class="token operator">!!</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">cancelScan</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>mBlueAdapter <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        <span class="token comment">//1,当用户点击ui连接设备时,调用此方法,停止扫描周围设备</span>
        <span class="token comment">//2,接收系统扫描的结束的通知,当然自己也可以做一个定时任务主动停止扫描</span>
        mBlueAdapter<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">cancelDiscovery</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">onFind</span><span class="token punctuation">(</span>device<span class="token operator">:</span> BluetoothDevice<span class="token operator">?</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token comment">//如果接收到的设备为null直接返回不做处理</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>device <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">return</span>
    <span class="token comment">//如果集合不为null直接遍历集合,</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>mDeviceList<span class="token operator">!!</span><span class="token punctuation">.</span><span class="token function">isNotEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        mDeviceList<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">forEach</span> <span class="token punctuation">{<!-- --></span>
            <span class="token comment">//如果发现设备已存在则返回,不在继续加入集合</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>it<span class="token punctuation">.</span>address <span class="token operator">==</span> device<span class="token punctuation">.</span>address<span class="token punctuation">)</span> <span class="token keyword">return</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    <span class="token comment">//回调发现的设备</span>
    mScanCallback<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">onFindDevice</span><span class="token punctuation">(</span>device<span class="token punctuation">)</span>
    <span class="token comment">//将设备加入集合列表 用于ui展示</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>mDeviceList<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>device<span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">connect</span><span class="token punctuation">(</span>device<span class="token operator">:</span> BluetoothDevice<span class="token punctuation">,</span> callback<span class="token operator">:</span> BlueConnectCallback<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token comment">//初始化callback对象</span>
    mConnectCallback <span class="token operator">=</span> callback
    <span class="token comment">//连接一台指定的蓝牙设备</span>
    BlueConnectorImpl<span class="token punctuation">.</span>instant<span class="token punctuation">.</span><span class="token function">connect</span><span class="token punctuation">(</span>mBlueAdapter<span class="token punctuation">,</span> device<span class="token punctuation">,</span> mConnectCallback<span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">connect</span><span class="token punctuation">(</span>mac<span class="token operator">:</span> String<span class="token punctuation">,</span> connectCallback<span class="token operator">:</span> BlueConnectCallback<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token comment">//初始化callback对象</span>
    mConnectCallback <span class="token operator">=</span> connectCallback
    <span class="token comment">//指定mac 连接一台蓝牙设备</span>
    BlueConnectorImpl<span class="token punctuation">.</span>instant<span class="token punctuation">.</span><span class="token function">connect</span><span class="token punctuation">(</span>mBlueAdapter<span class="token punctuation">,</span> mac<span class="token punctuation">,</span> mConnectCallback<span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">disConnect</span><span class="token punctuation">(</span>device<span class="token operator">:</span> BluetoothDevice<span class="token punctuation">,</span> callback<span class="token operator">:</span> DisconnectCallback<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token comment">//初始化callback</span>
    mDisconnectCallback <span class="token operator">=</span> callback
    <span class="token comment">//断开蓝牙设备</span>
    BlueConnectorImpl<span class="token punctuation">.</span>instant<span class="token punctuation">.</span><span class="token function">disconnect</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">onReconnect</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token comment">//调用BlueConnector实现类完成重连</span>
    BlueConnectorImpl<span class="token punctuation">.</span>instant<span class="token punctuation">.</span><span class="token function">reconnect</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">openBlue</span><span class="token punctuation">(</span>callback<span class="token operator">:</span> BlueSwitchCallback<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token comment">//初始化switchCallback</span>
    mBlueSwitchCallback <span class="token operator">=</span> callback
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">supportBluetooth</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        <span class="token keyword">return</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>mBlueAdapter<span class="token operator">?</span><span class="token punctuation">.</span>isEnabled <span class="token operator">==</span> <span class="token boolean">false</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        <span class="token comment">//开启蓝牙</span>
        mBlueAdapter<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">enable</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
        mBlueSwitchCallback<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">onStateChange</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">closeBlue</span><span class="token punctuation">(</span>callback<span class="token operator">:</span> BlueSwitchCallback<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token comment">//关闭蓝牙,此处一般程序中用不到,若不支持蓝牙,不做任何操作</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">supportBluetooth</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>mBlueAdapter<span class="token operator">?</span><span class="token punctuation">.</span>isEnabled <span class="token operator">==</span> <span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        <span class="token comment">//调用蓝牙适配器关闭蓝牙</span>
        mBlueAdapter<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">disable</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">getContext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> Context <span class="token punctuation">{<!-- --></span>
    <span class="token keyword">return</span> mCtx
<span class="token punctuation">}</span>

<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token keyword">init</span><span class="token punctuation">(</span>context<span class="token operator">:</span> Context<span class="token punctuation">)</span><span class="token operator">:</span> BlueClient <span class="token punctuation">{<!-- --></span>
    mCtx <span class="token operator">=</span> context
    <span class="token comment">//获取蓝牙适配器</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>mBlueAdapter <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        mBlueAdapter <span class="token operator">=</span> BluetoothAdapter<span class="token punctuation">.</span><span class="token function">getDefaultAdapter</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    <span class="token comment">//初始化蓝牙广播接收 BroadcastReceiver</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>mBlueReceiver <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        mBlueReceiver <span class="token operator">=</span> <span class="token function">BluetoothReceiver</span><span class="token punctuation">(</span>mCtx<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> <span class="token keyword">this</span>
<span class="token punctuation">}</span>


<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">onConnected</span><span class="token punctuation">(</span>device<span class="token operator">:</span> BluetoothDevice<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token comment">//将连接状态置为true</span>
    connected <span class="token operator">=</span> <span class="token boolean">true</span>
    <span class="token comment">//f返回当前连接的设备以及当前的socket</span>
    mConnectCallback<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">connectSuccess</span><span class="token punctuation">(</span>BlueConnectorImpl<span class="token punctuation">.</span>instant<span class="token punctuation">.</span><span class="token function">getBlueSocket</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> device<span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">onDisconnect</span><span class="token punctuation">(</span>device<span class="token operator">:</span> BluetoothDevice<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token comment">//将连接状态置为false</span>
    connected <span class="token operator">=</span> <span class="token boolean">false</span>
    <span class="token comment">//通知连接失败状态,这里断开分为两种状态,</span>
    <span class="token comment">// 1认为操作断开,2无人为干预自动断开(此中状态会触发自动重连)</span>
    mDisconnectCallback<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">disConnectSuccess</span><span class="token punctuation">(</span>device<span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">bondStatus</span><span class="token punctuation">(</span>device<span class="token operator">:</span> BluetoothDevice<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token comment">//返回当前配对蓝牙设备</span>
    mConnectCallback<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">bondStatus</span><span class="token punctuation">(</span>device<span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">getBondedDevices</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> MutableList<span class="token operator">&lt;</span>BluetoothDevice<span class="token operator">&gt;</span> <span class="token punctuation">{<!-- --></span>
    <span class="token comment">//这里返回配对过的蓝牙设备,这里由于暂未使用此功能,直接返回了空的list集合</span>
    <span class="token keyword">return</span> <span class="token function">arrayListOf</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token comment">/**
 * 检查设备是否支持蓝牙功能
 */</span>
<span class="token keyword">private</span> <span class="token keyword">fun</span> <span class="token function">supportBluetooth</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> Boolean <span class="token punctuation">{<!-- --></span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>mBlueAdapter <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        <span class="token comment">//通过判断蓝牙适配器是否为空,如果未空直接返回蓝牙关闭状态false</span>
        mBlueSwitchCallback<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">onStateChange</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> <span class="token boolean">true</span>
<span class="token punctuation">}</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208

定义BlueConector接口,连接指定设备或者mac蓝牙设备,断开蓝牙设备

/**
 *author  : Frank
 *e-mail  : zhuhuitao_struggle@163.com
 *date    : 2021/1/15 15:07
 *desc    :
 *version :
 */
interface BlueConnector {
    /**
     * 尝试连接一个指定蓝牙设备
     *
     * @param device          所要连接的设备
     * @param connectCallback 连接状态回调
     * @param adapter         设备蓝牙适配器
     */
    fun connect(
        adapter: BluetoothAdapter?,
        device: BluetoothDevice?,
        connectCallback: BlueConnectCallback?
    )
<span class="token comment">/**
 * 尝试连接一个指定mac的蓝牙设备
 *
 * @param mac             要连接的蓝牙设备mac地址
 * @param connectCallback 连接状态回调
 * @param adapter         设备蓝牙适配器
 */</span>
fun <span class="token function">connect</span><span class="token punctuation">(</span>
    adapter<span class="token operator">:</span> <span class="token class-name">BluetoothAdapter</span><span class="token operator">?</span><span class="token punctuation">,</span>
    mac<span class="token operator">:</span> <span class="token class-name">String</span><span class="token operator">?</span><span class="token punctuation">,</span>
    connectCallback<span class="token operator">:</span> <span class="token class-name">BlueConnectCallback</span><span class="token operator">?</span>
<span class="token punctuation">)</span>

<span class="token comment">/**
 * 设备重连,只适用于当前已连接的设备
 */</span>
fun <span class="token function">reconnect</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">/**
 * 尝试断开当前连接的蓝牙设备
 */</span>
fun <span class="token function">disconnect</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">/**
 * 获取当前连接的蓝牙设备socket
 *
 * @return
 */</span>
fun <span class="token function">getBlueSocket</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token class-name">BluetoothSocket</span><span class="token operator">?</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

定义BlueConnector接口实现类BlueConnectorImpl

/**
 *author  : Frank
 *e-mail  : zhuhuitao_struggle@163.com
 *date    : 2021/1/15 15:34
 *desc    :
 *version :
 */
class BlueConnectorImpl : BlueConnector {
    //蓝牙适配器
    private var mBlueAdapter: BluetoothAdapter? = null
<span class="token comment">//当前连接的蓝牙设备</span>
<span class="token keyword">private</span> <span class="token keyword">var</span> mDevice<span class="token operator">:</span> BluetoothDevice<span class="token operator">?</span> <span class="token operator">=</span> <span class="token keyword">null</span>

<span class="token comment">//socket</span>
<span class="token keyword">private</span> <span class="token keyword">var</span> mBlueSocket<span class="token operator">:</span> BluetoothSocket<span class="token operator">?</span> <span class="token operator">=</span> <span class="token keyword">null</span>

<span class="token comment">//连接状态回调</span>
<span class="token keyword">private</span> <span class="token keyword">var</span> mBlueConnectCallback<span class="token operator">:</span> BlueConnectCallback<span class="token operator">?</span> <span class="token operator">=</span> <span class="token keyword">null</span>

<span class="token keyword">companion</span> <span class="token keyword">object</span> <span class="token punctuation">{<!-- --></span>
    <span class="token comment">//半生对象</span>
    <span class="token keyword">val</span> instant <span class="token operator">=</span> <span class="token function">BlueConnectorImpl</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">val</span> CBT_UUID<span class="token operator">:</span> UUID <span class="token operator">=</span> UUID<span class="token punctuation">.</span><span class="token function">fromString</span><span class="token punctuation">(</span><span class="token string">"00001101-0000-1000-8000-00805F9B34FB"</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token comment">/**
 * 指定连接一台蓝牙设备
 */</span>
<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">connect</span><span class="token punctuation">(</span>
    adapter<span class="token operator">:</span> BluetoothAdapter<span class="token operator">?</span><span class="token punctuation">,</span>
    device<span class="token operator">:</span> BluetoothDevice<span class="token operator">?</span><span class="token punctuation">,</span>
    connectCallback<span class="token operator">:</span> BlueConnectCallback<span class="token operator">?</span>
<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>device <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>mDevice<span class="token operator">?</span><span class="token punctuation">.</span>address <span class="token operator">==</span> device<span class="token punctuation">.</span>address<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
            <span class="token function">reconnect</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
            <span class="token keyword">return</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    <span class="token comment">//赋值</span>
    mDevice <span class="token operator">=</span> device
    <span class="token keyword">if</span> <span class="token punctuation">(</span>adapter <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">return</span>
    mBlueAdapter <span class="token operator">=</span> adapter
    mBlueConnectCallback <span class="token operator">=</span> connectCallback
    <span class="token comment">//声明临时的socket对象</span>
    <span class="token keyword">var</span> temp<span class="token operator">:</span> BluetoothSocket<span class="token operator">?</span> <span class="token operator">=</span> <span class="token keyword">null</span>
    <span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span>
        <span class="token keyword">val</span> uuid <span class="token operator">=</span> CBT_UUID <span class="token operator">?:</span> <span class="token keyword">return</span>
        <span class="token comment">//获取蓝牙socket对象</span>
        temp <span class="token operator">=</span> mDevice<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">createRfcommSocketToServiceRecord</span><span class="token punctuation">(</span>uuid<span class="token punctuation">)</span>
    <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>e<span class="token operator">:</span> Exception<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        mBlueConnectCallback<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">connectFailed</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>temp <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        mBlueConnectCallback<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">connectFailed</span><span class="token punctuation">(</span><span class="token function">IOException</span><span class="token punctuation">(</span><span class="token string">"Bluetooth connect failed..."</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token keyword">return</span>
    <span class="token punctuation">}</span>
    mBlueSocket <span class="token operator">=</span> temp
    <span class="token function">connect</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token comment">/**
 * 根据指定的mac 连接一台蓝牙设备
 */</span>
<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">connect</span><span class="token punctuation">(</span>
    adapter<span class="token operator">:</span> BluetoothAdapter<span class="token operator">?</span><span class="token punctuation">,</span>
    mac<span class="token operator">:</span> String<span class="token operator">?</span><span class="token punctuation">,</span>
    connectCallback<span class="token operator">:</span> BlueConnectCallback<span class="token operator">?</span>
<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>adapter <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">return</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>mac<span class="token punctuation">.</span><span class="token function">isNullOrEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>connectCallback <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">return</span>
    <span class="token comment">//赋值</span>
    mBlueAdapter <span class="token operator">=</span> adapter
    mBlueConnectCallback <span class="token operator">=</span> connectCallback
    mDevice <span class="token operator">=</span> mBlueAdapter<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">getRemoteDevice</span><span class="token punctuation">(</span>mac<span class="token punctuation">)</span> <span class="token operator">?:</span> <span class="token keyword">return</span>
    <span class="token keyword">var</span> temp<span class="token operator">:</span> BluetoothSocket<span class="token operator">?</span> <span class="token operator">=</span> <span class="token keyword">null</span>
    <span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span>
        temp <span class="token operator">=</span> mDevice<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">createInsecureRfcommSocketToServiceRecord</span><span class="token punctuation">(</span>CBT_UUID<span class="token punctuation">)</span>
    <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>e<span class="token operator">:</span> Exception<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        mBlueConnectCallback<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">connectFailed</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>temp <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        mBlueConnectCallback<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">connectFailed</span><span class="token punctuation">(</span><span class="token function">IOException</span><span class="token punctuation">(</span><span class="token string">"Bluetooth connect failed..."</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token keyword">return</span>
    <span class="token punctuation">}</span>
    mBlueSocket <span class="token operator">=</span> temp
    <span class="token function">connect</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token comment">/**
 * 重连
 */</span>
<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">reconnect</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token function">connect</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token comment">/**
 * 断开蓝牙设备
 */</span>
<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">disconnect</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>mBlueSocket <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">return</span>
    mBlueSocket<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    mBlueSocket <span class="token operator">=</span> <span class="token keyword">null</span>
    mBlueAdapter <span class="token operator">=</span> <span class="token keyword">null</span>
    mDevice <span class="token operator">=</span> <span class="token keyword">null</span>
<span class="token punctuation">}</span>

<span class="token comment">/**
 * 获取当前连接的蓝牙socket对象
 */</span>
<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">getBlueSocket</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> BluetoothSocket<span class="token operator">?</span> <span class="token punctuation">{<!-- --></span>
    <span class="token keyword">return</span> mBlueSocket
<span class="token punctuation">}</span>

<span class="token keyword">private</span> <span class="token keyword">fun</span> <span class="token function">connect</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    LogUtil<span class="token punctuation">.</span><span class="token function">debug</span><span class="token punctuation">(</span><span class="token string">"开始连接蓝牙设备..."</span><span class="token punctuation">)</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>mBlueSocket <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">return</span>
    <span class="token keyword">try</span> <span class="token punctuation">{<!-- --></span>
        <span class="token comment">//建立子任务,开始连接connect,不阻塞UI线程</span>
        GlobalScope<span class="token punctuation">.</span><span class="token function">launch</span> <span class="token punctuation">{<!-- --></span>
            runCatching <span class="token punctuation">{<!-- --></span>
                mBlueSocket<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">connect</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
            <span class="token punctuation">}</span><span class="token punctuation">.</span><span class="token function">onSuccess</span> <span class="token punctuation">{<!-- --></span>
                <span class="token comment">//这里可以回调成功,为了准确还可以以系统广播连接成功为准</span>
                mBlueConnectCallback<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">connectSuccess</span><span class="token punctuation">(</span>mBlueSocket<span class="token operator">!!</span><span class="token punctuation">,</span> mDevice<span class="token punctuation">)</span>
                LogUtil<span class="token punctuation">.</span><span class="token function">debug</span><span class="token punctuation">(</span><span class="token string">"蓝牙连接成功...."</span><span class="token punctuation">)</span>
            <span class="token punctuation">}</span><span class="token punctuation">.</span><span class="token function">onFailure</span> <span class="token punctuation">{<!-- --></span>
                <span class="token comment">//当抛出异常直接回调连接失败</span>
                mBlueConnectCallback<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">connectFailed</span><span class="token punctuation">(</span>it<span class="token punctuation">)</span>
                LogUtil<span class="token punctuation">.</span><span class="token function">debug</span><span class="token punctuation">(</span><span class="token string">"蓝牙设备连接失败...."</span><span class="token punctuation">)</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>e<span class="token operator">:</span> Exception<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        <span class="token comment">//回调连接失败</span>
        mBlueConnectCallback<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">connectFailed</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span>
        LogUtil<span class="token punctuation">.</span><span class="token function">debug</span><span class="token punctuation">(</span><span class="token string">"蓝牙设备连接失败..."</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143

定义系统广播接收者BluetoothReceiver extends BroadcastReceiver

/**
 *author  : Frank
 *e-mail  : zhuhuitao_struggle@163.com
 *date    : 2021/1/16 9:55
 *desc    :
 *version :
 */
class BluetoothReceiver(ctx: Context, client: BlueClient) : BroadcastReceiver() {
    private var mClient: BlueClient = client
<span class="token keyword">init</span> <span class="token punctuation">{<!-- --></span>
    <span class="token keyword">val</span> filter <span class="token operator">=</span> <span class="token function">IntentFilter</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token comment">//蓝牙开关状态</span>
    filter<span class="token punctuation">.</span><span class="token function">addAction</span><span class="token punctuation">(</span>BluetoothAdapter<span class="token punctuation">.</span>ACTION_STATE_CHANGED<span class="token punctuation">)</span>
    <span class="token comment">//蓝牙开始扫描状态</span>
    filter<span class="token punctuation">.</span><span class="token function">addAction</span><span class="token punctuation">(</span>BluetoothAdapter<span class="token punctuation">.</span>ACTION_DISCOVERY_STARTED<span class="token punctuation">)</span>
    <span class="token comment">//蓝牙扫描结束</span>
    filter<span class="token punctuation">.</span><span class="token function">addAction</span><span class="token punctuation">(</span>BluetoothAdapter<span class="token punctuation">.</span>ACTION_DISCOVERY_FINISHED<span class="token punctuation">)</span>
    <span class="token comment">//蓝牙扫描发现新设备(未配对)</span>
    filter<span class="token punctuation">.</span><span class="token function">addAction</span><span class="token punctuation">(</span>BluetoothDevice<span class="token punctuation">.</span>ACTION_FOUND<span class="token punctuation">)</span>
    <span class="token comment">//蓝牙配对状态改变</span>
    filter<span class="token punctuation">.</span><span class="token function">addAction</span><span class="token punctuation">(</span>BluetoothDevice<span class="token punctuation">.</span>ACTION_BOND_STATE_CHANGED<span class="token punctuation">)</span>
    <span class="token comment">//设备建立连接</span>
    filter<span class="token punctuation">.</span><span class="token function">addAction</span><span class="token punctuation">(</span>BluetoothDevice<span class="token punctuation">.</span>ACTION_ACL_CONNECTED<span class="token punctuation">)</span>
    <span class="token comment">//设备断开连接</span>
    filter<span class="token punctuation">.</span><span class="token function">addAction</span><span class="token punctuation">(</span>BluetoothDevice<span class="token punctuation">.</span>ACTION_ACL_DISCONNECTED<span class="token punctuation">)</span>
    <span class="token comment">//蓝牙适配器连接状态改变</span>
    filter<span class="token punctuation">.</span><span class="token function">addAction</span><span class="token punctuation">(</span>BluetoothAdapter<span class="token punctuation">.</span>ACTION_CONNECTION_STATE_CHANGED<span class="token punctuation">)</span>
    <span class="token comment">//BluetoothA2dp连接状态</span>
    filter<span class="token punctuation">.</span><span class="token function">addAction</span><span class="token punctuation">(</span>BluetoothA2dp<span class="token punctuation">.</span>ACTION_CONNECTION_STATE_CHANGED<span class="token punctuation">)</span>
    filter<span class="token punctuation">.</span><span class="token function">addAction</span><span class="token punctuation">(</span><span class="token string">"android.media.VOLUME_CHANGED_ACTION"</span><span class="token punctuation">)</span>
    ctx<span class="token punctuation">.</span><span class="token function">registerReceiver</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> filter<span class="token punctuation">)</span>
    <span class="token comment">//创建心跳机制 这里为了节省开销,可以在蓝牙设备连接成功后在建立心跳机制,这里为了简单直接在此初始化</span>
    <span class="token function">createHeartBeat</span><span class="token punctuation">(</span>mClient<span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">onReceive</span><span class="token punctuation">(</span>context<span class="token operator">:</span> Context<span class="token operator">?</span><span class="token punctuation">,</span> intent<span class="token operator">:</span> Intent<span class="token operator">?</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token keyword">val</span> action <span class="token operator">=</span> intent<span class="token operator">?</span><span class="token punctuation">.</span>action <span class="token operator">?:</span> <span class="token keyword">return</span>
    <span class="token keyword">when</span> <span class="token punctuation">(</span>action<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        BluetoothAdapter<span class="token punctuation">.</span>ACTION_STATE_CHANGED <span class="token operator">-&gt;</span> <span class="token punctuation">{<!-- --></span>
            <span class="token keyword">val</span> state <span class="token operator">=</span> intent<span class="token punctuation">.</span><span class="token function">getIntExtra</span><span class="token punctuation">(</span>BluetoothAdapter<span class="token punctuation">.</span>EXTRA_STATE<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>
            BlueClientImpl<span class="token punctuation">.</span>isOPen <span class="token operator">=</span> <span class="token punctuation">(</span>state <span class="token operator">==</span> BluetoothAdapter<span class="token punctuation">.</span>STATE_ON<span class="token punctuation">)</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>BlueClientImpl<span class="token punctuation">.</span>isOPen<span class="token punctuation">)</span>
            <span class="token comment">//当蓝牙设备为开启状态时回调给上层操作对象</span>
                mClient<span class="token punctuation">.</span><span class="token function">onBlueState</span><span class="token punctuation">(</span>state<span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
        BluetoothAdapter<span class="token punctuation">.</span>ACTION_DISCOVERY_STARTED <span class="token operator">-&gt;</span> <span class="token punctuation">{<!-- --></span>
            <span class="token comment">//start scan bluetooth device</span>
        <span class="token punctuation">}</span>

        BluetoothAdapter<span class="token punctuation">.</span>ACTION_DISCOVERY_FINISHED <span class="token operator">-&gt;</span> <span class="token punctuation">{<!-- --></span>
            <span class="token comment">//接收到系统停止扫描设备广播</span>
            mClient<span class="token punctuation">.</span><span class="token function">onStopScan</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span>

        BluetoothDevice<span class="token punctuation">.</span>ACTION_FOUND <span class="token operator">-&gt;</span> <span class="token punctuation">{<!-- --></span>
            <span class="token comment">//接收到系统扫描到周围的蓝牙设备</span>
            mClient<span class="token punctuation">.</span><span class="token function">onFind</span><span class="token punctuation">(</span>
                intent<span class="token punctuation">.</span>getParcelableExtra<span class="token operator">&lt;</span>BluetoothDevice<span class="token operator">&gt;</span><span class="token punctuation">(</span>BluetoothDevice<span class="token punctuation">.</span>EXTRA_DEVICE<span class="token punctuation">)</span>
                    <span class="token operator">?:</span> <span class="token keyword">return</span>
            <span class="token punctuation">)</span>
        <span class="token punctuation">}</span>

        BluetoothDevice<span class="token punctuation">.</span>ACTION_BOND_STATE_CHANGED <span class="token operator">-&gt;</span> <span class="token punctuation">{<!-- --></span>
            <span class="token comment">//蓝牙配对状态回调</span>
            <span class="token keyword">val</span> device <span class="token operator">=</span>
                intent<span class="token punctuation">.</span>getParcelableExtra<span class="token operator">&lt;</span>BluetoothDevice<span class="token operator">&gt;</span><span class="token punctuation">(</span>BluetoothDevice<span class="token punctuation">.</span>EXTRA_DEVICE<span class="token punctuation">)</span>
                    <span class="token operator">?:</span> <span class="token keyword">return</span>
            mClient<span class="token punctuation">.</span><span class="token function">bondStatus</span><span class="token punctuation">(</span>device<span class="token punctuation">)</span>
        <span class="token punctuation">}</span>

        BluetoothDevice<span class="token punctuation">.</span>ACTION_ACL_CONNECTED <span class="token operator">-&gt;</span> <span class="token punctuation">{<!-- --></span>
            <span class="token comment">//蓝牙连接状态回到</span>
            <span class="token keyword">val</span> device <span class="token operator">=</span>
                intent<span class="token punctuation">.</span>getParcelableExtra<span class="token operator">&lt;</span>BluetoothDevice<span class="token operator">&gt;</span><span class="token punctuation">(</span>BluetoothDevice<span class="token punctuation">.</span>EXTRA_DEVICE<span class="token punctuation">)</span>
                    <span class="token operator">?:</span> <span class="token keyword">return</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>device<span class="token punctuation">.</span>bondState <span class="token operator">==</span> <span class="token number">12</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                <span class="token comment">//如果绑定状态为12 则判断蓝牙连接成功,可以发起回调通知UI层,前面通过协程任务我们已经知道</span>
                <span class="token comment">//蓝牙连接是否成功,此处将不再回调,</span>
                <span class="token comment">// mClient.onConnected(device)</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>

        BluetoothDevice<span class="token punctuation">.</span>ACTION_ACL_DISCONNECTED <span class="token operator">-&gt;</span> <span class="token punctuation">{<!-- --></span>
            <span class="token comment">//蓝牙设备断开</span>
            <span class="token keyword">val</span> device <span class="token operator">=</span>
                intent<span class="token punctuation">.</span>getParcelableExtra<span class="token operator">&lt;</span>BluetoothDevice<span class="token operator">&gt;</span><span class="token punctuation">(</span>BluetoothDevice<span class="token punctuation">.</span>EXTRA_DEVICE<span class="token punctuation">)</span>
                    <span class="token operator">?:</span> <span class="token keyword">return</span>
            <span class="token comment">//由于我们这里连接的是打印机,所以判断如果不是蓝牙打印机设备,不做处理,这里的设备类型,查看了源码,直接写成了</span>
            <span class="token comment">//1536 和 7936  具体类型可以前往系统源码Device查看</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">isPrinter</span><span class="token punctuation">(</span>device<span class="token punctuation">.</span>bluetoothClass<span class="token punctuation">.</span>majorDeviceClass<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span>
            <span class="token comment">//如果是人为,不做重连处理</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>isArtifical<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                <span class="token comment">//回调蓝牙断开状态</span>
                mClient<span class="token punctuation">.</span><span class="token function">onDisconnect</span><span class="token punctuation">(</span>device<span class="token punctuation">)</span>
                <span class="token keyword">return</span>
            <span class="token punctuation">}</span>
            mClient<span class="token punctuation">.</span><span class="token function">onReconnect</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104

使用

  • 初始化BlueClint对象
 BlueClientImpl.instance.init(context).enableDebug(true)
  • 1
  • 开始操作蓝牙
  BlueClientImpl.instance.onStartScan(object : ScanCallback {
            override fun onStartScan(isOn: Boolean) {
                mViewModel.isScanning.set(true)
            }
        <span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">onStopScan</span><span class="token punctuation">(</span>deviceList<span class="token operator">:</span> MutableList<span class="token operator">&lt;</span>BluetoothDevice<span class="token operator">&gt;</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
            mViewModel<span class="token punctuation">.</span>isScanning<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span>

        <span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">onFindDevice</span><span class="token punctuation">(</span>device<span class="token operator">:</span> BluetoothDevice<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>device<span class="token punctuation">.</span>name <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">return</span>
            mSystemList<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>device<span class="token punctuation">)</span>
            mAdapter<span class="token punctuation">.</span><span class="token function">addData</span><span class="token punctuation">(</span><span class="token function">BluetoothSimpleDevice</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> device<span class="token punctuation">.</span>name<span class="token punctuation">,</span> device<span class="token punctuation">.</span>address<span class="token punctuation">,</span> <span class="token string">"89"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

注意事项

在扫描周围蓝牙设备的时候一定要开启定位权限,不然无法获取到周围的蓝牙设备(特别注意),6.0以上设备需要动态申请定位权限,manifest清单文件申请蓝牙操作必要的权限:

 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
 <uses-permission android:name="android.permission.BLUETOOTH" />
 <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
  • 1
  • 2
  • 3

总结

通过以上几个重要的步骤,我们基本实现了蓝牙的开启,扫描周围设备,连接一台蓝牙设备,断开蓝牙设备等常用功能,当然其中仍然存在许多优化的细节,大体思路和方向我觉得还是正确和行的通,毕竟在项目中已经使用了此方案,代码我会在写完第二部分上传到github,代码我也将会持续更新,由于我自身技术水平受限,可能由于思考问题不全面,如果觉得写的不好,请勿喷,也欢迎指教和issue。

针对蓝牙相关问题,我已做了相关lib,如果想了解,请查阅Anddroid链接蓝牙打印机

posted @ 2024-04-12 09:43  一贴灵  阅读(17)  评论(0编辑  收藏  举报
学以致用,效率第一