rohitsangwan01 / ble_peripheral Goto Github PK
View Code? Open in Web Editor NEWA Flutter plugin that allows you to use your device as Bluetooth Low Energy (BLE) peripheral
License: MIT License
A Flutter plugin that allows you to use your device as Bluetooth Low Energy (BLE) peripheral
License: MIT License
So i stumbled upon a curious bug, like the title said.
The workflow is currently this:
1: Permissions need to be asked and given, that means the user has some time on page if they refuse the first time around.
2: Then and only then can BlePeripheral.initialize() be called.
Now, if the user declines the permissions, initialize hasn't been called, and the user manually turns bluetooth on or off (or its done by some other way), the whole application will fatal crash and close with the stacktrace:
java.lang.RuntimeException: Error receiving broadcast Intent { act=android.bluetooth.adapter.action.STATE_CHANGED flg=0x4000010 (has extras) } in com.rohit.ble_peripheral.BlePeripheralPlugin$broadcastReceiver$1@f88b5e9
at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0(LoadedApk.java:1810)
at android.app.LoadedApk$ReceiverDispatcher$Args.$r8$lambda$gDuJqgxY6Zb-ifyeubKeivTLAwk(Unknown Source:0)
at android.app.LoadedApk$ReceiverDispatcher$Args$$ExternalSyntheticLambda0.run(Unknown Source:2)
at android.os.Handler.handleCallback(Handler.java:958)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:205)
at android.os.Looper.loop(Looper.java:294)
at android.app.ActivityThread.main(ActivityThread.java:8177)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
Caused by: kotlin.UninitializedPropertyAccessException: lateinit property handler has not been initialized
at com.rohit.ble_peripheral.BlePeripheralPlugin$broadcastReceiver$1.onReceive(BlePeripheralPlugin.kt:475)
at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0(LoadedApk.java:1802)
... 10 more
So i guess the solution would be to add checks to see if its initialized on the code that catches the state change and if it is, then proceed, if not then don't do anything.
When I call intitialize method, it throws this exception:
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(Exception, java.lang.Exception: Bluetooth Permission not granted, Cause: null, Stacktrace: java.lang.Exception: Bluetooth Permission not granted
at com.rohit.ble_peripheral.BlePeripheralPlugin.initialize(BlePeripheralPlugin.kt:71)
at com.rohit.ble_peripheral.BlePeripheralChannel$Companion.setUp$lambda$1$lambda$0(BlePeripheral.g.kt:277)
at com.rohit.ble_peripheral.BlePeripheralChannel$Companion.$r8$lambda$MnuKy-RVGk0M2vNjak8GFv1UlD4(Unknown Source:0)
at com.rohit.ble_peripheral.BlePeripheralChannel$Companion$$ExternalSyntheticLambda0.onMessage(Unknown Source:2)
at io.flutter.plugin.common.BasicMessageChannel$IncomingMessageHandler.onMessage(BasicMessageChannel.java:219)
at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:295)
at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:322)
at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(Unknown Source:12)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8663)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
, null)
#0 BlePeripheralChannel.initialize (package:ble_peripheral/src/ble_peripheral.g.dart:249:7)
#1 BlePeripheral.initialize (package:ble_peripheral/ble_peripheral.dart:11:5)
First, thank you providing us this repo, it is very helpfull.
From central device with another device I perform a simple write to a characteristic (using flutter blue).
await char1.write(utf8.encode("Test"));
On Peripheral side I am expecting getting the value from callback with
BlePeripheral.setWriteRequestCallback((characteristicId, offset, value) {
Get.log("WriteRequest: $characteristicId : $offset : $value");
String? resultString = value != null ? utf8.decode(value) : null;
print(resultString);
print(value);
print(characteristicId);
}
But I get
I/flutter (27720): null
I/flutter (27720): null
I/flutter (27720): 00002a18-0000-1000-8000-00805f9b34fb
But when I trigger this function (from periphal side)
void updateCharacteristic() async {
for (var device in devices) {
try {
await BlePeripheral.updateCharacteristic(
deviceId: device,
characteristicId: characteristicTest,
value: utf8.encode("Test Data"),
);
} catch (e) {
Get.log("UpdateCharacteristicError: $e");
}
}
}
And then I try to perform a write again from central device, I got the date from the updateCharacterisc in the log each time I trigger the write, and not the null result again.. but still I don't get data from central.
I/flutter (29461): Test Data
I/flutter (29461): [84, 101, 115, 116, 32, 68, 97, 116, 97]
I/flutter (29461): 00002a18-0000-1000-8000-00805f9b34fb
I guess I am missing something here, how could I get within the peripheral the data sent with write from a central device ?
Thank
Running this on Android.
Expected: When localName is not defined => do not broadcast name or use device name.
Error: AdvertisingStatus: false Error Data too large
Current workaround: define localName with a "space" to get around error.
When trying to connect to the server hosted on an Android device, it opens a pairing request on both server and client.
The service and advertising looks like this:
await BlePeripheral.addService(
BleService(
uuid: serviceTicketing,
primary: true,
characteristics: [
BleCharacteristic(
uuid: characteristicTicketing,
properties: [
CharacteristicProperties.write.index,
],
value: null,
permissions: [AttributePermissions.writeable.index],
),
],
),
);
/// set callback for advertising state
BlePeripheral.setAdvertisingStatusUpdateCallback(
(bool advertising, String? error) {
print("AdvertisingStatus: $advertising Error $error");
});
BlePeripheral.setWriteRequestCallback(
(deviceId, characteristicId, offset, value) {
print(
"WriteRequest: $deviceId ${String.fromCharCodes(value?.toList() ?? [])} : $offset : $value ");
final userId = String.fromCharCodes(value?.toList() ?? []);
if (userId.isNotEmpty) {
addUserId(userId);
}
return null;
});
// Start advertising
await BlePeripheral.startAdvertising(
services: [serviceTicketing],
localName: "ticketing",
);
java.lang.RuntimeException: Methods marked with @UiThread must be executed on the main thread. Current thread: Binder:10909_3
at io.flutter.embedding.engine.FlutterJNI.ensureRunningOnMainThread(FlutterJNI.java:1449)
at io.flutter.embedding.engine.FlutterJNI.dispatchPlatformMessage(FlutterJNI.java:1070)
at io.flutter.embedding.engine.dart.DartMessenger.send(DartMessenger.java:282)
at io.flutter.embedding.engine.dart.DartExecutor$DefaultBinaryMessenger.send(DartExecutor.java:470)
at io.flutter.embedding.engine.dart.DartExecutor.send(DartExecutor.java:223)
at io.flutter.plugin.common.BasicMessageChannel.send(BasicMessageChannel.java:106)
at com.rohit.ble_peripheral.BleCallback.onWriteRequest(BlePeripheral.g.kt:490)
at com.rohit.ble_peripheral.BlePeripheralPlugin$gattServerCallback$1.onCharacteristicWriteRequest(BlePeripheralPlugin.kt:373)
at android.bluetooth.BluetoothGattServer$1.onCharacteristicWriteRequest(BluetoothGattServer.java:219)
at android.bluetooth.IBluetoothGattServerCallback$Stub.onTransact(IBluetoothGattServerCallback.java:256)
at android.os.Binder.execTransactInternal(Binder.java:1220)
at android.os.Binder.execTransact(Binder.java:1179)
Steps:
Please help me!
I have given write and read permissions to descriptor still i am getting write not permitted
Add on Mtu Changed Call back in the gattserver callback
The value
parameter in onWriteRequest
method of BleCallback
is returning a null value. I'm using the code of the example app. And using the fixes mentioned in #2
Hey,
I noticed that one of the services passed to the "addServices" function is being added twice. I believe there is an oversight in the "addServices" function (if it is important, I was adding a list with only one service):
as you can see, you add all the services to the queue and then explicitly add the last one, so it looks like it is added twice. (First time with explicit add, next time with queued add)
I have never used kotlin, but I think it can be solved this way:
override fun addServices(services: List<BleService>) {
// To make sure that we are safe from race condition
val totalServices = services.size - 1
val numOfServicesToAdd = if (servicesToAdd.peek() != null) totalServices else (totalServices - 1)
for (i in 0..numOfServicesToAdd) {
servicesToAdd.add(services[i].toGattService())
}
// Start a queue if it isn't started
if (numOfServicesToAdd != totalServices) {
addService(services.last().toGattService())
}
}
I tested this, and this code seems to solve the problem.
If my code is good enough, I can make PR with this change.
Thanks!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.