提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
第一次开源,一个flutter蓝牙开发的小插件。之前写的文章有点看不下去了,刚好我这段时间有时间,所以有时间升级了一下当前的代码,然后所以把插件上传到了谷歌插件库中 https://pub.flutter-io.cn/packages/ble ,有需要可以看看,顺便star一下。
项目github地址:https://github.com/laoeg/Ble (项目源码)
项目dev地址:https://pub.flutter-io.cn/packages/ble(使用文档)
前面三张是iOS端的,后面加了一张Android端的,可以对比一下效果
flutter ble plugin是基于Android,ISO的蓝牙插件,提供扫描,连接,发送指令等一系列功能的插件。插件功能稳定,不管是需要做Flutter,Android还是iOS端的蓝牙功能,都可以使用该插件。
插件已上传 https://pub.flutter-io.cn/ 谷歌插件库中,直接搜索 ble就可以找到。
引入(示例):
dependencies:
ble: ^2.0.0
下载插件(示例):
$ flutter pub get
导入包(示例):
import 'package:ble/ble.dart';
初始化提供了单列,在项目启动的时候调用Ble.getInstance()即可。后面所有使用到Ble()对象的时候都是使用的此单列。
//初始化
Ble.getInstance();
//也可以这样,但是你看看源码你会发现调用的都是getInstance方法
Ble();
事件:底层发送事件,flutter实现接口,监听各种蓝牙事件。
// 要实现的接口
abstract class DeviceListener {
// 扫描开始
void onScanStart() {}
// 发现蓝牙设备
void onFoundDevice(List<DeviceBle> devices) {}
// 停止扫描
void onScanStop() {}
// 蓝牙连接状态发送改变
void onConnectionStateChange(int status) {
print("flutter插件监听到蓝牙状态发送改变:" + (status == 4 ? "蓝牙连接上了" : "蓝牙断开了"));
}
// 收到数据
void onReceivedDataListener(List<dynamic> byteData) {
print("插件接收到数据:" + byteData.toString());
}
// 发现服务
void onServicesDiscovered() {}
// 没有发现可以用的服务
void onServicesNotSupport() {}
// 蓝牙关闭
void onBluetoothOff() {}
// 蓝牙开启
void onBluetoothOn() {}
// 重连成功
void onReConnected() {}
// 发现服务和服务下的特征值
void onServiceCharac(Map data){}
}
// 设置监听
Ble.getInstance().setDeviceListenner(this);
// 开启扫描
Ble.getInstance().startScanBluetooth;
// 停止扫描
Ble.getInstance().stopScanBluetooth;
// 是否支持蓝牙
Ble.getInstance().isSpport;
// 蓝牙是否打开
Ble.getInstance().isEnabled;
// 连接蓝牙
Ble.getInstance().connect(uuid);
// 打开蓝牙
Ble.getInstance().enabled();
// 断开蓝牙连接
Ble.getInstance().disconnect();
// 发送ASCALL
Ble.getInstance().sendCommend(command);
// 发送十进制
Ble.getInstance().sendCommand(command);
// 设置写特征值
Ble.getInstance().setWriteCharator(uuid);
// 设置通知特征值
Ble.getInstance().setNotifyCharator(uuid,isNotify);
Android端处理flutter端发送过来的事件。
// flutter调用原生Android处理方法
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
switch (call.method) {
case "getPlatformVersion":
result.success("Android " + android.os.Build.VERSION.RELEASE);
break;
case "isSupport":
result.success(isSupport());
break;
case "isEnabled":
result.success(isEnabled());
break;
case "startScanBluetooth":
result.success(startScanBluetooth());
break;
case "stopScanBluetooth":
stopScanBluetooth();
break;
case "connect":
connect(call.argument("address").toString());
break;
case "enabled":
enabled();
break;
case "disconnect":
disconnect();
break;
case "status":
result.success(status());
break;
case "isConnect":
result.success(isConnect());
break;
case "auth":
auth(call.argument("authCode").toString().getBytes());
break;
case "broadcastData":
broadcastData(call.argument("command").toString().getBytes());
break;
case "isCommanding":
result.success(mService.sendingStoredData);
break;
default:
result.notImplemented();
break;
}
}
}
IOS端处理flutter端发送过来的事件。
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
NSLog(@"handleMethodCall=======%@",call.method);
if ([@"getPlatformVersion" isEqualToString:call.method]) {
result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);
}else if([@"initTargetUUID" isEqualToString:call.method]){
NSMutableDictionary* dic = call.arguments;
NSString* targetServiceUUID = [dic objectForKey:@"targetServiceUUID"];
NSString* targetWriteCharacriticUUID = [dic objectForKey:@"targetWriteCharacriticUUID"];
NSString* targetReadCharacriticUUID = [dic objectForKey:@"targetReadCharacriticUUID"];
_targetServiceUUID = targetServiceUUID;
_targetWriteCharacteristicUUID = targetWriteCharacriticUUID;
_targetreadCharacteristicUUID = targetReadCharacriticUUID;
}else if([@"isSupport" isEqualToString:call.method]){
return result([NSNumber numberWithBool:_isSupport?YES:NO]);
} else if([@"isEnabled" isEqualToString:call.method]){
return result([NSNumber numberWithBool:_isEnable?YES:NO]);
}else if([@"startScanBluetooth" isEqualToString:call.method]){
if(!_targetServiceUUID||!_targetWriteCharacteristicUUID||!_targetreadCharacteristicUUID){
NSLog(@"没有初始化目标服务UUID或目标写特征值或目标读特征值");
return;
}
//停止之前的连接
[_centralManager stopScan];
[_centralManager scanForPeripheralsWithServices:nil options:nil];
// 清空存储蓝牙设备的数组
peripheralDataArray = [[NSMutableArray alloc]init];
_eventSink([self sendEvent:START_SACN data:@"start scan ble"]);
//baby.scanForPeripherals().begin().stop(10);
return result([NSNumber numberWithBool:YES]);
}else if([@"stopScanBluetooth" isEqualToString:call.method]){
[_centralManager stopScan ];
if(![_centralManager isScanning]){
_eventSink([self sendEvent:STOP_SACN data:@"stop scan ble"]);
}
}else if([@"connect" isEqualToString:call.method]){
NSMutableDictionary* dic = call.arguments;
NSString* address = [dic objectForKey:@"address"];
NSLog(@"address:%@",address);
NSArray *peripherals = [peripheralDataArray valueForKey:@"peripheral"];
if(peripherals.count<=0){
NSLog(@"数组中没有数据");
if(!_targetServiceUUID||!_targetWriteCharacteristicUUID||!_targetreadCharacteristicUUID){
NSLog(@"没有初始化目标服务UUID或目标写特征值或目标读特征值");
return;
}
tempAddress = address;
//扫描查找uuid和tempAddress(重连地址)一样的蓝牙设备,找到后直接连接。不设置超时时间
[_centralManager stopScan];
[_centralManager scanForPeripheralsWithServices:nil options:nil];
return;
}else{
tempAddress = nil;
}
for (CBPeripheral* peripheral in peripherals) {
NSLog(@"ios 遍历数组,peripheral.name=%@",peripheral.name);
NSLog(@"ios 遍历数组,peripheral.identifier=%@",peripheral.identifier.UUIDString);
if([peripheral.identifier.UUIDString isEqualToString: address]){
NSLog(@"ios 在数组中找到了对应的peripheral=================");
[_centralManager stopScan];
[_centralManager connectPeripheral:peripheral options:nil];
_peripheral = peripheral;
_state = 1;
break;
}
}
}else if([@"disconnect" isEqualToString:call.method]){
if(_centralManager && _peripheral){
if(_isConnected){
[_centralManager cancelPeripheralConnection:_peripheral];
}
}else{
[_centralManager stopScan];
}
}else if([@"status" isEqualToString:call.method]){
return result([NSNumber numberWithBool:_state]);
}else if([@"isConnect" isEqualToString:call.method]){
return result([NSNumber numberWithBool:_isConnected?YES:NO]);
}else if([@"auth" isEqualToString:call.method]){
// 发送数据给蓝牙外设
NSMutableDictionary* dic = call.arguments;
NSString* authCode = [dic objectForKey:@"authCode"];
NSLog(@"authCode:%@",authCode);
//发送数据给蓝牙设备
[_peripheral writeValue:[authCode dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:_writeCharacteristic type:CBCharacteristicWriteWithoutResponse];
}else if([@"broadcastData" isEqualToString:call.method]){
NSMutableDictionary* dic = call.arguments;
NSString* command = [dic objectForKey:@"command"];
NSLog(@"command:%@",command);
[_peripheral writeValue:[command dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:_writeCharacteristic type:CBCharacteristicWriteWithoutResponse];
}else if([@"isCommanding" isEqualToString:call.method]){
//是否正在发送指令,不支持iso,支持安卓
return result([NSNumber numberWithBool:NO]);
}else {
result(FlutterMethodNotImplemented);
}
}
不需要打赏,有时间请star一下吧!有什么问题直接联系我把,QQ:2912842867。
项目github地址:https://github.com/laoeg/Ble (项目源码)
项目dev地址:https://pub.flutter-io.cn/packages/ble(使用文档)