Update Universal BLE Plugin for Peripheral Support and Code Generation
- Updated autogenerated files to reflect changes from Pigeon v26.3.4. - Added new classes for UniversalBlePeripheralConfig, UniversalBlePeripheralService, UniversalBlePeripheralCharacteristic, UniversalBlePeripheralDescriptor, and UniversalBlePeripheralWriteEvent to handle peripheral configurations and events. - Modified UniversalBlePlugin to implement methods for peripheral support, including StartPeripheral, StopPeripheral, UpdatePeripheralCharacteristicValue, and NotifyPeripheralCharacteristic, returning appropriate error messages for unsupported features on Windows. - Updated HasPermissions method to include an additional parameter for Bluetooth advertising permissions. - Adjusted method signatures and implementations across the plugin to accommodate new peripheral functionality. Signed-off-by: Tony <tonylu@tony-cloud.com>
This commit is contained in:
@@ -7,4 +7,5 @@
|
||||
<uses-permission
|
||||
android:name="android.permission.BLUETOOTH_ADMIN"
|
||||
android:maxSdkVersion="30" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
||||
</manifest>
|
||||
|
||||
@@ -35,12 +35,12 @@ class PermissionHandler(
|
||||
/**
|
||||
* Check if we have required permissions
|
||||
*/
|
||||
fun hasPermissions(withFineLocation: Boolean): Boolean {
|
||||
val validationError = validateRequiredPermissions(withFineLocation)
|
||||
fun hasPermissions(withFineLocation: Boolean, withAdvertise: Boolean): Boolean {
|
||||
val validationError = validateRequiredPermissions(withFineLocation, withAdvertise)
|
||||
if (validationError != null) {
|
||||
throw validationError
|
||||
}
|
||||
val permissionsToRequest = getRequiredPermissions(withFineLocation)
|
||||
val permissionsToRequest = getRequiredPermissions(withFineLocation, withAdvertise)
|
||||
return permissionsToRequest.isEmpty()
|
||||
}
|
||||
|
||||
@@ -55,17 +55,18 @@ class PermissionHandler(
|
||||
*/
|
||||
fun requestPermissions(
|
||||
withFineLocation: Boolean,
|
||||
withAdvertise: Boolean,
|
||||
callback: (Result<Unit>) -> Unit,
|
||||
) {
|
||||
// Validate required permissions are declared in manifest
|
||||
val validationError = validateRequiredPermissions(withFineLocation)
|
||||
val validationError = validateRequiredPermissions(withFineLocation, withAdvertise)
|
||||
if (validationError != null) {
|
||||
callback(Result.failure(validationError))
|
||||
return
|
||||
}
|
||||
|
||||
// Check which permissions need to be requested
|
||||
val permissionsToRequest = getRequiredPermissions(withFineLocation)
|
||||
val permissionsToRequest = getRequiredPermissions(withFineLocation, withAdvertise)
|
||||
|
||||
if (permissionsToRequest.isEmpty()) {
|
||||
// All required permissions are already granted
|
||||
@@ -163,7 +164,7 @@ class PermissionHandler(
|
||||
*
|
||||
* Returns a list of permissions that need to be requested (excluding already granted ones)
|
||||
*/
|
||||
private fun getRequiredPermissions(withFineLocation: Boolean): List<String> {
|
||||
private fun getRequiredPermissions(withFineLocation: Boolean, withAdvertise: Boolean): List<String> {
|
||||
val permissionsToRequest = mutableListOf<String>()
|
||||
// Android 12+ (API 31+)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
@@ -175,6 +176,9 @@ class PermissionHandler(
|
||||
if (!hasPermissionGranted(Manifest.permission.BLUETOOTH_CONNECT)) {
|
||||
permissionsToRequest.add(Manifest.permission.BLUETOOTH_CONNECT)
|
||||
}
|
||||
if (withAdvertise && !hasPermissionGranted(Manifest.permission.BLUETOOTH_ADVERTISE)) {
|
||||
permissionsToRequest.add(Manifest.permission.BLUETOOTH_ADVERTISE)
|
||||
}
|
||||
// Location permission is optional - only request if user wants it
|
||||
if (withFineLocation) {
|
||||
// Prefer ACCESS_FINE_LOCATION over ACCESS_COARSE_LOCATION
|
||||
@@ -236,7 +240,7 @@ class PermissionHandler(
|
||||
* @param withFineLocation Whether location permission should be requested
|
||||
* @return FlutterError if validation fails, null if all required permissions are declared
|
||||
*/
|
||||
private fun validateRequiredPermissions(withFineLocation: Boolean): FlutterError? {
|
||||
private fun validateRequiredPermissions(withFineLocation: Boolean, withAdvertise: Boolean): FlutterError? {
|
||||
val sdkInt = Build.VERSION.SDK_INT
|
||||
val missingPermissions = mutableListOf<String>()
|
||||
|
||||
@@ -259,6 +263,10 @@ class PermissionHandler(
|
||||
missingPermissions.add(Manifest.permission.BLUETOOTH_CONNECT)
|
||||
}
|
||||
|
||||
if (withAdvertise && !hasPermissionInManifest(Manifest.permission.BLUETOOTH_ADVERTISE)) {
|
||||
missingPermissions.add(Manifest.permission.BLUETOOTH_ADVERTISE)
|
||||
}
|
||||
|
||||
// Location permission is optional on Android 12+ (depends on neverForLocation and withFineLocation)
|
||||
// Only validate if it's actually needed
|
||||
if (withFineLocation && !hasDeclaredLocationPermission) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Autogenerated from Pigeon (v26.1.4), do not edit directly.
|
||||
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
|
||||
// See also: https://pub.dev/packages/pigeon
|
||||
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
|
||||
|
||||
@@ -37,36 +37,150 @@ private object UniversalBlePigeonUtils {
|
||||
)
|
||||
}
|
||||
}
|
||||
fun doubleEquals(a: Double, b: Double): Boolean {
|
||||
// Normalize -0.0 to 0.0 and handle NaN equality.
|
||||
return (if (a == 0.0) 0.0 else a) == (if (b == 0.0) 0.0 else b) || (a.isNaN() && b.isNaN())
|
||||
}
|
||||
|
||||
fun floatEquals(a: Float, b: Float): Boolean {
|
||||
// Normalize -0.0 to 0.0 and handle NaN equality.
|
||||
return (if (a == 0.0f) 0.0f else a) == (if (b == 0.0f) 0.0f else b) || (a.isNaN() && b.isNaN())
|
||||
}
|
||||
|
||||
fun doubleHash(d: Double): Int {
|
||||
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
|
||||
val normalized = if (d == 0.0) 0.0 else d
|
||||
val bits = java.lang.Double.doubleToLongBits(normalized)
|
||||
return (bits xor (bits ushr 32)).toInt()
|
||||
}
|
||||
|
||||
fun floatHash(f: Float): Int {
|
||||
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
|
||||
val normalized = if (f == 0.0f) 0.0f else f
|
||||
return java.lang.Float.floatToIntBits(normalized)
|
||||
}
|
||||
|
||||
fun deepEquals(a: Any?, b: Any?): Boolean {
|
||||
if (a === b) {
|
||||
return true
|
||||
}
|
||||
if (a == null || b == null) {
|
||||
return false
|
||||
}
|
||||
if (a is ByteArray && b is ByteArray) {
|
||||
return a.contentEquals(b)
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is IntArray && b is IntArray) {
|
||||
return a.contentEquals(b)
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is LongArray && b is LongArray) {
|
||||
return a.contentEquals(b)
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is DoubleArray && b is DoubleArray) {
|
||||
return a.contentEquals(b)
|
||||
if (a.size != b.size) return false
|
||||
for (i in a.indices) {
|
||||
if (!doubleEquals(a[i], b[i])) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is FloatArray && b is FloatArray) {
|
||||
if (a.size != b.size) return false
|
||||
for (i in a.indices) {
|
||||
if (!floatEquals(a[i], b[i])) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is Array<*> && b is Array<*>) {
|
||||
return a.size == b.size &&
|
||||
a.indices.all{ deepEquals(a[it], b[it]) }
|
||||
if (a.size != b.size) return false
|
||||
for (i in a.indices) {
|
||||
if (!deepEquals(a[i], b[i])) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is List<*> && b is List<*>) {
|
||||
return a.size == b.size &&
|
||||
a.indices.all{ deepEquals(a[it], b[it]) }
|
||||
if (a.size != b.size) return false
|
||||
val iterA = a.iterator()
|
||||
val iterB = b.iterator()
|
||||
while (iterA.hasNext() && iterB.hasNext()) {
|
||||
if (!deepEquals(iterA.next(), iterB.next())) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is Map<*, *> && b is Map<*, *>) {
|
||||
return a.size == b.size && a.all {
|
||||
(b as Map<Any?, Any?>).contains(it.key) &&
|
||||
deepEquals(it.value, b[it.key])
|
||||
if (a.size != b.size) return false
|
||||
for (entry in a) {
|
||||
val key = entry.key
|
||||
var found = false
|
||||
for (bEntry in b) {
|
||||
if (deepEquals(key, bEntry.key)) {
|
||||
if (deepEquals(entry.value, bEntry.value)) {
|
||||
found = true
|
||||
break
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if (a is Double && b is Double) {
|
||||
return doubleEquals(a, b)
|
||||
}
|
||||
if (a is Float && b is Float) {
|
||||
return floatEquals(a, b)
|
||||
}
|
||||
return a == b
|
||||
}
|
||||
|
||||
|
||||
fun deepHash(value: Any?): Int {
|
||||
return when (value) {
|
||||
null -> 0
|
||||
is ByteArray -> value.contentHashCode()
|
||||
is IntArray -> value.contentHashCode()
|
||||
is LongArray -> value.contentHashCode()
|
||||
is DoubleArray -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + doubleHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is FloatArray -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + floatHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is Array<*> -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + deepHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is List<*> -> {
|
||||
var result = 1
|
||||
for (item in value) {
|
||||
result = 31 * result + deepHash(item)
|
||||
}
|
||||
result
|
||||
}
|
||||
is Map<*, *> -> {
|
||||
var result = 0
|
||||
for (entry in value) {
|
||||
result += ((deepHash(entry.key) * 31) xor deepHash(entry.value))
|
||||
}
|
||||
result
|
||||
}
|
||||
is Double -> doubleHash(value)
|
||||
is Float -> floatHash(value)
|
||||
else -> value.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,7 +193,7 @@ class FlutterError (
|
||||
val code: String,
|
||||
override val message: String? = null,
|
||||
val details: Any? = null
|
||||
) : Throwable()
|
||||
) : RuntimeException()
|
||||
|
||||
enum class UniversalBleLogLevel(val raw: Int) {
|
||||
NONE(0),
|
||||
@@ -219,15 +333,28 @@ data class UniversalBleScanResult (
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is UniversalBleScanResult) {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
val other = other as UniversalBleScanResult
|
||||
return UniversalBlePigeonUtils.deepEquals(this.deviceId, other.deviceId) && UniversalBlePigeonUtils.deepEquals(this.name, other.name) && UniversalBlePigeonUtils.deepEquals(this.isPaired, other.isPaired) && UniversalBlePigeonUtils.deepEquals(this.rssi, other.rssi) && UniversalBlePigeonUtils.deepEquals(this.manufacturerDataList, other.manufacturerDataList) && UniversalBlePigeonUtils.deepEquals(this.serviceData, other.serviceData) && UniversalBlePigeonUtils.deepEquals(this.services, other.services) && UniversalBlePigeonUtils.deepEquals(this.timestamp, other.timestamp)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.deviceId)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.name)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.isPaired)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.rssi)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.manufacturerDataList)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.serviceData)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.services)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.timestamp)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
@@ -250,15 +377,22 @@ data class UniversalBleService (
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is UniversalBleService) {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
val other = other as UniversalBleService
|
||||
return UniversalBlePigeonUtils.deepEquals(this.uuid, other.uuid) && UniversalBlePigeonUtils.deepEquals(this.characteristics, other.characteristics)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.uuid)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.characteristics)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
@@ -284,15 +418,23 @@ data class UniversalBleCharacteristic (
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is UniversalBleCharacteristic) {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
val other = other as UniversalBleCharacteristic
|
||||
return UniversalBlePigeonUtils.deepEquals(this.uuid, other.uuid) && UniversalBlePigeonUtils.deepEquals(this.properties, other.properties) && UniversalBlePigeonUtils.deepEquals(this.descriptors, other.descriptors)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.uuid)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.properties)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.descriptors)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
@@ -312,15 +454,235 @@ data class UniversalBleDescriptor (
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is UniversalBleDescriptor) {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
val other = other as UniversalBleDescriptor
|
||||
return UniversalBlePigeonUtils.deepEquals(this.uuid, other.uuid)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.uuid)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class UniversalBlePeripheralConfig (
|
||||
val advertisedName: String,
|
||||
val services: List<UniversalBlePeripheralService>
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): UniversalBlePeripheralConfig {
|
||||
val advertisedName = pigeonVar_list[0] as String
|
||||
val services = pigeonVar_list[1] as List<UniversalBlePeripheralService>
|
||||
return UniversalBlePeripheralConfig(advertisedName, services)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
advertisedName,
|
||||
services,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
val other = other as UniversalBlePeripheralConfig
|
||||
return UniversalBlePigeonUtils.deepEquals(this.advertisedName, other.advertisedName) && UniversalBlePigeonUtils.deepEquals(this.services, other.services)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.advertisedName)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.services)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class UniversalBlePeripheralService (
|
||||
val uuid: String,
|
||||
val characteristics: List<UniversalBlePeripheralCharacteristic>
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): UniversalBlePeripheralService {
|
||||
val uuid = pigeonVar_list[0] as String
|
||||
val characteristics = pigeonVar_list[1] as List<UniversalBlePeripheralCharacteristic>
|
||||
return UniversalBlePeripheralService(uuid, characteristics)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
uuid,
|
||||
characteristics,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
val other = other as UniversalBlePeripheralService
|
||||
return UniversalBlePigeonUtils.deepEquals(this.uuid, other.uuid) && UniversalBlePigeonUtils.deepEquals(this.characteristics, other.characteristics)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.uuid)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.characteristics)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class UniversalBlePeripheralCharacteristic (
|
||||
val uuid: String,
|
||||
val properties: List<Long>,
|
||||
val permissions: List<Long>,
|
||||
val descriptors: List<UniversalBlePeripheralDescriptor>,
|
||||
val initialValue: ByteArray? = null
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): UniversalBlePeripheralCharacteristic {
|
||||
val uuid = pigeonVar_list[0] as String
|
||||
val properties = pigeonVar_list[1] as List<Long>
|
||||
val permissions = pigeonVar_list[2] as List<Long>
|
||||
val descriptors = pigeonVar_list[3] as List<UniversalBlePeripheralDescriptor>
|
||||
val initialValue = pigeonVar_list[4] as ByteArray?
|
||||
return UniversalBlePeripheralCharacteristic(uuid, properties, permissions, descriptors, initialValue)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
uuid,
|
||||
properties,
|
||||
permissions,
|
||||
descriptors,
|
||||
initialValue,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
val other = other as UniversalBlePeripheralCharacteristic
|
||||
return UniversalBlePigeonUtils.deepEquals(this.uuid, other.uuid) && UniversalBlePigeonUtils.deepEquals(this.properties, other.properties) && UniversalBlePigeonUtils.deepEquals(this.permissions, other.permissions) && UniversalBlePigeonUtils.deepEquals(this.descriptors, other.descriptors) && UniversalBlePigeonUtils.deepEquals(this.initialValue, other.initialValue)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.uuid)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.properties)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.permissions)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.descriptors)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.initialValue)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class UniversalBlePeripheralDescriptor (
|
||||
val uuid: String,
|
||||
val permissions: List<Long>,
|
||||
val initialValue: ByteArray? = null
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): UniversalBlePeripheralDescriptor {
|
||||
val uuid = pigeonVar_list[0] as String
|
||||
val permissions = pigeonVar_list[1] as List<Long>
|
||||
val initialValue = pigeonVar_list[2] as ByteArray?
|
||||
return UniversalBlePeripheralDescriptor(uuid, permissions, initialValue)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
uuid,
|
||||
permissions,
|
||||
initialValue,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
val other = other as UniversalBlePeripheralDescriptor
|
||||
return UniversalBlePigeonUtils.deepEquals(this.uuid, other.uuid) && UniversalBlePigeonUtils.deepEquals(this.permissions, other.permissions) && UniversalBlePigeonUtils.deepEquals(this.initialValue, other.initialValue)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.uuid)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.permissions)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.initialValue)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class UniversalBlePeripheralWriteEvent (
|
||||
val deviceId: String,
|
||||
val service: String,
|
||||
val characteristic: String,
|
||||
val value: ByteArray
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): UniversalBlePeripheralWriteEvent {
|
||||
val deviceId = pigeonVar_list[0] as String
|
||||
val service = pigeonVar_list[1] as String
|
||||
val characteristic = pigeonVar_list[2] as String
|
||||
val value = pigeonVar_list[3] as ByteArray
|
||||
return UniversalBlePeripheralWriteEvent(deviceId, service, characteristic, value)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
deviceId,
|
||||
service,
|
||||
characteristic,
|
||||
value,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
val other = other as UniversalBlePeripheralWriteEvent
|
||||
return UniversalBlePigeonUtils.deepEquals(this.deviceId, other.deviceId) && UniversalBlePigeonUtils.deepEquals(this.service, other.service) && UniversalBlePigeonUtils.deepEquals(this.characteristic, other.characteristic) && UniversalBlePigeonUtils.deepEquals(this.value, other.value)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.deviceId)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.service)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.characteristic)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.value)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -355,15 +717,23 @@ data class AndroidOptions (
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is AndroidOptions) {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
val other = other as AndroidOptions
|
||||
return UniversalBlePigeonUtils.deepEquals(this.requestLocationPermission, other.requestLocationPermission) && UniversalBlePigeonUtils.deepEquals(this.scanMode, other.scanMode) && UniversalBlePigeonUtils.deepEquals(this.reportDelayMillis, other.reportDelayMillis)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.requestLocationPermission)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.scanMode)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.reportDelayMillis)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
@@ -383,15 +753,21 @@ data class UniversalScanConfig (
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is UniversalScanConfig) {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
val other = other as UniversalScanConfig
|
||||
return UniversalBlePigeonUtils.deepEquals(this.android, other.android)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.android)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -421,15 +797,23 @@ data class UniversalScanFilter (
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is UniversalScanFilter) {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
val other = other as UniversalScanFilter
|
||||
return UniversalBlePigeonUtils.deepEquals(this.withServices, other.withServices) && UniversalBlePigeonUtils.deepEquals(this.withNamePrefix, other.withNamePrefix) && UniversalBlePigeonUtils.deepEquals(this.withManufacturerData, other.withManufacturerData)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.withServices)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.withNamePrefix)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.withManufacturerData)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
@@ -455,15 +839,23 @@ data class UniversalManufacturerDataFilter (
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is UniversalManufacturerDataFilter) {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
val other = other as UniversalManufacturerDataFilter
|
||||
return UniversalBlePigeonUtils.deepEquals(this.companyIdentifier, other.companyIdentifier) && UniversalBlePigeonUtils.deepEquals(this.data, other.data) && UniversalBlePigeonUtils.deepEquals(this.mask, other.mask)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.companyIdentifier)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.data)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.mask)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
@@ -486,15 +878,22 @@ data class UniversalManufacturerData (
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is UniversalManufacturerData) {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
return UniversalBlePigeonUtils.deepEquals(toList(), other.toList()) }
|
||||
val other = other as UniversalManufacturerData
|
||||
return UniversalBlePigeonUtils.deepEquals(this.companyIdentifier, other.companyIdentifier) && UniversalBlePigeonUtils.deepEquals(this.data, other.data)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = toList().hashCode()
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.companyIdentifier)
|
||||
result = 31 * result + UniversalBlePigeonUtils.deepHash(this.data)
|
||||
return result
|
||||
}
|
||||
}
|
||||
private open class UniversalBlePigeonCodec : StandardMessageCodec() {
|
||||
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
|
||||
@@ -536,25 +935,50 @@ private open class UniversalBlePigeonCodec : StandardMessageCodec() {
|
||||
}
|
||||
136.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
AndroidOptions.fromList(it)
|
||||
UniversalBlePeripheralConfig.fromList(it)
|
||||
}
|
||||
}
|
||||
137.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
UniversalScanConfig.fromList(it)
|
||||
UniversalBlePeripheralService.fromList(it)
|
||||
}
|
||||
}
|
||||
138.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
UniversalScanFilter.fromList(it)
|
||||
UniversalBlePeripheralCharacteristic.fromList(it)
|
||||
}
|
||||
}
|
||||
139.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
UniversalManufacturerDataFilter.fromList(it)
|
||||
UniversalBlePeripheralDescriptor.fromList(it)
|
||||
}
|
||||
}
|
||||
140.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
UniversalBlePeripheralWriteEvent.fromList(it)
|
||||
}
|
||||
}
|
||||
141.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
AndroidOptions.fromList(it)
|
||||
}
|
||||
}
|
||||
142.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
UniversalScanConfig.fromList(it)
|
||||
}
|
||||
}
|
||||
143.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
UniversalScanFilter.fromList(it)
|
||||
}
|
||||
}
|
||||
144.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
UniversalManufacturerDataFilter.fromList(it)
|
||||
}
|
||||
}
|
||||
145.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
UniversalManufacturerData.fromList(it)
|
||||
}
|
||||
@@ -592,26 +1016,46 @@ private open class UniversalBlePigeonCodec : StandardMessageCodec() {
|
||||
stream.write(135)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is AndroidOptions -> {
|
||||
is UniversalBlePeripheralConfig -> {
|
||||
stream.write(136)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is UniversalScanConfig -> {
|
||||
is UniversalBlePeripheralService -> {
|
||||
stream.write(137)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is UniversalScanFilter -> {
|
||||
is UniversalBlePeripheralCharacteristic -> {
|
||||
stream.write(138)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is UniversalManufacturerDataFilter -> {
|
||||
is UniversalBlePeripheralDescriptor -> {
|
||||
stream.write(139)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is UniversalManufacturerData -> {
|
||||
is UniversalBlePeripheralWriteEvent -> {
|
||||
stream.write(140)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is AndroidOptions -> {
|
||||
stream.write(141)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is UniversalScanConfig -> {
|
||||
stream.write(142)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is UniversalScanFilter -> {
|
||||
stream.write(143)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is UniversalManufacturerDataFilter -> {
|
||||
stream.write(144)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is UniversalManufacturerData -> {
|
||||
stream.write(145)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
else -> super.writeValue(stream, value)
|
||||
}
|
||||
}
|
||||
@@ -625,8 +1069,8 @@ private open class UniversalBlePigeonCodec : StandardMessageCodec() {
|
||||
*/
|
||||
interface UniversalBlePlatformChannel {
|
||||
fun getBluetoothAvailabilityState(callback: (Result<Long>) -> Unit)
|
||||
fun hasPermissions(withAndroidFineLocation: Boolean): Boolean
|
||||
fun requestPermissions(withAndroidFineLocation: Boolean, callback: (Result<Unit>) -> Unit)
|
||||
fun hasPermissions(withAndroidFineLocation: Boolean, withAndroidBluetoothAdvertise: Boolean): Boolean
|
||||
fun requestPermissions(withAndroidFineLocation: Boolean, withAndroidBluetoothAdvertise: Boolean, callback: (Result<Unit>) -> Unit)
|
||||
fun enableBluetooth(callback: (Result<Boolean>) -> Unit)
|
||||
fun disableBluetooth(callback: (Result<Boolean>) -> Unit)
|
||||
fun startScan(filter: UniversalScanFilter?, config: UniversalScanConfig?)
|
||||
@@ -646,6 +1090,11 @@ interface UniversalBlePlatformChannel {
|
||||
fun getConnectionState(deviceId: String): Long
|
||||
fun readRssi(deviceId: String, callback: (Result<Long>) -> Unit)
|
||||
fun requestConnectionPriority(deviceId: String, priority: Long, callback: (Result<Unit>) -> Unit)
|
||||
fun isPeripheralSupported(): Boolean
|
||||
fun startPeripheral(config: UniversalBlePeripheralConfig, callback: (Result<Unit>) -> Unit)
|
||||
fun stopPeripheral(callback: (Result<Unit>) -> Unit)
|
||||
fun updatePeripheralCharacteristicValue(service: String, characteristic: String, value: ByteArray, callback: (Result<Unit>) -> Unit)
|
||||
fun notifyPeripheralCharacteristic(service: String, characteristic: String, value: ByteArray, indicate: Boolean, callback: (Result<Unit>) -> Unit)
|
||||
fun setLogLevel(logLevel: UniversalBleLogLevel)
|
||||
|
||||
companion object {
|
||||
@@ -681,8 +1130,9 @@ interface UniversalBlePlatformChannel {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val withAndroidFineLocationArg = args[0] as Boolean
|
||||
val withAndroidBluetoothAdvertiseArg = args[1] as Boolean
|
||||
val wrapped: List<Any?> = try {
|
||||
listOf(api.hasPermissions(withAndroidFineLocationArg))
|
||||
listOf(api.hasPermissions(withAndroidFineLocationArg, withAndroidBluetoothAdvertiseArg))
|
||||
} catch (exception: Throwable) {
|
||||
UniversalBlePigeonUtils.wrapError(exception)
|
||||
}
|
||||
@@ -698,7 +1148,8 @@ interface UniversalBlePlatformChannel {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val withAndroidFineLocationArg = args[0] as Boolean
|
||||
api.requestPermissions(withAndroidFineLocationArg) { result: Result<Unit> ->
|
||||
val withAndroidBluetoothAdvertiseArg = args[1] as Boolean
|
||||
api.requestPermissions(withAndroidFineLocationArg, withAndroidBluetoothAdvertiseArg) { result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||
@@ -1078,6 +1529,100 @@ interface UniversalBlePlatformChannel {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isPeripheralSupported$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
val wrapped: List<Any?> = try {
|
||||
listOf(api.isPeripheralSupported())
|
||||
} catch (exception: Throwable) {
|
||||
UniversalBlePigeonUtils.wrapError(exception)
|
||||
}
|
||||
reply.reply(wrapped)
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.startPeripheral$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val configArg = args[0] as UniversalBlePeripheralConfig
|
||||
api.startPeripheral(configArg) { result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||
} else {
|
||||
reply.reply(UniversalBlePigeonUtils.wrapResult(null))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.stopPeripheral$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
api.stopPeripheral{ result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||
} else {
|
||||
reply.reply(UniversalBlePigeonUtils.wrapResult(null))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.updatePeripheralCharacteristicValue$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val serviceArg = args[0] as String
|
||||
val characteristicArg = args[1] as String
|
||||
val valueArg = args[2] as ByteArray
|
||||
api.updatePeripheralCharacteristicValue(serviceArg, characteristicArg, valueArg) { result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||
} else {
|
||||
reply.reply(UniversalBlePigeonUtils.wrapResult(null))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.notifyPeripheralCharacteristic$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val serviceArg = args[0] as String
|
||||
val characteristicArg = args[1] as String
|
||||
val valueArg = args[2] as ByteArray
|
||||
val indicateArg = args[3] as Boolean
|
||||
api.notifyPeripheralCharacteristic(serviceArg, characteristicArg, valueArg, indicateArg) { result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(UniversalBlePigeonUtils.wrapError(error))
|
||||
} else {
|
||||
reply.reply(UniversalBlePigeonUtils.wrapResult(null))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.setLogLevel$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
@@ -1125,7 +1670,7 @@ class UniversalBleCallbackChannel(private val binaryMessenger: BinaryMessenger,
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(UniversalBlePigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fun onPairStateChange(deviceIdArg: String, isPairedArg: Boolean, errorArg: String?, callback: (Result<Unit>) -> Unit)
|
||||
@@ -1142,7 +1687,7 @@ class UniversalBleCallbackChannel(private val binaryMessenger: BinaryMessenger,
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(UniversalBlePigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fun onScanResult(resultArg: UniversalBleScanResult, callback: (Result<Unit>) -> Unit)
|
||||
@@ -1159,7 +1704,7 @@ class UniversalBleCallbackChannel(private val binaryMessenger: BinaryMessenger,
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(UniversalBlePigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fun onValueChanged(deviceIdArg: String, characteristicIdArg: String, valueArg: ByteArray, timestampArg: Long?, callback: (Result<Unit>) -> Unit)
|
||||
@@ -1176,7 +1721,7 @@ class UniversalBleCallbackChannel(private val binaryMessenger: BinaryMessenger,
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(UniversalBlePigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fun onConnectionChanged(deviceIdArg: String, connectedArg: Boolean, errorArg: String?, callback: (Result<Unit>) -> Unit)
|
||||
@@ -1193,7 +1738,58 @@ class UniversalBleCallbackChannel(private val binaryMessenger: BinaryMessenger,
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(UniversalBlePigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fun onPeripheralConnectionChanged(deviceIdArg: String, connectedArg: Boolean, callback: (Result<Unit>) -> Unit)
|
||||
{
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
val channelName = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPeripheralConnectionChanged$separatedMessageChannelSuffix"
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
||||
channel.send(listOf(deviceIdArg, connectedArg)) {
|
||||
if (it is List<*>) {
|
||||
if (it.size > 1) {
|
||||
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
||||
} else {
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(UniversalBlePigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
fun onPeripheralWrite(eventArg: UniversalBlePeripheralWriteEvent, callback: (Result<Unit>) -> Unit)
|
||||
{
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
val channelName = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPeripheralWrite$separatedMessageChannelSuffix"
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
||||
channel.send(listOf(eventArg)) {
|
||||
if (it is List<*>) {
|
||||
if (it.size > 1) {
|
||||
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
||||
} else {
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(UniversalBlePigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
fun onPeripheralSubscriptionChanged(deviceIdArg: String, serviceArg: String, characteristicArg: String, subscribedArg: Boolean, callback: (Result<Unit>) -> Unit)
|
||||
{
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
val channelName = "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPeripheralSubscriptionChanged$separatedMessageChannelSuffix"
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
||||
channel.send(listOf(deviceIdArg, serviceArg, characteristicArg, subscribedArg)) {
|
||||
if (it is List<*>) {
|
||||
if (it.size > 1) {
|
||||
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
||||
} else {
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
} else {
|
||||
callback(Result.failure(UniversalBlePigeonUtils.createConnectionError(channelName)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,16 @@ import android.bluetooth.BluetoothGatt
|
||||
import android.bluetooth.BluetoothGattCallback
|
||||
import android.bluetooth.BluetoothGattCharacteristic
|
||||
import android.bluetooth.BluetoothGattDescriptor
|
||||
import android.bluetooth.BluetoothGattServer
|
||||
import android.bluetooth.BluetoothGattServerCallback
|
||||
import android.bluetooth.BluetoothGattService
|
||||
import android.bluetooth.BluetoothManager
|
||||
import android.bluetooth.BluetoothProfile
|
||||
import android.bluetooth.BluetoothStatusCodes
|
||||
import android.bluetooth.le.AdvertiseCallback
|
||||
import android.bluetooth.le.AdvertiseData
|
||||
import android.bluetooth.le.AdvertiseSettings
|
||||
import android.bluetooth.le.BluetoothLeAdvertiser
|
||||
import android.bluetooth.le.ScanCallback
|
||||
import android.bluetooth.le.ScanFilter
|
||||
import android.bluetooth.le.ScanResult
|
||||
@@ -24,6 +31,7 @@ import android.content.IntentFilter
|
||||
import android.os.Build
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.ParcelUuid
|
||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityAware
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
|
||||
@@ -63,6 +71,12 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
private val rssiResultFutureList = mutableListOf<RssiResultFuture>()
|
||||
private val autoConnectDevices = mutableSetOf<String>()
|
||||
|
||||
private var peripheralGattServer: BluetoothGattServer? = null
|
||||
private var peripheralAdvertiser: BluetoothLeAdvertiser? = null
|
||||
private var peripheralPendingStartCallback: ((Result<Unit>) -> Unit)? = null
|
||||
private val peripheralConnectedDevices = mutableSetOf<BluetoothDevice>()
|
||||
private val peripheralCharacteristics = mutableMapOf<String, BluetoothGattCharacteristic>()
|
||||
|
||||
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
|
||||
UniversalBlePlatformChannel.setUp(flutterPluginBinding.binaryMessenger, this)
|
||||
callbackChannel = UniversalBleCallbackChannel(flutterPluginBinding.binaryMessenger)
|
||||
@@ -84,6 +98,7 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
|
||||
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
|
||||
bluetoothManager.adapter.bluetoothLeScanner?.stopScan(scanCallback)
|
||||
stopPeripheralInternal()
|
||||
context.unregisterReceiver(broadcastReceiver)
|
||||
callbackChannel = null
|
||||
mainThreadHandler = null
|
||||
@@ -99,12 +114,19 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
)
|
||||
}
|
||||
|
||||
override fun hasPermissions(withAndroidFineLocation: Boolean): Boolean {
|
||||
return permissionHandler?.hasPermissions(withAndroidFineLocation) ?: false
|
||||
override fun hasPermissions(
|
||||
withAndroidFineLocation: Boolean,
|
||||
withAndroidBluetoothAdvertise: Boolean,
|
||||
): Boolean {
|
||||
return permissionHandler?.hasPermissions(
|
||||
withAndroidFineLocation,
|
||||
withAndroidBluetoothAdvertise,
|
||||
) ?: false
|
||||
}
|
||||
|
||||
override fun requestPermissions(
|
||||
withAndroidFineLocation: Boolean,
|
||||
withAndroidBluetoothAdvertise: Boolean,
|
||||
callback: (Result<Unit>) -> Unit,
|
||||
) {
|
||||
if (permissionHandler == null) {
|
||||
@@ -117,7 +139,11 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
)
|
||||
)
|
||||
}
|
||||
permissionHandler?.requestPermissions(withAndroidFineLocation, callback)
|
||||
permissionHandler?.requestPermissions(
|
||||
withAndroidFineLocation,
|
||||
withAndroidBluetoothAdvertise,
|
||||
callback,
|
||||
)
|
||||
}
|
||||
|
||||
override fun enableBluetooth(callback: (Result<Boolean>) -> Unit) {
|
||||
@@ -801,6 +827,319 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
}
|
||||
}
|
||||
|
||||
override fun isPeripheralSupported(): Boolean {
|
||||
val adapter = bluetoothManager.adapter ?: return false
|
||||
return adapter.isEnabled && adapter.isMultipleAdvertisementSupported
|
||||
}
|
||||
|
||||
override fun startPeripheral(
|
||||
config: UniversalBlePeripheralConfig,
|
||||
callback: (Result<Unit>) -> Unit,
|
||||
) {
|
||||
val adapter = bluetoothManager.adapter
|
||||
if (adapter == null || !adapter.isEnabled) {
|
||||
callback(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.BLUETOOTH_NOT_ENABLED,
|
||||
"Bluetooth not enabled"
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
if (!adapter.isMultipleAdvertisementSupported) {
|
||||
callback(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.NOT_SUPPORTED,
|
||||
"BLE peripheral advertising is not supported on this device"
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
if (peripheralPendingStartCallback != null) {
|
||||
callback(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.OPERATION_IN_PROGRESS,
|
||||
"Peripheral start already in progress"
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
stopPeripheralInternal()
|
||||
|
||||
val server = bluetoothManager.openGattServer(context, peripheralGattServerCallback)
|
||||
if (server == null) {
|
||||
callback(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.FAILED,
|
||||
"Unable to open GATT server"
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
peripheralCharacteristics.clear()
|
||||
config.services.forEach { serviceConfig ->
|
||||
val service = BluetoothGattService(
|
||||
UUID.fromString(serviceConfig.uuid),
|
||||
BluetoothGattService.SERVICE_TYPE_PRIMARY,
|
||||
)
|
||||
serviceConfig.characteristics.forEach { characteristicConfig ->
|
||||
val characteristic = BluetoothGattCharacteristic(
|
||||
UUID.fromString(characteristicConfig.uuid),
|
||||
characteristicConfig.properties.toPeripheralPropertyFlags(),
|
||||
characteristicConfig.permissions.toPeripheralPermissionFlags(),
|
||||
)
|
||||
@Suppress("DEPRECATION")
|
||||
characteristic.value = characteristicConfig.initialValue ?: ByteArray(0)
|
||||
characteristicConfig.descriptors.forEach { descriptorConfig ->
|
||||
val descriptor = BluetoothGattDescriptor(
|
||||
UUID.fromString(descriptorConfig.uuid),
|
||||
descriptorConfig.permissions.toPeripheralPermissionFlags(),
|
||||
)
|
||||
@Suppress("DEPRECATION")
|
||||
descriptor.value = descriptorConfig.initialValue ?: ByteArray(0)
|
||||
characteristic.addDescriptor(descriptor)
|
||||
}
|
||||
if (characteristicConfig.properties.any {
|
||||
it == CharacteristicProperty.Notify.value ||
|
||||
it == CharacteristicProperty.Indicate.value
|
||||
} && characteristic.getDescriptor(ccdCharacteristic) == null
|
||||
) {
|
||||
characteristic.addDescriptor(
|
||||
BluetoothGattDescriptor(
|
||||
ccdCharacteristic,
|
||||
BluetoothGattDescriptor.PERMISSION_READ or
|
||||
BluetoothGattDescriptor.PERMISSION_WRITE,
|
||||
)
|
||||
)
|
||||
}
|
||||
service.addCharacteristic(characteristic)
|
||||
peripheralCharacteristics[peripheralCharacteristicKey(serviceConfig.uuid, characteristicConfig.uuid)] = characteristic
|
||||
}
|
||||
if (!server.addService(service)) {
|
||||
throw createFlutterError(
|
||||
UniversalBleErrorCode.FAILED,
|
||||
"Failed to add GATT service ${serviceConfig.uuid}"
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch (e: FlutterError) {
|
||||
server.close()
|
||||
peripheralCharacteristics.clear()
|
||||
callback(Result.failure(e))
|
||||
return
|
||||
} catch (e: Exception) {
|
||||
server.close()
|
||||
peripheralCharacteristics.clear()
|
||||
callback(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.FAILED,
|
||||
"Failed to create GATT services",
|
||||
e.toString()
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
peripheralGattServer = server
|
||||
try {
|
||||
adapter.name = config.advertisedName
|
||||
} catch (_: SecurityException) {
|
||||
}
|
||||
|
||||
val advertiser = adapter.bluetoothLeAdvertiser
|
||||
if (advertiser == null) {
|
||||
stopPeripheralInternal()
|
||||
callback(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.NOT_SUPPORTED,
|
||||
"BLE advertiser not available"
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
val settings = AdvertiseSettings.Builder()
|
||||
.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED)
|
||||
.setConnectable(true)
|
||||
.setTimeout(0)
|
||||
.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM)
|
||||
.build()
|
||||
val dataBuilder = AdvertiseData.Builder().setIncludeDeviceName(true)
|
||||
config.services.forEach { service ->
|
||||
dataBuilder.addServiceUuid(ParcelUuid(UUID.fromString(service.uuid)))
|
||||
}
|
||||
peripheralAdvertiser = advertiser
|
||||
peripheralPendingStartCallback = callback
|
||||
advertiser.startAdvertising(settings, dataBuilder.build(), peripheralAdvertiseCallback)
|
||||
}
|
||||
|
||||
override fun stopPeripheral(callback: (Result<Unit>) -> Unit) {
|
||||
peripheralPendingStartCallback?.invoke(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.OPERATION_CANCELLED,
|
||||
"Peripheral start cancelled"
|
||||
)
|
||||
)
|
||||
)
|
||||
peripheralPendingStartCallback = null
|
||||
stopPeripheralInternal()
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
|
||||
override fun updatePeripheralCharacteristicValue(
|
||||
service: String,
|
||||
characteristic: String,
|
||||
value: ByteArray,
|
||||
callback: (Result<Unit>) -> Unit,
|
||||
) {
|
||||
val gattCharacteristic = peripheralCharacteristics[peripheralCharacteristicKey(service, characteristic)]
|
||||
if (gattCharacteristic == null) {
|
||||
callback(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.CHARACTERISTIC_NOT_FOUND,
|
||||
"Unknown peripheral characteristic $characteristic"
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
@Suppress("DEPRECATION")
|
||||
gattCharacteristic.value = value
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
|
||||
override fun notifyPeripheralCharacteristic(
|
||||
service: String,
|
||||
characteristic: String,
|
||||
value: ByteArray,
|
||||
indicate: Boolean,
|
||||
callback: (Result<Unit>) -> Unit,
|
||||
) {
|
||||
val server = peripheralGattServer
|
||||
val gattCharacteristic = peripheralCharacteristics[peripheralCharacteristicKey(service, characteristic)]
|
||||
if (server == null || gattCharacteristic == null) {
|
||||
callback(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.CHARACTERISTIC_NOT_FOUND,
|
||||
"Unknown peripheral characteristic $characteristic"
|
||||
)
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
@Suppress("DEPRECATION")
|
||||
gattCharacteristic.value = value
|
||||
val devices = synchronized(peripheralConnectedDevices) {
|
||||
peripheralConnectedDevices.toList()
|
||||
}
|
||||
devices.forEach { device ->
|
||||
server.notifyCharacteristicChanged(device, gattCharacteristic, indicate)
|
||||
}
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
|
||||
private fun stopPeripheralInternal() {
|
||||
peripheralAdvertiser?.stopAdvertising(peripheralAdvertiseCallback)
|
||||
peripheralAdvertiser = null
|
||||
peripheralGattServer?.close()
|
||||
peripheralGattServer = null
|
||||
synchronized(peripheralConnectedDevices) {
|
||||
peripheralConnectedDevices.clear()
|
||||
}
|
||||
peripheralCharacteristics.clear()
|
||||
}
|
||||
|
||||
private fun peripheralCharacteristicKey(service: String, characteristic: String): String {
|
||||
return "${service.lowercase()}|${characteristic.lowercase()}"
|
||||
}
|
||||
|
||||
private fun List<Long>.toPeripheralPropertyFlags(): Int {
|
||||
var flags = 0
|
||||
forEach { property ->
|
||||
when (CharacteristicProperty.entries.firstOrNull { it.value == property }) {
|
||||
CharacteristicProperty.Broadcast -> flags = flags or BluetoothGattCharacteristic.PROPERTY_BROADCAST
|
||||
CharacteristicProperty.Read -> flags = flags or BluetoothGattCharacteristic.PROPERTY_READ
|
||||
CharacteristicProperty.WriteWithoutResponse -> flags = flags or BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE
|
||||
CharacteristicProperty.Write -> flags = flags or BluetoothGattCharacteristic.PROPERTY_WRITE
|
||||
CharacteristicProperty.Notify -> flags = flags or BluetoothGattCharacteristic.PROPERTY_NOTIFY
|
||||
CharacteristicProperty.Indicate -> flags = flags or BluetoothGattCharacteristic.PROPERTY_INDICATE
|
||||
CharacteristicProperty.AuthenticatedSignedWrites -> flags = flags or BluetoothGattCharacteristic.PROPERTY_SIGNED_WRITE
|
||||
CharacteristicProperty.ExtendedProperties -> flags = flags or BluetoothGattCharacteristic.PROPERTY_EXTENDED_PROPS
|
||||
null -> {}
|
||||
}
|
||||
}
|
||||
return flags
|
||||
}
|
||||
|
||||
private fun List<Long>.toPeripheralPermissionFlags(): Int {
|
||||
var flags = 0
|
||||
forEach { permission ->
|
||||
when (permission) {
|
||||
0L -> flags = flags or BluetoothGattCharacteristic.PERMISSION_READ
|
||||
1L -> flags = flags or BluetoothGattCharacteristic.PERMISSION_WRITE
|
||||
}
|
||||
}
|
||||
return flags
|
||||
}
|
||||
|
||||
private fun callbackPeripheralConnection(deviceId: String, connected: Boolean) {
|
||||
mainThreadHandler?.post {
|
||||
callbackChannel?.onPeripheralConnectionChanged(deviceId, connected) {}
|
||||
}
|
||||
}
|
||||
|
||||
private fun callbackPeripheralSubscription(
|
||||
deviceId: String,
|
||||
service: String,
|
||||
characteristic: String,
|
||||
subscribed: Boolean,
|
||||
) {
|
||||
mainThreadHandler?.post {
|
||||
callbackChannel?.onPeripheralSubscriptionChanged(
|
||||
deviceId,
|
||||
service,
|
||||
characteristic,
|
||||
subscribed,
|
||||
) {}
|
||||
}
|
||||
}
|
||||
|
||||
private fun callbackPeripheralWrite(
|
||||
deviceId: String,
|
||||
service: String,
|
||||
characteristic: String,
|
||||
value: ByteArray,
|
||||
) {
|
||||
mainThreadHandler?.post {
|
||||
callbackChannel?.onPeripheralWrite(
|
||||
UniversalBlePeripheralWriteEvent(
|
||||
deviceId,
|
||||
service,
|
||||
characteristic,
|
||||
value,
|
||||
)
|
||||
) {}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMtuChanged(gatt: BluetoothGatt?, mtu: Int, status: Int) {
|
||||
val deviceId = gatt?.device?.address ?: return
|
||||
mtuResultFutureList.removeAll {
|
||||
@@ -1191,6 +1530,157 @@ class UniversalBlePlugin : UniversalBlePlatformChannel, BluetoothGattCallback(),
|
||||
}
|
||||
}
|
||||
|
||||
private val peripheralAdvertiseCallback = object : AdvertiseCallback() {
|
||||
override fun onStartSuccess(settingsInEffect: AdvertiseSettings) {
|
||||
peripheralPendingStartCallback?.invoke(Result.success(Unit))
|
||||
peripheralPendingStartCallback = null
|
||||
}
|
||||
|
||||
override fun onStartFailure(errorCode: Int) {
|
||||
peripheralPendingStartCallback?.invoke(
|
||||
Result.failure(
|
||||
createFlutterError(
|
||||
UniversalBleErrorCode.FAILED,
|
||||
"BLE advertising failed with code $errorCode",
|
||||
errorCode.toString()
|
||||
)
|
||||
)
|
||||
)
|
||||
peripheralPendingStartCallback = null
|
||||
stopPeripheralInternal()
|
||||
}
|
||||
}
|
||||
|
||||
private val peripheralGattServerCallback = object : BluetoothGattServerCallback() {
|
||||
override fun onConnectionStateChange(device: BluetoothDevice, status: Int, newState: Int) {
|
||||
if (newState == BluetoothProfile.STATE_CONNECTED) {
|
||||
synchronized(peripheralConnectedDevices) {
|
||||
peripheralConnectedDevices.add(device)
|
||||
}
|
||||
callbackPeripheralConnection(device.address, true)
|
||||
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
|
||||
synchronized(peripheralConnectedDevices) {
|
||||
peripheralConnectedDevices.remove(device)
|
||||
}
|
||||
callbackPeripheralConnection(device.address, false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCharacteristicReadRequest(
|
||||
device: BluetoothDevice,
|
||||
requestId: Int,
|
||||
offset: Int,
|
||||
characteristic: BluetoothGattCharacteristic,
|
||||
) {
|
||||
@Suppress("DEPRECATION")
|
||||
val value = characteristic.value ?: ByteArray(0)
|
||||
if (offset > value.size) {
|
||||
peripheralGattServer?.sendResponse(
|
||||
device,
|
||||
requestId,
|
||||
BluetoothGatt.GATT_INVALID_OFFSET,
|
||||
offset,
|
||||
null,
|
||||
)
|
||||
return
|
||||
}
|
||||
peripheralGattServer?.sendResponse(
|
||||
device,
|
||||
requestId,
|
||||
BluetoothGatt.GATT_SUCCESS,
|
||||
offset,
|
||||
value.copyOfRange(offset, value.size),
|
||||
)
|
||||
}
|
||||
|
||||
override fun onCharacteristicWriteRequest(
|
||||
device: BluetoothDevice,
|
||||
requestId: Int,
|
||||
characteristic: BluetoothGattCharacteristic,
|
||||
preparedWrite: Boolean,
|
||||
responseNeeded: Boolean,
|
||||
offset: Int,
|
||||
value: ByteArray,
|
||||
) {
|
||||
@Suppress("DEPRECATION")
|
||||
characteristic.value = value
|
||||
if (responseNeeded) {
|
||||
peripheralGattServer?.sendResponse(
|
||||
device,
|
||||
requestId,
|
||||
BluetoothGatt.GATT_SUCCESS,
|
||||
offset,
|
||||
null,
|
||||
)
|
||||
}
|
||||
callbackPeripheralWrite(
|
||||
device.address,
|
||||
characteristic.service.uuid.toString(),
|
||||
characteristic.uuid.toString(),
|
||||
value,
|
||||
)
|
||||
}
|
||||
|
||||
override fun onDescriptorReadRequest(
|
||||
device: BluetoothDevice,
|
||||
requestId: Int,
|
||||
offset: Int,
|
||||
descriptor: BluetoothGattDescriptor,
|
||||
) {
|
||||
@Suppress("DEPRECATION")
|
||||
val value = descriptor.value ?: ByteArray(0)
|
||||
if (offset > value.size) {
|
||||
peripheralGattServer?.sendResponse(
|
||||
device,
|
||||
requestId,
|
||||
BluetoothGatt.GATT_INVALID_OFFSET,
|
||||
offset,
|
||||
null,
|
||||
)
|
||||
return
|
||||
}
|
||||
peripheralGattServer?.sendResponse(
|
||||
device,
|
||||
requestId,
|
||||
BluetoothGatt.GATT_SUCCESS,
|
||||
offset,
|
||||
value.copyOfRange(offset, value.size),
|
||||
)
|
||||
}
|
||||
|
||||
override fun onDescriptorWriteRequest(
|
||||
device: BluetoothDevice,
|
||||
requestId: Int,
|
||||
descriptor: BluetoothGattDescriptor,
|
||||
preparedWrite: Boolean,
|
||||
responseNeeded: Boolean,
|
||||
offset: Int,
|
||||
value: ByteArray,
|
||||
) {
|
||||
@Suppress("DEPRECATION")
|
||||
descriptor.value = value
|
||||
if (responseNeeded) {
|
||||
peripheralGattServer?.sendResponse(
|
||||
device,
|
||||
requestId,
|
||||
BluetoothGatt.GATT_SUCCESS,
|
||||
offset,
|
||||
null,
|
||||
)
|
||||
}
|
||||
if (descriptor.uuid == ccdCharacteristic) {
|
||||
val subscribed = value.contentEquals(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE) ||
|
||||
value.contentEquals(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE)
|
||||
callbackPeripheralSubscription(
|
||||
device.address,
|
||||
descriptor.characteristic.service.uuid.toString(),
|
||||
descriptor.characteristic.uuid.toString(),
|
||||
subscribed,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onConnectionStateChange(
|
||||
gatt: BluetoothGatt,
|
||||
|
||||
Reference in New Issue
Block a user