Skip to content

Commit 2e1b519

Browse files
authored
Merge pull request #3 from PureSwift/feature/swift-java-callbacks
Fix Android Central Callbacks
2 parents b393a31 + 80ded19 commit 2e1b519

4 files changed

Lines changed: 294 additions & 83 deletions

File tree

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
package org.pureswift.bluetooth
2+
3+
import android.bluetooth.BluetoothGatt
4+
import android.bluetooth.BluetoothGattCallback as AndroidGattCallback
5+
import android.bluetooth.BluetoothGattCharacteristic
6+
import android.bluetooth.BluetoothGattDescriptor
7+
import android.util.Log
8+
9+
/**
10+
* Bluetooth GATT Callback for AndroidBluetooth Swift package.
11+
*
12+
* This class is referenced by AndroidBluetooth's GattCallback
13+
* via the @JavaClass("org.pureswift.bluetooth.BluetoothGattCallback") annotation.
14+
* It extends Android's BluetoothGattCallback and provides the bridge between
15+
* Android's Bluetooth GATT and the Swift AndroidBluetooth package.
16+
*/
17+
open class BluetoothGattCallback(
18+
private var swiftPeer: Long = 0L
19+
) : AndroidGattCallback() {
20+
21+
fun setSwiftPeer(swiftPeer: Long) {
22+
this.swiftPeer = swiftPeer
23+
}
24+
25+
fun getSwiftPeer(): Long {
26+
return swiftPeer
27+
}
28+
29+
fun finalize() {
30+
swiftGattRelease(swiftPeer)
31+
swiftPeer = 0L
32+
}
33+
34+
private external fun swiftGattRelease(swiftPeer: Long)
35+
36+
companion object {
37+
private const val TAG = "PureSwift.GattCallback"
38+
}
39+
40+
override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
41+
super.onConnectionStateChange(gatt, status, newState)
42+
if (swiftPeer != 0L) {
43+
swiftOnConnectionStateChange(swiftPeer, gatt, status, newState)
44+
} else {
45+
Log.d(TAG, "onConnectionStateChange: status=$status newState=$newState")
46+
}
47+
}
48+
private external fun swiftOnConnectionStateChange(swiftPeer: Long, gatt: BluetoothGatt?, status: Int, newState: Int)
49+
50+
override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
51+
super.onServicesDiscovered(gatt, status)
52+
if (swiftPeer != 0L) {
53+
swiftOnServicesDiscovered(swiftPeer, gatt, status)
54+
} else {
55+
Log.d(TAG, "onServicesDiscovered: status=$status")
56+
}
57+
}
58+
private external fun swiftOnServicesDiscovered(swiftPeer: Long, gatt: BluetoothGatt?, status: Int)
59+
60+
@Deprecated("Deprecated in Java")
61+
override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
62+
@Suppress("DEPRECATION")
63+
super.onCharacteristicChanged(gatt, characteristic)
64+
if (swiftPeer != 0L) {
65+
swiftOnCharacteristicChanged(swiftPeer, gatt, characteristic)
66+
} else {
67+
Log.d(TAG, "onCharacteristicChanged: ${characteristic.uuid}")
68+
}
69+
}
70+
private external fun swiftOnCharacteristicChanged(swiftPeer: Long, gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?)
71+
72+
@Deprecated("Deprecated in Java")
73+
override fun onCharacteristicRead(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) {
74+
@Suppress("DEPRECATION")
75+
super.onCharacteristicRead(gatt, characteristic, status)
76+
if (swiftPeer != 0L) {
77+
swiftOnCharacteristicRead(swiftPeer, gatt, characteristic, status)
78+
} else {
79+
Log.d(TAG, "onCharacteristicRead: ${characteristic.uuid} status=$status")
80+
}
81+
}
82+
private external fun swiftOnCharacteristicRead(swiftPeer: Long, gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int)
83+
84+
override fun onCharacteristicWrite(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int) {
85+
super.onCharacteristicWrite(gatt, characteristic, status)
86+
if (swiftPeer != 0L) {
87+
swiftOnCharacteristicWrite(swiftPeer, gatt, characteristic, status)
88+
} else {
89+
Log.d(TAG, "onCharacteristicWrite: ${characteristic?.uuid} status=$status")
90+
}
91+
}
92+
private external fun swiftOnCharacteristicWrite(swiftPeer: Long, gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int)
93+
94+
@Deprecated("Deprecated in Java")
95+
override fun onDescriptorRead(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int) {
96+
@Suppress("DEPRECATION")
97+
super.onDescriptorRead(gatt, descriptor, status)
98+
if (swiftPeer != 0L) {
99+
swiftOnDescriptorRead(swiftPeer, gatt, descriptor, status)
100+
} else {
101+
Log.d(TAG, "onDescriptorRead: ${descriptor.uuid} status=$status")
102+
}
103+
}
104+
private external fun swiftOnDescriptorRead(swiftPeer: Long, gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int)
105+
106+
override fun onDescriptorWrite(gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int) {
107+
super.onDescriptorWrite(gatt, descriptor, status)
108+
if (swiftPeer != 0L) {
109+
swiftOnDescriptorWrite(swiftPeer, gatt, descriptor, status)
110+
} else {
111+
Log.d(TAG, "onDescriptorWrite: ${descriptor?.uuid} status=$status")
112+
}
113+
}
114+
private external fun swiftOnDescriptorWrite(swiftPeer: Long, gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int)
115+
116+
override fun onMtuChanged(gatt: BluetoothGatt?, mtu: Int, status: Int) {
117+
super.onMtuChanged(gatt, mtu, status)
118+
if (swiftPeer != 0L) {
119+
swiftOnMtuChanged(swiftPeer, gatt, mtu, status)
120+
} else {
121+
Log.d(TAG, "onMtuChanged: mtu=$mtu status=$status")
122+
}
123+
}
124+
private external fun swiftOnMtuChanged(swiftPeer: Long, gatt: BluetoothGatt?, mtu: Int, status: Int)
125+
126+
override fun onPhyRead(gatt: BluetoothGatt?, txPhy: Int, rxPhy: Int, status: Int) {
127+
super.onPhyRead(gatt, txPhy, rxPhy, status)
128+
if (swiftPeer != 0L) {
129+
swiftOnPhyRead(swiftPeer, gatt, txPhy, rxPhy, status)
130+
} else {
131+
Log.d(TAG, "onPhyRead: txPhy=$txPhy rxPhy=$rxPhy status=$status")
132+
}
133+
}
134+
private external fun swiftOnPhyRead(swiftPeer: Long, gatt: BluetoothGatt?, txPhy: Int, rxPhy: Int, status: Int)
135+
136+
override fun onPhyUpdate(gatt: BluetoothGatt?, txPhy: Int, rxPhy: Int, status: Int) {
137+
super.onPhyUpdate(gatt, txPhy, rxPhy, status)
138+
if (swiftPeer != 0L) {
139+
swiftOnPhyUpdate(swiftPeer, gatt, txPhy, rxPhy, status)
140+
} else {
141+
Log.d(TAG, "onPhyUpdate: txPhy=$txPhy rxPhy=$rxPhy status=$status")
142+
}
143+
}
144+
private external fun swiftOnPhyUpdate(swiftPeer: Long, gatt: BluetoothGatt?, txPhy: Int, rxPhy: Int, status: Int)
145+
146+
override fun onReadRemoteRssi(gatt: BluetoothGatt?, rssi: Int, status: Int) {
147+
super.onReadRemoteRssi(gatt, rssi, status)
148+
if (swiftPeer != 0L) {
149+
swiftOnReadRemoteRssi(swiftPeer, gatt, rssi, status)
150+
} else {
151+
Log.d(TAG, "onReadRemoteRssi: rssi=$rssi status=$status")
152+
}
153+
}
154+
private external fun swiftOnReadRemoteRssi(swiftPeer: Long, gatt: BluetoothGatt?, rssi: Int, status: Int)
155+
156+
override fun onReliableWriteCompleted(gatt: BluetoothGatt?, status: Int) {
157+
super.onReliableWriteCompleted(gatt, status)
158+
if (swiftPeer != 0L) {
159+
swiftOnReliableWriteCompleted(swiftPeer, gatt, status)
160+
} else {
161+
Log.d(TAG, "onReliableWriteCompleted: status=$status")
162+
}
163+
}
164+
private external fun swiftOnReliableWriteCompleted(swiftPeer: Long, gatt: BluetoothGatt?, status: Int)
165+
}

