Add Android scan mode setting (#212)

* Add Android scan mode setting

* Format pigeon generated code

* format whole project

* Fix windows compilation because of generated code order

* Fix unwanted imports

* Add doc comment for AndroidOptions

* Update code doc
This commit is contained in:
Rohit Sangwan
2026-01-21 15:32:40 +05:30
committed by GitHub
parent dae2f5dc4d
commit 2f7f1f693d
24 changed files with 744 additions and 108 deletions
+1
View File
@@ -1,6 +1,7 @@
## 1.2.0
* Add `autoConnect` parameter to `connect()` method for automatic reconnection support on Android and iOS/macOS
* Add `serviceData` in `BleDevice`
* Add `AndroidScanMode` and `reportDelayMillis` to `AndroidOptions` for scanning
## 1.1.0
* Add readRssi method
@@ -96,6 +96,20 @@ enum class UniversalBleLogLevel(val raw: Int) {
}
}
/** Scan config */
enum class AndroidScanMode(val raw: Int) {
BALANCED(0),
LOW_LATENCY(1),
LOW_POWER(2),
OPPORTUNISTIC(3);
companion object {
fun ofRaw(raw: Int): AndroidScanMode? {
return values().firstOrNull { it.raw == raw }
}
}
}
/** Unified error codes for all platforms */
enum class UniversalBleErrorCode(val raw: Int) {
UNKNOWN_ERROR(0),
@@ -309,6 +323,77 @@ data class UniversalBleDescriptor (
override fun hashCode(): Int = toList().hashCode()
}
/**
* Android options to scan devices
* [requestLocationPermission] is used to request location permission on Android 12+ (API 31+).
* [scanMode] is used to set the scan mode for for Bluetooth LE scan.
* Set [reportDelayMillis] timestamp for Bluetooth LE scan. If set to 0, you will be notified of scan results immediately.
* If > 0, scan results are queued up and delivered after the requested delay or 5000 milliseconds (whichever is higher).
* Note scan results may be delivered sooner if the internal buffers fill up.
*
* Generated class from Pigeon that represents data sent in messages.
*/
data class AndroidOptions (
val requestLocationPermission: Boolean? = null,
val scanMode: AndroidScanMode? = null,
val reportDelayMillis: Long? = null
)
{
companion object {
fun fromList(pigeonVar_list: List<Any?>): AndroidOptions {
val requestLocationPermission = pigeonVar_list[0] as Boolean?
val scanMode = pigeonVar_list[1] as AndroidScanMode?
val reportDelayMillis = pigeonVar_list[2] as Long?
return AndroidOptions(requestLocationPermission, scanMode, reportDelayMillis)
}
}
fun toList(): List<Any?> {
return listOf(
requestLocationPermission,
scanMode,
reportDelayMillis,
)
}
override fun equals(other: Any?): Boolean {
if (other !is AndroidOptions) {
return false
}
if (this === other) {
return true
}
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
override fun hashCode(): Int = toList().hashCode()
}
/** Generated class from Pigeon that represents data sent in messages. */
data class UniversalScanConfig (
val android: AndroidOptions? = null
)
{
companion object {
fun fromList(pigeonVar_list: List<Any?>): UniversalScanConfig {
val android = pigeonVar_list[0] as AndroidOptions?
return UniversalScanConfig(android)
}
}
fun toList(): List<Any?> {
return listOf(
android,
)
}
override fun equals(other: Any?): Boolean {
if (other !is UniversalScanConfig) {
return false
}
if (this === other) {
return true
}
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
override fun hashCode(): Int = toList().hashCode()
}
/**
* Scan Filters
*
@@ -421,40 +506,55 @@ private open class UniversalBlePigeonCodec : StandardMessageCodec() {
}
130.toByte() -> {
return (readValue(buffer) as Long?)?.let {
UniversalBleErrorCode.ofRaw(it.toInt())
AndroidScanMode.ofRaw(it.toInt())
}
}
131.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
UniversalBleScanResult.fromList(it)
return (readValue(buffer) as Long?)?.let {
UniversalBleErrorCode.ofRaw(it.toInt())
}
}
132.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
UniversalBleService.fromList(it)
UniversalBleScanResult.fromList(it)
}
}
133.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
UniversalBleCharacteristic.fromList(it)
UniversalBleService.fromList(it)
}
}
134.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
UniversalBleDescriptor.fromList(it)
UniversalBleCharacteristic.fromList(it)
}
}
135.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
UniversalScanFilter.fromList(it)
UniversalBleDescriptor.fromList(it)
}
}
136.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
UniversalManufacturerDataFilter.fromList(it)
AndroidOptions.fromList(it)
}
}
137.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
UniversalScanConfig.fromList(it)
}
}
138.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
UniversalScanFilter.fromList(it)
}
}
139.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
UniversalManufacturerDataFilter.fromList(it)
}
}
140.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
UniversalManufacturerData.fromList(it)
}
@@ -468,38 +568,50 @@ private open class UniversalBlePigeonCodec : StandardMessageCodec() {
stream.write(129)
writeValue(stream, value.raw.toLong())
}
is UniversalBleErrorCode -> {
is AndroidScanMode -> {
stream.write(130)
writeValue(stream, value.raw.toLong())
}
is UniversalBleScanResult -> {
is UniversalBleErrorCode -> {
stream.write(131)
writeValue(stream, value.toList())
writeValue(stream, value.raw.toLong())
}
is UniversalBleService -> {
is UniversalBleScanResult -> {
stream.write(132)
writeValue(stream, value.toList())
}
is UniversalBleCharacteristic -> {
is UniversalBleService -> {
stream.write(133)
writeValue(stream, value.toList())
}
is UniversalBleDescriptor -> {
is UniversalBleCharacteristic -> {
stream.write(134)
writeValue(stream, value.toList())
}
is UniversalScanFilter -> {
is UniversalBleDescriptor -> {
stream.write(135)
writeValue(stream, value.toList())
}
is UniversalManufacturerDataFilter -> {
is AndroidOptions -> {
stream.write(136)
writeValue(stream, value.toList())
}
is UniversalManufacturerData -> {
is UniversalScanConfig -> {
stream.write(137)
writeValue(stream, value.toList())
}
is UniversalScanFilter -> {
stream.write(138)
writeValue(stream, value.toList())
}
is UniversalManufacturerDataFilter -> {
stream.write(139)
writeValue(stream, value.toList())
}
is UniversalManufacturerData -> {
stream.write(140)
writeValue(stream, value.toList())
}
else -> super.writeValue(stream, value)
}
}
@@ -517,7 +629,7 @@ interface UniversalBlePlatformChannel {
fun requestPermissions(withAndroidFineLocation: Boolean, callback: (Result<Unit>) -> Unit)
fun enableBluetooth(callback: (Result<Boolean>) -> Unit)
fun disableBluetooth(callback: (Result<Boolean>) -> Unit)
fun startScan(filter: UniversalScanFilter?)
fun startScan(filter: UniversalScanFilter?, config: UniversalScanConfig?)
fun stopScan()
fun isScanning(): Boolean
fun connect(deviceId: String, autoConnect: Boolean?)
@@ -640,8 +752,9 @@ interface UniversalBlePlatformChannel {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val filterArg = args[0] as UniversalScanFilter?
val configArg = args[1] as UniversalScanConfig?
val wrapped: List<Any?> = try {
api.startScan(filterArg)
api.startScan(filterArg, configArg)
listOf(null)
} catch (exception: Throwable) {
UniversalBlePigeonUtils.wrapError(exception)
@@ -12,6 +12,8 @@ import android.bluetooth.le.ScanCallback.SCAN_FAILED_INTERNAL_ERROR
import android.bluetooth.le.ScanCallback.SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES
import android.bluetooth.le.ScanCallback.SCAN_FAILED_SCANNING_TOO_FREQUENTLY
import android.bluetooth.le.ScanResult
import android.bluetooth.le.ScanSettings
import android.os.Build
import android.util.Log
import android.util.SparseArray
import java.nio.ByteBuffer
@@ -224,6 +226,20 @@ fun gattStatusToUniversalBleErrorCode(code: Int): UniversalBleErrorCode {
}
}
fun AndroidScanMode.parse(): Int? {
return when (this) {
AndroidScanMode.BALANCED -> ScanSettings.SCAN_MODE_BALANCED
AndroidScanMode.LOW_LATENCY -> ScanSettings.SCAN_MODE_LOW_LATENCY
AndroidScanMode.LOW_POWER -> ScanSettings.SCAN_MODE_LOW_POWER
AndroidScanMode.OPPORTUNISTIC -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ScanSettings.SCAN_MODE_OPPORTUNISTIC
} else {
UniversalBleLogger.logError("Scan mode OPPORTUNISTIC is not supported on this Android version.")
null
}
}
}
fun Int.parseBluetoothStatusCodeError(): UniversalBleErrorCode? {
if (this == BluetoothStatusCodes.SUCCESS) return null
return when (this) {
@@ -160,7 +160,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
bluetoothDisableRequestFuture = callback
}
override fun startScan(filter: UniversalScanFilter?) {
override fun startScan(filter: UniversalScanFilter?, config: UniversalScanConfig?) {
if (!isBluetoothAvailable()) throw createFlutterError(
UniversalBleErrorCode.BLUETOOTH_NOT_ENABLED,
"Bluetooth not enabled"
@@ -171,6 +171,14 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
builder.setPhy(ScanSettings.PHY_LE_ALL_SUPPORTED)
builder.setLegacy(false)
}
config?.android?.let { androidConfig ->
androidConfig.scanMode?.parse()?.let { scanMode ->
builder.setScanMode(scanMode)
}
androidConfig.reportDelayMillis?.let { reportDelay ->
builder.setReportDelay(reportDelay)
}
}
val settings = builder.build()
val usesCustomFilters = filter?.usesCustomFilters() ?: false
@@ -1151,7 +1159,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
} else if (newState == BluetoothGatt.STATE_DISCONNECTED) {
val deviceId = gatt.device.address
val shouldAutoConnect = autoConnectDevices.contains(deviceId)
// Always clean up internal state (futures, etc.)
cleanUpConnection(deviceId)
@@ -1161,7 +1169,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
deviceId, false, status.parseHciErrorCode()
) {}
}
if (!shouldAutoConnect) {
// Only close GATT resources when autoConnect is disabled
gatt.removeCache()
+111 -18
View File
@@ -141,6 +141,14 @@ enum UniversalBleLogLevel: Int {
case verbose = 5
}
/// Scan config
enum AndroidScanMode: Int {
case balanced = 0
case lowLatency = 1
case lowPower = 2
case opportunistic = 3
}
/// Unified error codes for all platforms
enum UniversalBleErrorCode: Int {
case unknownError = 0
@@ -346,6 +354,71 @@ struct UniversalBleDescriptor: Hashable {
}
}
/// Android options to scan devices
/// [requestLocationPermission] is used to request location permission on Android 12+ (API 31+).
/// [scanMode] is used to set the scan mode for for Bluetooth LE scan.
/// Set [reportDelayMillis] timestamp for Bluetooth LE scan. If set to 0, you will be notified of scan results immediately.
/// If > 0, scan results are queued up and delivered after the requested delay or 5000 milliseconds (whichever is higher).
/// Note scan results may be delivered sooner if the internal buffers fill up.
///
/// Generated class from Pigeon that represents data sent in messages.
struct AndroidOptions: Hashable {
var requestLocationPermission: Bool? = nil
var scanMode: AndroidScanMode? = nil
var reportDelayMillis: Int64? = nil
// swift-format-ignore: AlwaysUseLowerCamelCase
static func fromList(_ pigeonVar_list: [Any?]) -> AndroidOptions? {
let requestLocationPermission: Bool? = nilOrValue(pigeonVar_list[0])
let scanMode: AndroidScanMode? = nilOrValue(pigeonVar_list[1])
let reportDelayMillis: Int64? = nilOrValue(pigeonVar_list[2])
return AndroidOptions(
requestLocationPermission: requestLocationPermission,
scanMode: scanMode,
reportDelayMillis: reportDelayMillis
)
}
func toList() -> [Any?] {
return [
requestLocationPermission,
scanMode,
reportDelayMillis,
]
}
static func == (lhs: AndroidOptions, rhs: AndroidOptions) -> Bool {
return deepEqualsUniversalBle(lhs.toList(), rhs.toList()) }
func hash(into hasher: inout Hasher) {
deepHashUniversalBle(value: toList(), hasher: &hasher)
}
}
/// Generated class from Pigeon that represents data sent in messages.
struct UniversalScanConfig: Hashable {
var android: AndroidOptions? = nil
// swift-format-ignore: AlwaysUseLowerCamelCase
static func fromList(_ pigeonVar_list: [Any?]) -> UniversalScanConfig? {
let android: AndroidOptions? = nilOrValue(pigeonVar_list[0])
return UniversalScanConfig(
android: android
)
}
func toList() -> [Any?] {
return [
android
]
}
static func == (lhs: UniversalScanConfig, rhs: UniversalScanConfig) -> Bool {
return deepEqualsUniversalBle(lhs.toList(), rhs.toList()) }
func hash(into hasher: inout Hasher) {
deepHashUniversalBle(value: toList(), hasher: &hasher)
}
}
/// Scan Filters
///
/// Generated class from Pigeon that represents data sent in messages.
@@ -455,22 +528,32 @@ private class UniversalBlePigeonCodecReader: FlutterStandardReader {
case 130:
let enumResultAsInt: Int? = nilOrValue(self.readValue() as! Int?)
if let enumResultAsInt = enumResultAsInt {
return UniversalBleErrorCode(rawValue: enumResultAsInt)
return AndroidScanMode(rawValue: enumResultAsInt)
}
return nil
case 131:
return UniversalBleScanResult.fromList(self.readValue() as! [Any?])
let enumResultAsInt: Int? = nilOrValue(self.readValue() as! Int?)
if let enumResultAsInt = enumResultAsInt {
return UniversalBleErrorCode(rawValue: enumResultAsInt)
}
return nil
case 132:
return UniversalBleService.fromList(self.readValue() as! [Any?])
return UniversalBleScanResult.fromList(self.readValue() as! [Any?])
case 133:
return UniversalBleCharacteristic.fromList(self.readValue() as! [Any?])
return UniversalBleService.fromList(self.readValue() as! [Any?])
case 134:
return UniversalBleDescriptor.fromList(self.readValue() as! [Any?])
return UniversalBleCharacteristic.fromList(self.readValue() as! [Any?])
case 135:
return UniversalScanFilter.fromList(self.readValue() as! [Any?])
return UniversalBleDescriptor.fromList(self.readValue() as! [Any?])
case 136:
return UniversalManufacturerDataFilter.fromList(self.readValue() as! [Any?])
return AndroidOptions.fromList(self.readValue() as! [Any?])
case 137:
return UniversalScanConfig.fromList(self.readValue() as! [Any?])
case 138:
return UniversalScanFilter.fromList(self.readValue() as! [Any?])
case 139:
return UniversalManufacturerDataFilter.fromList(self.readValue() as! [Any?])
case 140:
return UniversalManufacturerData.fromList(self.readValue() as! [Any?])
default:
return super.readValue(ofType: type)
@@ -483,30 +566,39 @@ private class UniversalBlePigeonCodecWriter: FlutterStandardWriter {
if let value = value as? UniversalBleLogLevel {
super.writeByte(129)
super.writeValue(value.rawValue)
} else if let value = value as? UniversalBleErrorCode {
} else if let value = value as? AndroidScanMode {
super.writeByte(130)
super.writeValue(value.rawValue)
} else if let value = value as? UniversalBleScanResult {
} else if let value = value as? UniversalBleErrorCode {
super.writeByte(131)
super.writeValue(value.toList())
} else if let value = value as? UniversalBleService {
super.writeValue(value.rawValue)
} else if let value = value as? UniversalBleScanResult {
super.writeByte(132)
super.writeValue(value.toList())
} else if let value = value as? UniversalBleCharacteristic {
} else if let value = value as? UniversalBleService {
super.writeByte(133)
super.writeValue(value.toList())
} else if let value = value as? UniversalBleDescriptor {
} else if let value = value as? UniversalBleCharacteristic {
super.writeByte(134)
super.writeValue(value.toList())
} else if let value = value as? UniversalScanFilter {
} else if let value = value as? UniversalBleDescriptor {
super.writeByte(135)
super.writeValue(value.toList())
} else if let value = value as? UniversalManufacturerDataFilter {
} else if let value = value as? AndroidOptions {
super.writeByte(136)
super.writeValue(value.toList())
} else if let value = value as? UniversalManufacturerData {
} else if let value = value as? UniversalScanConfig {
super.writeByte(137)
super.writeValue(value.toList())
} else if let value = value as? UniversalScanFilter {
super.writeByte(138)
super.writeValue(value.toList())
} else if let value = value as? UniversalManufacturerDataFilter {
super.writeByte(139)
super.writeValue(value.toList())
} else if let value = value as? UniversalManufacturerData {
super.writeByte(140)
super.writeValue(value.toList())
} else {
super.writeValue(value)
}
@@ -537,7 +629,7 @@ protocol UniversalBlePlatformChannel {
func requestPermissions(withAndroidFineLocation: Bool, completion: @escaping (Result<Void, Error>) -> Void)
func enableBluetooth(completion: @escaping (Result<Bool, Error>) -> Void)
func disableBluetooth(completion: @escaping (Result<Bool, Error>) -> Void)
func startScan(filter: UniversalScanFilter?) throws
func startScan(filter: UniversalScanFilter?, config: UniversalScanConfig?) throws
func stopScan() throws
func isScanning() throws -> Bool
func connect(deviceId: String, autoConnect: Bool?) throws
@@ -644,8 +736,9 @@ class UniversalBlePlatformChannelSetup {
startScanChannel.setMessageHandler { message, reply in
let args = message as! [Any?]
let filterArg: UniversalScanFilter? = nilOrValue(args[0])
let configArg: UniversalScanConfig? = nilOrValue(args[1])
do {
try api.startScan(filter: filterArg)
try api.startScan(filter: filterArg, config: configArg)
reply(wrapResult(nil))
} catch {
reply(wrapError(error))
+1 -1
View File
@@ -91,7 +91,7 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
completion(Result.failure(createFlutterError(code: .notSupported)))
}
func startScan(filter: UniversalScanFilter?) throws {
func startScan(filter: UniversalScanFilter?, config _: UniversalScanConfig?) throws {
// If filter has any other filter other than official one
let usesCustomFilters = filter?.usesCustomFilters ?? false
+2 -1
View File
@@ -52,7 +52,8 @@ class MockUniversalBle extends UniversalBlePlatform {
}
@override
Future<void> connect(String deviceId, {bool autoConnect = false, Duration? connectionTimeout}) async {
Future<void> connect(String deviceId,
{bool autoConnect = false, Duration? connectionTimeout}) async {
updateConnection(deviceId, true);
_connectionStateMap[deviceId] = BleConnectionState.connected;
}
+7 -4
View File
@@ -84,7 +84,11 @@ class _ScannerScreenState extends State<ScannerScreen> {
_isScanning = true;
});
try {
PlatformConfig? platformConfig;
PlatformConfig platformConfig = PlatformConfig(
android: AndroidOptions(
scanMode: AndroidScanMode.lowLatency,
),
);
if (kIsWeb && _webServicesController.text.isNotEmpty) {
List<String> webServices = _webServicesController.text
.split(',')
@@ -96,10 +100,9 @@ class _ScannerScreenState extends State<ScannerScreen> {
return s.trim();
}
}).toList();
platformConfig = PlatformConfig(
web: WebOptions(optionalServices: webServices),
);
platformConfig.web = WebOptions(optionalServices: webServices);
}
await UniversalBle.startScan(
scanFilter: scanFilter,
platformConfig: platformConfig,
+3 -2
View File
@@ -9,7 +9,7 @@ import 'package:url_launcher/url_launcher.dart';
class AppDrawer extends StatefulWidget {
final QueueType? queueType;
final Function(QueueType)? onQueueTypeChanged;
const AppDrawer({
super.key,
this.queueType,
@@ -87,7 +87,8 @@ class _AppDrawerState extends State<AppDrawer> {
),
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
padding:
const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Column(
children: [
_buildQueueOption(
@@ -66,7 +66,8 @@ class _ScanFilterWidgetState extends State<ScanFilterWidget> {
.where((s) => s.isNotEmpty)
.toList();
for (String manufacturer in manufacturerData) {
final companyIdentifier = companyService.parseCompanyIdentifier(manufacturer);
final companyIdentifier =
companyService.parseCompanyIdentifier(manufacturer);
if (companyIdentifier == null) {
throw Exception(
+8 -7
View File
@@ -2,23 +2,23 @@ import 'package:flutter/material.dart';
import 'package:universal_ble_example/data/company_identifier_service.dart';
/// A reusable widget that displays company information for a given company ID.
///
///
/// This widget fetches the company name from the CompanyIdentifierService
/// and displays it in a consistent format. If no company name is found,
/// the widget returns an empty SizedBox.
class CompanyInfoWidget extends StatelessWidget {
/// The company ID to look up
final int companyId;
/// Optional text style for the "Company:" label
final TextStyle? labelStyle;
/// Optional text style for the company name
final TextStyle? nameStyle;
/// Optional padding around the widget
final EdgeInsets? padding;
/// Optional color scheme. If not provided, will be obtained from Theme
final ColorScheme? colorScheme;
@@ -33,8 +33,9 @@ class CompanyInfoWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final companyName = CompanyIdentifierService.instance.getCompanyName(companyId);
final companyName =
CompanyIdentifierService.instance.getCompanyName(companyId);
if (companyName == null) {
return const SizedBox.shrink();
}
+2 -2
View File
@@ -1,4 +1,3 @@
import 'package:universal_ble/src/universal_ble_pigeon/universal_ble.g.dart';
import 'package:universal_ble/src/utils/cache_handler.dart';
import 'package:universal_ble/universal_ble.dart';
@@ -19,7 +18,8 @@ extension BleDeviceExtension on BleDevice {
/// Connects to the device.
/// [autoConnect] enables automatic reconnection when the device becomes available.
Future<void> connect({bool autoConnect = false, Duration? timeout}) =>
UniversalBle.connect(deviceId, autoConnect: autoConnect, timeout: timeout);
UniversalBle.connect(deviceId,
autoConnect: autoConnect, timeout: timeout);
/// Disconnects from the device.
Future<void> disconnect() => UniversalBle.disconnect(deviceId);
@@ -1,4 +1,3 @@
import 'package:universal_ble/src/universal_ble_pigeon/universal_ble.g.dart';
import 'package:universal_ble/universal_ble.dart';
/// Extension methods for [BleService] objects.
+4 -7
View File
@@ -1,4 +1,8 @@
import 'package:universal_ble/src/universal_ble_pigeon/universal_ble.g.dart';
/// Platform specific config to scan devices
///
/// If more than 1 platform supports a certain parameter then it should be in the high level APIs instead of platform specific options.
class PlatformConfig {
WebOptions? web;
AndroidOptions? android;
@@ -22,10 +26,3 @@ class WebOptions {
this.optionalManufacturerData = const [],
});
}
/// Android options to scan devices
class AndroidOptions {
bool requestLocationPermission;
AndroidOptions({this.requestLocationPermission = true});
}
+141 -18
View File
@@ -50,6 +50,14 @@ enum UniversalBleLogLevel {
verbose,
}
/// Scan config
enum AndroidScanMode {
balanced,
lowLatency,
lowPower,
opportunistic,
}
/// Unified error codes for all platforms
enum UniversalBleErrorCode {
unknownError,
@@ -334,6 +342,104 @@ class UniversalBleDescriptor {
int get hashCode => Object.hashAll(_toList());
}
/// Android options to scan devices
/// [requestLocationPermission] is used to request location permission on Android 12+ (API 31+).
/// [scanMode] is used to set the scan mode for for Bluetooth LE scan.
/// Set [reportDelayMillis] timestamp for Bluetooth LE scan. If set to 0, you will be notified of scan results immediately.
/// If > 0, scan results are queued up and delivered after the requested delay or 5000 milliseconds (whichever is higher).
/// Note scan results may be delivered sooner if the internal buffers fill up.
class AndroidOptions {
AndroidOptions({
this.requestLocationPermission,
this.scanMode,
this.reportDelayMillis,
});
bool? requestLocationPermission;
AndroidScanMode? scanMode;
int? reportDelayMillis;
List<Object?> _toList() {
return <Object?>[
requestLocationPermission,
scanMode,
reportDelayMillis,
];
}
Object encode() {
return _toList();
}
static AndroidOptions decode(Object result) {
result as List<Object?>;
return AndroidOptions(
requestLocationPermission: result[0] as bool?,
scanMode: result[1] as AndroidScanMode?,
reportDelayMillis: result[2] as int?,
);
}
@override
// ignore: avoid_equals_and_hash_code_on_mutable_classes
bool operator ==(Object other) {
if (other is! AndroidOptions || other.runtimeType != runtimeType) {
return false;
}
if (identical(this, other)) {
return true;
}
return _deepEquals(encode(), other.encode());
}
@override
// ignore: avoid_equals_and_hash_code_on_mutable_classes
int get hashCode => Object.hashAll(_toList());
}
class UniversalScanConfig {
UniversalScanConfig({
this.android,
});
AndroidOptions? android;
List<Object?> _toList() {
return <Object?>[
android,
];
}
Object encode() {
return _toList();
}
static UniversalScanConfig decode(Object result) {
result as List<Object?>;
return UniversalScanConfig(
android: result[0] as AndroidOptions?,
);
}
@override
// ignore: avoid_equals_and_hash_code_on_mutable_classes
bool operator ==(Object other) {
if (other is! UniversalScanConfig || other.runtimeType != runtimeType) {
return false;
}
if (identical(this, other)) {
return true;
}
return _deepEquals(encode(), other.encode());
}
@override
// ignore: avoid_equals_and_hash_code_on_mutable_classes
int get hashCode => Object.hashAll(_toList());
}
/// Scan Filters
class UniversalScanFilter {
UniversalScanFilter({
@@ -496,30 +602,39 @@ class _PigeonCodec extends StandardMessageCodec {
} else if (value is UniversalBleLogLevel) {
buffer.putUint8(129);
writeValue(buffer, value.index);
} else if (value is UniversalBleErrorCode) {
} else if (value is AndroidScanMode) {
buffer.putUint8(130);
writeValue(buffer, value.index);
} else if (value is UniversalBleScanResult) {
} else if (value is UniversalBleErrorCode) {
buffer.putUint8(131);
writeValue(buffer, value.encode());
} else if (value is UniversalBleService) {
writeValue(buffer, value.index);
} else if (value is UniversalBleScanResult) {
buffer.putUint8(132);
writeValue(buffer, value.encode());
} else if (value is UniversalBleCharacteristic) {
} else if (value is UniversalBleService) {
buffer.putUint8(133);
writeValue(buffer, value.encode());
} else if (value is UniversalBleDescriptor) {
} else if (value is UniversalBleCharacteristic) {
buffer.putUint8(134);
writeValue(buffer, value.encode());
} else if (value is UniversalScanFilter) {
} else if (value is UniversalBleDescriptor) {
buffer.putUint8(135);
writeValue(buffer, value.encode());
} else if (value is UniversalManufacturerDataFilter) {
} else if (value is AndroidOptions) {
buffer.putUint8(136);
writeValue(buffer, value.encode());
} else if (value is UniversalManufacturerData) {
} else if (value is UniversalScanConfig) {
buffer.putUint8(137);
writeValue(buffer, value.encode());
} else if (value is UniversalScanFilter) {
buffer.putUint8(138);
writeValue(buffer, value.encode());
} else if (value is UniversalManufacturerDataFilter) {
buffer.putUint8(139);
writeValue(buffer, value.encode());
} else if (value is UniversalManufacturerData) {
buffer.putUint8(140);
writeValue(buffer, value.encode());
} else {
super.writeValue(buffer, value);
}
@@ -533,20 +648,27 @@ class _PigeonCodec extends StandardMessageCodec {
return value == null ? null : UniversalBleLogLevel.values[value];
case 130:
final value = readValue(buffer) as int?;
return value == null ? null : UniversalBleErrorCode.values[value];
return value == null ? null : AndroidScanMode.values[value];
case 131:
return UniversalBleScanResult.decode(readValue(buffer)!);
final value = readValue(buffer) as int?;
return value == null ? null : UniversalBleErrorCode.values[value];
case 132:
return UniversalBleService.decode(readValue(buffer)!);
return UniversalBleScanResult.decode(readValue(buffer)!);
case 133:
return UniversalBleCharacteristic.decode(readValue(buffer)!);
return UniversalBleService.decode(readValue(buffer)!);
case 134:
return UniversalBleDescriptor.decode(readValue(buffer)!);
return UniversalBleCharacteristic.decode(readValue(buffer)!);
case 135:
return UniversalScanFilter.decode(readValue(buffer)!);
return UniversalBleDescriptor.decode(readValue(buffer)!);
case 136:
return UniversalManufacturerDataFilter.decode(readValue(buffer)!);
return AndroidOptions.decode(readValue(buffer)!);
case 137:
return UniversalScanConfig.decode(readValue(buffer)!);
case 138:
return UniversalScanFilter.decode(readValue(buffer)!);
case 139:
return UniversalManufacturerDataFilter.decode(readValue(buffer)!);
case 140:
return UniversalManufacturerData.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
@@ -707,7 +829,8 @@ class UniversalBlePlatformChannel {
}
}
Future<void> startScan(UniversalScanFilter? filter) async {
Future<void> startScan(
UniversalScanFilter? filter, UniversalScanConfig? config) async {
final pigeonVar_channelName =
'dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.startScan$pigeonVar_messageChannelSuffix';
final pigeonVar_channel = BasicMessageChannel<Object?>(
@@ -716,7 +839,7 @@ class UniversalBlePlatformChannel {
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture =
pigeonVar_channel.send(<Object?>[filter]);
pigeonVar_channel.send(<Object?>[filter, config]);
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
@@ -49,6 +49,7 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
await _executeWithErrorHandling(
() => _channel.startScan(
scanFilter.toUniversalScanFilter(),
platformConfig?.toUniversalScanConfig(),
),
);
}
@@ -69,8 +70,10 @@ class UniversalBlePigeonChannel extends UniversalBlePlatform {
}
@override
Future<void> connect(String deviceId, {Duration? connectionTimeout, bool autoConnect = false}) =>
_executeWithErrorHandling(() => _channel.connect(deviceId, autoConnect: autoConnect));
Future<void> connect(String deviceId,
{Duration? connectionTimeout, bool autoConnect = false}) =>
_executeWithErrorHandling(
() => _channel.connect(deviceId, autoConnect: autoConnect));
@override
Future<void> disconnect(String deviceId) =>
@@ -329,3 +332,11 @@ extension _BleLogLevelExtension on BleLogLevel {
BleLogLevel.verbose => UniversalBleLogLevel.verbose,
};
}
extension _PlatformConfigExtension on PlatformConfig? {
UniversalScanConfig? toUniversalScanConfig() {
return UniversalScanConfig(
android: this?.android,
);
}
}
@@ -53,7 +53,8 @@ abstract class UniversalBlePlatform {
Future<bool> isScanning();
Future<void> connect(String deviceId, {Duration? connectionTimeout, bool autoConnect = false});
Future<void> connect(String deviceId,
{Duration? connectionTimeout, bool autoConnect = false});
Future<void> disconnect(String deviceId);
@@ -4,7 +4,6 @@ import 'dart:collection';
import 'package:flutter/foundation.dart';
import 'package:flutter_web_bluetooth/flutter_web_bluetooth.dart';
import 'package:universal_ble/src/utils/universal_logger.dart';
import 'package:universal_ble/src/universal_ble_pigeon/universal_ble.g.dart';
import 'package:universal_ble/universal_ble.dart';
class UniversalBleWeb extends UniversalBlePlatform {
+6
View File
@@ -5,3 +5,9 @@ export 'package:universal_ble/src/universal_ble_platform_interface.dart';
export 'package:universal_ble/src/universal_ble.dart';
export 'package:universal_ble/src/models/model_exports.dart';
export 'package:universal_ble/src/extensions/exports.dart';
export 'package:universal_ble/src/universal_ble_pigeon/universal_ble.g.dart'
show
AndroidOptions,
AndroidScanMode,
UniversalBleErrorCode,
UniversalBleLogLevel;
+32 -1
View File
@@ -35,7 +35,7 @@ abstract class UniversalBlePlatformChannel {
@async
bool disableBluetooth();
void startScan(UniversalScanFilter? filter);
void startScan(UniversalScanFilter? filter, UniversalScanConfig? config);
void stopScan();
@@ -171,6 +171,37 @@ class UniversalBleDescriptor {
UniversalBleDescriptor(this.uuid);
}
/// Scan config
enum AndroidScanMode {
balanced,
lowLatency,
lowPower,
opportunistic,
}
/// Android options to scan devices
/// [requestLocationPermission] is used to request location permission on Android 12+ (API 31+).
/// [scanMode] is used to set the scan mode for for Bluetooth LE scan.
/// Set [reportDelayMillis] timestamp for Bluetooth LE scan. If set to 0, you will be notified of scan results immediately.
/// If > 0, scan results are queued up and delivered after the requested delay or 5000 milliseconds (whichever is higher).
/// Note scan results may be delivered sooner if the internal buffers fill up.
class AndroidOptions {
bool? requestLocationPermission;
AndroidScanMode? scanMode;
int? reportDelayMillis;
AndroidOptions({
this.requestLocationPermission,
this.scanMode,
this.reportDelayMillis,
});
}
class UniversalScanConfig {
AndroidOptions? android;
UniversalScanConfig(this.android);
}
/// Scan Filters
class UniversalScanFilter {
final List<String> withServices;
+165 -16
View File
@@ -331,6 +331,127 @@ UniversalBleDescriptor UniversalBleDescriptor::FromEncodableList(const Encodable
return decoded;
}
// AndroidOptions
AndroidOptions::AndroidOptions() {}
AndroidOptions::AndroidOptions(
const bool* request_location_permission,
const AndroidScanMode* scan_mode,
const int64_t* report_delay_millis)
: request_location_permission_(request_location_permission ? std::optional<bool>(*request_location_permission) : std::nullopt),
scan_mode_(scan_mode ? std::optional<AndroidScanMode>(*scan_mode) : std::nullopt),
report_delay_millis_(report_delay_millis ? std::optional<int64_t>(*report_delay_millis) : std::nullopt) {}
const bool* AndroidOptions::request_location_permission() const {
return request_location_permission_ ? &(*request_location_permission_) : nullptr;
}
void AndroidOptions::set_request_location_permission(const bool* value_arg) {
request_location_permission_ = value_arg ? std::optional<bool>(*value_arg) : std::nullopt;
}
void AndroidOptions::set_request_location_permission(bool value_arg) {
request_location_permission_ = value_arg;
}
const AndroidScanMode* AndroidOptions::scan_mode() const {
return scan_mode_ ? &(*scan_mode_) : nullptr;
}
void AndroidOptions::set_scan_mode(const AndroidScanMode* value_arg) {
scan_mode_ = value_arg ? std::optional<AndroidScanMode>(*value_arg) : std::nullopt;
}
void AndroidOptions::set_scan_mode(const AndroidScanMode& value_arg) {
scan_mode_ = value_arg;
}
const int64_t* AndroidOptions::report_delay_millis() const {
return report_delay_millis_ ? &(*report_delay_millis_) : nullptr;
}
void AndroidOptions::set_report_delay_millis(const int64_t* value_arg) {
report_delay_millis_ = value_arg ? std::optional<int64_t>(*value_arg) : std::nullopt;
}
void AndroidOptions::set_report_delay_millis(int64_t value_arg) {
report_delay_millis_ = value_arg;
}
EncodableList AndroidOptions::ToEncodableList() const {
EncodableList list;
list.reserve(3);
list.push_back(request_location_permission_ ? EncodableValue(*request_location_permission_) : EncodableValue());
list.push_back(scan_mode_ ? CustomEncodableValue(*scan_mode_) : EncodableValue());
list.push_back(report_delay_millis_ ? EncodableValue(*report_delay_millis_) : EncodableValue());
return list;
}
AndroidOptions AndroidOptions::FromEncodableList(const EncodableList& list) {
AndroidOptions decoded;
auto& encodable_request_location_permission = list[0];
if (!encodable_request_location_permission.IsNull()) {
decoded.set_request_location_permission(std::get<bool>(encodable_request_location_permission));
}
auto& encodable_scan_mode = list[1];
if (!encodable_scan_mode.IsNull()) {
decoded.set_scan_mode(std::any_cast<const AndroidScanMode&>(std::get<CustomEncodableValue>(encodable_scan_mode)));
}
auto& encodable_report_delay_millis = list[2];
if (!encodable_report_delay_millis.IsNull()) {
decoded.set_report_delay_millis(std::get<int64_t>(encodable_report_delay_millis));
}
return decoded;
}
// UniversalScanConfig
UniversalScanConfig::UniversalScanConfig() {}
UniversalScanConfig::UniversalScanConfig(const AndroidOptions* android)
: android_(android ? std::make_unique<AndroidOptions>(*android) : nullptr) {}
UniversalScanConfig::UniversalScanConfig(const UniversalScanConfig& other)
: android_(other.android_ ? std::make_unique<AndroidOptions>(*other.android_) : nullptr) {}
UniversalScanConfig& UniversalScanConfig::operator=(const UniversalScanConfig& other) {
android_ = other.android_ ? std::make_unique<AndroidOptions>(*other.android_) : nullptr;
return *this;
}
const AndroidOptions* UniversalScanConfig::android() const {
return android_.get();
}
void UniversalScanConfig::set_android(const AndroidOptions* value_arg) {
android_ = value_arg ? std::make_unique<AndroidOptions>(*value_arg) : nullptr;
}
void UniversalScanConfig::set_android(const AndroidOptions& value_arg) {
android_ = std::make_unique<AndroidOptions>(value_arg);
}
EncodableList UniversalScanConfig::ToEncodableList() const {
EncodableList list;
list.reserve(1);
list.push_back(android_ ? CustomEncodableValue(*android_) : EncodableValue());
return list;
}
UniversalScanConfig UniversalScanConfig::FromEncodableList(const EncodableList& list) {
UniversalScanConfig decoded;
auto& encodable_android = list[0];
if (!encodable_android.IsNull()) {
decoded.set_android(std::any_cast<const AndroidOptions&>(std::get<CustomEncodableValue>(encodable_android)));
}
return decoded;
}
// UniversalScanFilter
UniversalScanFilter::UniversalScanFilter(
@@ -512,27 +633,38 @@ EncodableValue PigeonInternalCodecSerializer::ReadValueOfType(
case 130: {
const auto& encodable_enum_arg = ReadValue(stream);
const int64_t enum_arg_value = encodable_enum_arg.IsNull() ? 0 : encodable_enum_arg.LongValue();
return encodable_enum_arg.IsNull() ? EncodableValue() : CustomEncodableValue(static_cast<UniversalBleErrorCode>(enum_arg_value));
return encodable_enum_arg.IsNull() ? EncodableValue() : CustomEncodableValue(static_cast<AndroidScanMode>(enum_arg_value));
}
case 131: {
return CustomEncodableValue(UniversalBleScanResult::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
const auto& encodable_enum_arg = ReadValue(stream);
const int64_t enum_arg_value = encodable_enum_arg.IsNull() ? 0 : encodable_enum_arg.LongValue();
return encodable_enum_arg.IsNull() ? EncodableValue() : CustomEncodableValue(static_cast<UniversalBleErrorCode>(enum_arg_value));
}
case 132: {
return CustomEncodableValue(UniversalBleService::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
return CustomEncodableValue(UniversalBleScanResult::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
}
case 133: {
return CustomEncodableValue(UniversalBleCharacteristic::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
return CustomEncodableValue(UniversalBleService::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
}
case 134: {
return CustomEncodableValue(UniversalBleDescriptor::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
return CustomEncodableValue(UniversalBleCharacteristic::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
}
case 135: {
return CustomEncodableValue(UniversalScanFilter::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
return CustomEncodableValue(UniversalBleDescriptor::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
}
case 136: {
return CustomEncodableValue(UniversalManufacturerDataFilter::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
return CustomEncodableValue(AndroidOptions::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
}
case 137: {
return CustomEncodableValue(UniversalScanConfig::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
}
case 138: {
return CustomEncodableValue(UniversalScanFilter::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
}
case 139: {
return CustomEncodableValue(UniversalManufacturerDataFilter::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
}
case 140: {
return CustomEncodableValue(UniversalManufacturerData::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
}
default:
@@ -549,43 +681,58 @@ void PigeonInternalCodecSerializer::WriteValue(
WriteValue(EncodableValue(static_cast<int>(std::any_cast<UniversalBleLogLevel>(*custom_value))), stream);
return;
}
if (custom_value->type() == typeid(UniversalBleErrorCode)) {
if (custom_value->type() == typeid(AndroidScanMode)) {
stream->WriteByte(130);
WriteValue(EncodableValue(static_cast<int>(std::any_cast<AndroidScanMode>(*custom_value))), stream);
return;
}
if (custom_value->type() == typeid(UniversalBleErrorCode)) {
stream->WriteByte(131);
WriteValue(EncodableValue(static_cast<int>(std::any_cast<UniversalBleErrorCode>(*custom_value))), stream);
return;
}
if (custom_value->type() == typeid(UniversalBleScanResult)) {
stream->WriteByte(131);
stream->WriteByte(132);
WriteValue(EncodableValue(std::any_cast<UniversalBleScanResult>(*custom_value).ToEncodableList()), stream);
return;
}
if (custom_value->type() == typeid(UniversalBleService)) {
stream->WriteByte(132);
stream->WriteByte(133);
WriteValue(EncodableValue(std::any_cast<UniversalBleService>(*custom_value).ToEncodableList()), stream);
return;
}
if (custom_value->type() == typeid(UniversalBleCharacteristic)) {
stream->WriteByte(133);
stream->WriteByte(134);
WriteValue(EncodableValue(std::any_cast<UniversalBleCharacteristic>(*custom_value).ToEncodableList()), stream);
return;
}
if (custom_value->type() == typeid(UniversalBleDescriptor)) {
stream->WriteByte(134);
stream->WriteByte(135);
WriteValue(EncodableValue(std::any_cast<UniversalBleDescriptor>(*custom_value).ToEncodableList()), stream);
return;
}
if (custom_value->type() == typeid(AndroidOptions)) {
stream->WriteByte(136);
WriteValue(EncodableValue(std::any_cast<AndroidOptions>(*custom_value).ToEncodableList()), stream);
return;
}
if (custom_value->type() == typeid(UniversalScanConfig)) {
stream->WriteByte(137);
WriteValue(EncodableValue(std::any_cast<UniversalScanConfig>(*custom_value).ToEncodableList()), stream);
return;
}
if (custom_value->type() == typeid(UniversalScanFilter)) {
stream->WriteByte(135);
stream->WriteByte(138);
WriteValue(EncodableValue(std::any_cast<UniversalScanFilter>(*custom_value).ToEncodableList()), stream);
return;
}
if (custom_value->type() == typeid(UniversalManufacturerDataFilter)) {
stream->WriteByte(136);
stream->WriteByte(139);
WriteValue(EncodableValue(std::any_cast<UniversalManufacturerDataFilter>(*custom_value).ToEncodableList()), stream);
return;
}
if (custom_value->type() == typeid(UniversalManufacturerData)) {
stream->WriteByte(137);
stream->WriteByte(140);
WriteValue(EncodableValue(std::any_cast<UniversalManufacturerData>(*custom_value).ToEncodableList()), stream);
return;
}
@@ -741,7 +888,9 @@ void UniversalBlePlatformChannel::SetUp(
const auto& args = std::get<EncodableList>(message);
const auto& encodable_filter_arg = args.at(0);
const auto* filter_arg = encodable_filter_arg.IsNull() ? nullptr : &(std::any_cast<const UniversalScanFilter&>(std::get<CustomEncodableValue>(encodable_filter_arg)));
std::optional<FlutterError> output = api->StartScan(filter_arg);
const auto& encodable_config_arg = args.at(1);
const auto* config_arg = encodable_config_arg.IsNull() ? nullptr : &(std::any_cast<const UniversalScanConfig&>(std::get<CustomEncodableValue>(encodable_config_arg)));
std::optional<FlutterError> output = api->StartScan(filter_arg, config_arg);
if (output.has_value()) {
reply(WrapError(output.value()));
return;
+83 -1
View File
@@ -66,6 +66,14 @@ enum class UniversalBleLogLevel {
kVerbose = 5
};
// Scan config
enum class AndroidScanMode {
kBalanced = 0,
kLowLatency = 1,
kLowPower = 2,
kOpportunistic = 3
};
// Unified error codes for all platforms
enum class UniversalBleErrorCode {
kUnknownError = 0,
@@ -275,6 +283,78 @@ class UniversalBleDescriptor {
};
// Android options to scan devices
// [requestLocationPermission] is used to request location permission on Android 12+ (API 31+).
// [scanMode] is used to set the scan mode for for Bluetooth LE scan.
// Set [reportDelayMillis] timestamp for Bluetooth LE scan. If set to 0, you will be notified of scan results immediately.
// If > 0, scan results are queued up and delivered after the requested delay or 5000 milliseconds (whichever is higher).
// Note scan results may be delivered sooner if the internal buffers fill up.
//
// Generated class from Pigeon that represents data sent in messages.
class AndroidOptions {
public:
// Constructs an object setting all non-nullable fields.
AndroidOptions();
// Constructs an object setting all fields.
explicit AndroidOptions(
const bool* request_location_permission,
const AndroidScanMode* scan_mode,
const int64_t* report_delay_millis);
const bool* request_location_permission() const;
void set_request_location_permission(const bool* value_arg);
void set_request_location_permission(bool value_arg);
const AndroidScanMode* scan_mode() const;
void set_scan_mode(const AndroidScanMode* value_arg);
void set_scan_mode(const AndroidScanMode& value_arg);
const int64_t* report_delay_millis() const;
void set_report_delay_millis(const int64_t* value_arg);
void set_report_delay_millis(int64_t value_arg);
private:
static AndroidOptions FromEncodableList(const flutter::EncodableList& list);
flutter::EncodableList ToEncodableList() const;
friend class UniversalScanConfig;
friend class UniversalBlePlatformChannel;
friend class UniversalBleCallbackChannel;
friend class PigeonInternalCodecSerializer;
std::optional<bool> request_location_permission_;
std::optional<AndroidScanMode> scan_mode_;
std::optional<int64_t> report_delay_millis_;
};
// Generated class from Pigeon that represents data sent in messages.
class UniversalScanConfig {
public:
// Constructs an object setting all non-nullable fields.
UniversalScanConfig();
// Constructs an object setting all fields.
explicit UniversalScanConfig(const AndroidOptions* android);
~UniversalScanConfig() = default;
UniversalScanConfig(const UniversalScanConfig& other);
UniversalScanConfig& operator=(const UniversalScanConfig& other);
UniversalScanConfig(UniversalScanConfig&& other) = default;
UniversalScanConfig& operator=(UniversalScanConfig&& other) noexcept = default;
const AndroidOptions* android() const;
void set_android(const AndroidOptions* value_arg);
void set_android(const AndroidOptions& value_arg);
private:
static UniversalScanConfig FromEncodableList(const flutter::EncodableList& list);
flutter::EncodableList ToEncodableList() const;
friend class UniversalBlePlatformChannel;
friend class UniversalBleCallbackChannel;
friend class PigeonInternalCodecSerializer;
std::unique_ptr<AndroidOptions> android_;
};
// Scan Filters
//
// Generated class from Pigeon that represents data sent in messages.
@@ -399,7 +479,9 @@ class UniversalBlePlatformChannel {
std::function<void(std::optional<FlutterError> reply)> result) = 0;
virtual void EnableBluetooth(std::function<void(ErrorOr<bool> reply)> result) = 0;
virtual void DisableBluetooth(std::function<void(ErrorOr<bool> reply)> result) = 0;
virtual std::optional<FlutterError> StartScan(const UniversalScanFilter* filter) = 0;
virtual std::optional<FlutterError> StartScan(
const UniversalScanFilter* filter,
const UniversalScanConfig* config) = 0;
virtual std::optional<FlutterError> StopScan() = 0;
virtual ErrorOr<bool> IsScanning() = 0;
virtual std::optional<FlutterError> Connect(
+1 -1
View File
@@ -134,7 +134,7 @@ void UniversalBlePlugin::RequestPermissions(
}
std::optional<FlutterError>
UniversalBlePlugin::StartScan(const UniversalScanFilter *filter) {
UniversalBlePlugin::StartScan(const UniversalScanFilter *filter, const UniversalScanConfig *config) {
if (!bluetooth_radio_ || bluetooth_radio_.State() != RadioState::On) {
return create_flutter_error(UniversalBleErrorCode::kBluetoothNotAvailable,
+1 -1
View File
@@ -174,7 +174,7 @@ private:
std::optional<FlutterError>
SetLogLevel(const UniversalBleLogLevel &log_level) override;
std::optional<FlutterError>
StartScan(const UniversalScanFilter *filter) override;
StartScan(const UniversalScanFilter *filter, const UniversalScanConfig *config) override;
std::optional<FlutterError> StopScan() override;
ErrorOr<bool> IsScanning() override;
std::optional<FlutterError> Connect(const std::string &device_id, const bool *auto_connect) override;