android下载模块封装,Android 蓝牙模块的封装

引入

结合项目中的开发需求,经常需要在一个app中连接多种设备,如果设备的传输协议一致的话,那么设备与app之间传输指令可以公用一套代码。可是现实情况复杂,经常项目开发到一半就需要兼容新的设备。如果在项目的一开始,就可以做一个高扩展的兼容多设备的sdk,那么不管是以后其他项目使用,还是再添加新设备兼容,都将是一个不错的选择。

android提供的api简介

获取蓝牙的管理adapter(在获取之前,记得检查权限)

private BluetoothAdapter mBluetoothAdapter;

// Initializes Bluetooth adapter.

final BluetoothManager bluetoothManager =

(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);

mBluetoothAdapter = bluetoothManager.getAdapter();

检查蓝牙是否可用,返回true,表明支持4.0低功耗蓝牙。

mBluetoothAdapter.isEnabled()

扫描蓝牙设备

BluetoothAdapter.LeScanCallback为扫描的回调函数。扫描到了设备,会在onLeScan中回调(不过要留意的是,同一个设备可能会被多次返回,在显示时,记得通过mac码进行筛选)。

开启和停止扫描的方法也很方便。

// Device scan callback.

private BluetoothAdapter.LeScanCallback mLeScanCallback =

new BluetoothAdapter.LeScanCallback() {

@Override

public void onLeScan(final BluetoothDevice device, int rssi,

byte[] scanRecord) {

//device 为扫描到的设备

}

};

mBluetoothAdapter.startLeScan(mLeScanCallback);

mBluetoothAdapter.stopLeScan(mLeScanCallback);

下来就是连接设备了, 其中 import android.bluetooth.BluetoothGattCallback;是一个抽象类。与蓝牙设备的连接回调都在这个类中。分别是:

onConnectionStateChange 连接状态改变。当判断这个方法的入参数符合以下两个条件时,则表示已经连接成功(蓝牙设备给手机传输数据时是通过设备的通道传输数据的,但是连接上之后,设备的通道此时并没有打开,此时可进行通道打开操作)。

status == GATT_SUCCESS && newState == BluetoothGatt.STATE_CONNECTED

onServicesDiscovered 发现服务

onCharacteristicRead 读取字符

onCharacteristicWrite 写入指令成功

onCharacteristicChanged 蓝牙回传数据处理

onDescriptorRead 读的描述返回

onDescriptorWrite 写的描述返回

onReliableWriteCompleted

onReadRemoteRssi 手机距离设备的远近

BluetoothDevice remoteDevice = mBluetoothAdapter.getRemoteDevice(address);

BluetoothGatt bluetoothGatt = remoteDevice.connectGatt(appContext, isAutoConnect, mBluetoothGattCallback);

发送数据给蓝牙设备(其中服务通道,数据通道,指令,是根据蓝牙设备协议确定的)

String serveGallery = "xxx-xxx-xxx-xxx";//服务通道

String gallery = "xxx-xxx-xxx-xxx";//数据通道

BluetoothGattCharacteristic bluetoothGattCharacteristic = bleGattCharMap.get(serveGallery).get(gallery);

bluetoothGattCharacteristic.setValue(new byte[]{ (byte) 0XBE, 0X02,0X03, (byte) 0XED}); //byte 为指令

bluetoothGatt.writeCharacteristic(bluetoothGattCharacteristic);

发送数据成功后,返回的数据会在上面实例的BluetoothGattCallback类的回调方法中回应,再根据业务需求做相应的处理。

以上是android api中提供的蓝牙的基本使用流程。

现在已经大致知道了怎么使用android api 进行蓝牙连接,可是我们也知道一个蓝牙设备会有好多服务通道(大通道)和下面的数据通道(小通道),每个设备会有很多指令集,往往实际应用中,集成一个蓝牙硬件,光是浏览协议中提供了哪些指令和功能,就已经够花费时间了,更别说集成了。最后终于根据协议,一个一个解析接入完了。这个时候要是老板和产品过来说又要加设备,那之前的代码是不是能够满足再加一个的需求。另外,下一次要再另外一个项目中集成这个设备,是不是又要重新解析接入一遍所有的协议指令。这些问题,光想想,都脑壳疼了。最好有个蓝牙的sdk,直接导入进来可以开发使用,不用在意输入输出指令的解析,那就太好了。于是,就有了下来要讨论的问题。

具体实现

因为要撸这样的一个框架,代码非常多,而且每个蓝牙设备的协议,都不尽相同,所以我尽量按照讲一下整个思路。

设计一个BleManager的管理类,全权处理app中有关蓝牙操作的所有事宜。

BleManager与app中的activity或者service 利用java提供的Obervable观察者模式,将所有的数据返回到服务里面或者UI层(我个人的思路是在blemanager和UI层之间在有一个service做衔接,这样就可以在app运行期间,不管在哪个界面,都可以去与蓝牙交互,蓝牙设备有信息,可以直接通知到UI层。)。

连接过程

BleManager设计为单例。提供一个init(Context appContext)方法,用于初始化BluetoothAdapter对象,设置为manager的成员变量。

初始化之后是扫描,创建一个扫描的回调,这个回调返回一个list集合或只返回一个设备。