Demo/app/src/main/kotlin/org/pureswift/bluetooth/le/ScanCallback.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ open class ScanCallback(
2525
}
2626

2727
fun finalize() {
28-
swiftRelease(swiftPeer)
28+
swiftScanRelease(swiftPeer)
2929
swiftPeer = 0L
3030
}
3131

32-
private external fun swiftRelease(swiftPeer: Long)
32+
private external fun swiftScanRelease(swiftPeer: Long)
3333

3434
companion object {
3535
private const val TAG = "PureSwift.ScanCallback"

Sources/AndroidBluetooth/AndroidCentral.swift

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,14 @@ public final class AndroidCentral: CentralManager {
3737

3838
public var peripherals: [GATT.Peripheral : Bool] {
3939
get async {
40-
[:] // FIXME:
40+
await storage.update { state in
41+
var peripherals = [GATT.Peripheral: Bool]()
42+
peripherals.reserveCapacity(state.scan.peripherals.count)
43+
for peripheral in state.scan.peripherals.keys {
44+
peripherals[peripheral] = state.cache[peripheral] != nil
45+
}
46+
return peripherals
47+
}
4148
}
4249
}
4350

@@ -95,10 +102,6 @@ public final class AndroidCentral: CentralManager {
95102
guard let scanner = hostController.getBluetoothLeScanner()
96103
else { throw AndroidCentralError.bluetoothDisabled }
97104

98-
// check permission
99-
let permission = try Permission(rawValue: JavaClass<Manifest.Permission>().BLUETOOTH_SCAN)
100-
try checkPermission(permission)
101-
102105
return .init(onTermination: {
103106
Task {
104107
await self.stopScan()

0 commit comments

Comments
 (0)