From 06ed747e15c2b78e5da5f8f1a1416ebf48a8eaa2 Mon Sep 17 00:00:00 2001 From: Martijn van Welie Date: Sat, 28 Oct 2023 08:59:42 +0200 Subject: [PATCH] Update to the latest callbacks --- app/build.gradle | 6 +- blessed/build.gradle | 18 ++-- .../com/welie/blessed/BluetoothPeripheral.kt | 88 +++++++++++++++---- build.gradle | 55 ++++++------ gradle.properties | 2 +- settings.gradle | 15 ++++ 6 files changed, 131 insertions(+), 53 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 54550fd..449436c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,5 +1,7 @@ -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' +plugins { + id 'com.android.application' + id 'org.jetbrains.kotlin.android' +} android { namespace 'com.welie.blessedexample' diff --git a/blessed/build.gradle b/blessed/build.gradle index a8aae7e..88219a0 100644 --- a/blessed/build.gradle +++ b/blessed/build.gradle @@ -1,11 +1,11 @@ -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' -apply plugin: 'maven-publish' +plugins { + id 'com.android.library' + id 'maven-publish' + id 'org.jetbrains.kotlin.android' +} android { - namespace 'com.welie.blessed' - compileSdk 34 defaultConfig { @@ -23,12 +23,12 @@ android { } kotlinOptions { - jvmTarget = "17" + jvmTarget = "1.8" } compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 } } @@ -39,7 +39,7 @@ dependencies { implementation 'com.jakewharton.timber:timber:5.0.1' testImplementation 'junit:junit:4.13.2' - testImplementation "org.robolectric:robolectric:4.5.1" + testImplementation "org.robolectric:robolectric:4.10.3" testImplementation "org.mockito:mockito-core:3.8.0" testImplementation 'androidx.test:core:1.5.0' testImplementation "io.mockk:mockk:1.13.8" diff --git a/blessed/src/main/java/com/welie/blessed/BluetoothPeripheral.kt b/blessed/src/main/java/com/welie/blessed/BluetoothPeripheral.kt index 08d7ab9..d6a2c6f 100644 --- a/blessed/src/main/java/com/welie/blessed/BluetoothPeripheral.kt +++ b/blessed/src/main/java/com/welie/blessed/BluetoothPeripheral.kt @@ -168,35 +168,67 @@ class BluetoothPeripheral internal constructor( completedCommand() } - override fun onDescriptorRead(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int) { + override fun onDescriptorRead( + gatt: BluetoothGatt, + descriptor: BluetoothGattDescriptor, + status: Int, + value: ByteArray + ) { val gattStatus = GattStatus.fromValue(status) if (gattStatus != GattStatus.SUCCESS) { Logger.e(TAG, "reading descriptor <%s> failed for device '%s, status '%s'", descriptor.uuid, address, gattStatus) } - val value = nonnullOf(descriptor.value) val resultCallback = currentResultCallback callbackScope.launch { resultCallback.onDescriptorRead(this@BluetoothPeripheral, value, descriptor, gattStatus) } completedCommand() } - override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) { - val value = nonnullOf(characteristic.value) + @Deprecated("Deprecated in Java") + override fun onDescriptorRead(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int) { + if (Build.VERSION.SDK_INT < 33) { + onDescriptorRead(gatt, descriptor, status, nonnullOf(descriptor.value)) + } + } + + override fun onCharacteristicChanged( + gatt: BluetoothGatt, + characteristic: BluetoothGattCharacteristic, + value: ByteArray + ) { callbackScope.launch { observeMap[characteristic]?.invoke(value) } } - override fun onCharacteristicRead(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) { + @Deprecated("Deprecated in Java") + override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) { + if (Build.VERSION.SDK_INT < 33) { + onCharacteristicChanged(gatt, characteristic, nonnullOf(characteristic.value)) + } + } + + override fun onCharacteristicRead( + gatt: BluetoothGatt, + characteristic: BluetoothGattCharacteristic, + value: ByteArray, + status: Int + ) { val gattStatus = GattStatus.fromValue(status) if (gattStatus != GattStatus.SUCCESS) { Logger.e(TAG, "read failed for characteristic <%s>, status '%s'", characteristic.uuid, gattStatus) } - val value = nonnullOf(characteristic.value) val resultCallback = currentResultCallback callbackScope.launch { resultCallback.onCharacteristicRead(this@BluetoothPeripheral, value, characteristic, gattStatus) } completedCommand() } + @Deprecated("Deprecated in Java") + override fun onCharacteristicRead(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) { + if (Build.VERSION.SDK_INT < 33) { + onCharacteristicRead(gatt, characteristic, nonnullOf(characteristic.value), status) + } + } + override fun onCharacteristicWrite(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) { val gattStatus = GattStatus.fromValue(status) if (gattStatus != GattStatus.SUCCESS) { @@ -922,9 +954,9 @@ class BluetoothPeripheral internal constructor( // See https://stackoverflow.com/questions/48216517/rxandroidble-write-only-sends-the-first-20b Logger.w(TAG, "value byte array is longer than allowed by MTU, write will fail if peripheral does not support long writes") } - characteristic.value = bytesToWrite - if (bluetoothGatt?.writeCharacteristic(characteristic) == true) { - Logger.d(TAG, "writing <%s> to characteristic <%s>", BluetoothBytesParser.bytes2String(bytesToWrite), characteristic.uuid) + + if (internalWriteCharacteristic(characteristic, bytesToWrite, writeType)) { + Logger.d(TAG, "writing <%s> to characteristic <%s>", bytesToWrite.asHexString(), characteristic.uuid) nrTries++ } else { Logger.e(TAG, "writeCharacteristic failed for characteristic: %s", characteristic.uuid) @@ -942,6 +974,24 @@ class BluetoothPeripheral internal constructor( return value.size > currentMtu - 3 && writeType == WriteType.WITH_RESPONSE } + private fun internalWriteCharacteristic( + characteristic: BluetoothGattCharacteristic, + value: ByteArray, + writeType: WriteType + ): Boolean { + if (bluetoothGatt == null) return false + + currentWriteBytes = value + return if (Build.VERSION.SDK_INT >= 33) { + val result = bluetoothGatt?.writeCharacteristic(characteristic, currentWriteBytes, writeType.writeType) + result == BluetoothStatusCodes.SUCCESS + } else { + characteristic.writeType = writeType.writeType + characteristic.value = value + bluetoothGatt!!.writeCharacteristic(characteristic) + } + } + suspend fun readDescriptor(descriptor: BluetoothGattDescriptor): ByteArray = suspendCoroutine { try { @@ -1033,10 +1083,8 @@ class BluetoothPeripheral internal constructor( return enqueue { if (isConnected) { currentResultCallback = resultCallback - currentWriteBytes = bytesToWrite - descriptor.value = bytesToWrite - if (bluetoothGatt?.writeDescriptor(descriptor) == true) { - Logger.d(TAG, "writing <%s> to descriptor <%s>", BluetoothBytesParser.bytes2String(bytesToWrite), descriptor.uuid) + if (internalWriteDescriptor(descriptor, bytesToWrite)) { + Logger.d(TAG, "writing <%s> to descriptor <%s>", bytesToWrite.asHexString(), descriptor.uuid) nrTries++ } else { Logger.e(TAG, "writeDescriptor failed for descriptor: %s", descriptor.uuid) @@ -1050,6 +1098,17 @@ class BluetoothPeripheral internal constructor( } } + private fun internalWriteDescriptor(descriptor: BluetoothGattDescriptor, value: ByteArray): Boolean { + if (bluetoothGatt == null) return false + currentWriteBytes = value + return if (Build.VERSION.SDK_INT >= 33) { + val result = bluetoothGatt?.writeDescriptor(descriptor, value) + result == BluetoothStatusCodes.SUCCESS + } else { + descriptor.value = value + bluetoothGatt!!.writeDescriptor(descriptor) + } + } suspend fun observe(characteristic: BluetoothGattCharacteristic, callback: (value: ByteArray) -> Unit): Boolean = suspendCoroutine { @@ -1156,8 +1215,7 @@ class BluetoothPeripheral internal constructor( completedCommand() } else { currentWriteBytes = finalValue - descriptor.value = finalValue - if (bluetoothGatt?.writeDescriptor(descriptor) == true) { + if (internalWriteDescriptor(descriptor, finalValue)) { nrTries++ } else { Logger.e(TAG, "writeDescriptor failed for descriptor: %s", descriptor.uuid) diff --git a/build.gradle b/build.gradle index 273a7d1..9559910 100644 --- a/build.gradle +++ b/build.gradle @@ -1,29 +1,32 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - ext.kotlin_version = '1.9.10' - repositories { - google() - mavenCentral() - } - - dependencies { - classpath 'com.android.tools.build:gradle:8.1.2' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } +plugins { + id 'com.android.application' version '8.1.2' apply false + id 'com.android.library' version '8.1.2' apply false + id 'org.jetbrains.kotlin.android' version '1.9.10' apply false } -allprojects { - repositories { - google() - mavenCentral() - maven { url 'https://jitpack.io' } - } -} - -task clean(type: Delete) { - delete rootProject.buildDir -} +//// Top-level build file where you can add configuration options common to all sub-projects/modules. +// +//buildscript { +// ext.kotlin_version = '1.9.10' +// repositories { +// google() +// mavenCentral() +// } +// +// dependencies { +// classpath 'com.android.tools.build:gradle:8.1.2' +// classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" +// +// // NOTE: Do not place your application dependencies here; they belong +// // in the individual module build.gradle files +// } +//} +// +//allprojects { +// repositories { +// google() +// mavenCentral() +// maven { url 'https://jitpack.io' } +// } +//} diff --git a/gradle.properties b/gradle.properties index d546dea..7da6579 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,5 +13,5 @@ org.gradle.jvmargs=-Xmx1536m # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true - +kotlin.code.style=official diff --git a/settings.gradle b/settings.gradle index 04a3c68..adeb22d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,16 @@ +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} + include ':app', ':blessed'