BleManager中有四个主要方法,分别为开始扫描,停止扫描,连接设备,设置指令。

然后是连接设备,当用户点击了一个设备条目,我们会拿到这个设备的名字,mac等信息。我们的框架在设计时,需要一个Driver的接口,表示一个所有设备的父类。

创建一个driver包,在包下面有一个driverimpl的实现包。

每一种设备,都有一种设备名字,根据实际情况,可能是手环,心率带等等。那么对应的就需要手环driver和心率带driver。下图中用DriverXXX表示。

创建一个Driver工厂专门生成具体的driver。在连接之前,生成一个具体的driver,保存成manager的成员变量。

//连接设备。

public void onConnectDervice(Context appContext, boolean isAutoConnect, MBleDeviceInfo mBleDevice, BleReciveListener listener) {

//mBleDevice是对系统driver的提取,增加了type类型。在扫描时进行的包装

String type = mBleDevice.getType();

driver = DriverFactory.createDriver(type);

BleDevice remoteDevice = bleAdapter.getRemoteDevice(mBleDevice.getAddress());

mBluetoothGattCallback = new MBluetoothGattCallback(driver, listener);

bluetoothGatt = remoteDevice.connectGatt(appContext, isAutoConnect, mBluetoothGattCallback);

}

需要解释一下MBluetoothGattCallback这个类,他是继承系统api中的BluetoothGattCallback,而BleReciveListener 为在调用层实例化,用于返回蓝牙连接的结果。将driver传入,以方便与将蓝牙的回调分发到具体的设备drvier中进行分析处理。下面贴一个转到driverxxx的代码。这样就可根据具体的设备做具体的数据解析了。

@Override

public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

driver.getBleConnactListener()

.onConnectionStateChange(gatt, status, newState, listener);

}

```

BleConnactListener mBleConnactListener = new BleConnactListener() {

//返回的接口方法实现。

//连接状态

@Override

public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState, BleManager.BleReciveListener listener) {

Logger.i(TAG, "BleConnactListener : 连接状态" + Thread.currentThread());

if (status == GATT_SUCCESS && newState == BluetoothGatt.STATE_CONNECTED) {

listener.onConnResult(true);

} else {

//连接失败。

listener.onConnResult(false);

}

}

}

```

* 注:如果要打开通道,可以在连接成功的回调之前去打开,打开完成,再刷新UI,显示连接成功。因为,有些时候,通道不打开,是没有办法与蓝牙交互数据的。

发送指令###

发送指令,调用Manager的setData()方法。其中参数分别表示指令。

//向设备传输数据。

public void setData(Perform perfrom) {

BleCommand command = driver.createCommand(perfrom);

driver.sendData(bluetoothGatt, command);

}

交给drvier去构造一个command命令,里面封装有这条指令的服务通道,数据通道,byte数组等信息。

createCommand过程

这个方法是传到具体的Driverxxx中实现的,方法中,对于具体指令的创建,交给了一个工厂类。

//@param performCommand 所需要创建指令的类型

//@param perfrom 包装参数的父类接口。此处应该传入具体的实现类。

//@return

@Override

public BleCommand createCommond(Perform perfrom) {

BleCommand cmd = null;

switch (performCommand) {//这里要分指令进行。所以要用switch。

case MConstant.PerformCommand.ONE_DAY://设置步距

if (perfrom instanceof PerfromSetStepDistance) {

cmd = new CommandXXXOneDay(perfrom);

}

break;

}

return cmd;

}

CommandXXXOneDay 这是一个指令类。里面封装了具体的这条指令信息:指令的服务通道,数据通道,byte数据等信息。到这里为止,指令创建完成。

发送指令,还是通过driver来。具体的实现和上一篇中相似。

@Override

public void sendData(BleGatt bluetoothGatt, BleCommand command) {

String serveGallery = command.getServeGallery();

String gallery = command.getGallery();

BluetoothGattCharacteristic bluetoothGattCharacteristic =bleGattCharMap.get(serveGallery).get(gallery);

bluetoothGattCharacteristic.setValue(command.getBytes());

bluetoothGatt.writeCharacteristic(bluetoothGattCharacteristic);

}

接收成功的返回

蓝牙数据的回传,在onCharacteristicChanged回调方法中。在下面方法的switch-case中根据蓝牙协议解析具体数据。解析完成,用listener回传到调用层。

@Override

public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, final BleManager.BleReciveListener listener) {

Logger.i(TAG, "BleConnactListener : 蓝牙回传数据接收处理");

//TODO 解析数据。

byte[] data = characteristic.getValue();

if (data != null && data.length > 0) {

StringBuilder stringBuilder = new StringBuilder(data.length);

for (byte byteChar : data) {

stringBuilder.append(String.format("%02X ", byteChar));

}

String lastData = stringBuilder.toString();

String uuid = characteristic.getUuid().toString();

switch (uuid) {

case MConstant.Uuid.W311N.charUuid0:

listener.receiveData(...);

break;

}

}

}

返回的数据,依旧是解析好,封装成具体的bean对象传出去。

总结###

以上,就是大致的思路。

这个框架,可以让调用层不关心具体的指令构建。需要做什么事情,直接传Perform具体实现类(但是这个实现类需是sdk提供的)。

bleManager还可以对外提供支持那些设备的方法。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值