I am attempting to connect my phone to a bluetooth device. I am using an android 13 . In my scandevices file, I am coming across an issue on this line bluetoothLeScaner.startScan(scanCallback). I am getting that IllegalArgumentException: callback is null.
Menifest.xml
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
build.gradle:
android {
namespace 'com.example.sensor'
compileSdk 34
kotlinOptions {
jvmTarget = '17'
}
defaultConfig {
applicationId "com.example.sensor"
minSdk 31
targetSdk 33 //33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary true
}
}
stack trace
2024-03-12 13:36:00.288 25335-25335 PERMISSIONS com.example.sensor D Permission already granted: android.permission.BLUETOOTH
2024-03-12 13:36:00.289 25335-25335 PERMISSIONS com.example.sensor D Permission already granted: android.permission.BLUETOOTH_CONNECT
2024-03-12 13:36:00.290 25335-25335 PERMISSIONS com.example.sensor D Permission already granted: android.permission.ACCESS_COARSE_LOCATION
2024-03-12 13:36:00.290 25335-25335 PERMISSIONS com.example.sensor D Permission already granted: android.permission.ACCESS_FINE_LOCATION
2024-03-12 13:36:00.292 25335-25335 PERMISSIONS com.example.sensor D Permission already granted: android.permission.BLUETOOTH_ADMIN
2024-03-12 13:36:00.293 25335-25335 PERMISSIONS com.example.sensor D Permission already granted: android.permission.BLUETOOTH_SCAN
2024-03-12 13:36:00.294 25335-25335 PERMISSIONS com.example.sensor D Permission already granted: android.permission.BLUETOOTH_ADVERTISE
2024-03-12 13:36:00.294 25335-25335 PERMISSIONS com.example.sensor D All permissions are already granted
2024-03-12 13:36:00.299 25335-25335 BluetoothAdapter com.example.sensor I STATE_ON
2024-03-12 13:36:00.300 25335-25335 AndroidRuntime com.example.sensor D Shutting down VM
2024-03-12 13:36:00.304 25335-25335 AndroidRuntime com.example.sensor E FATAL EXCEPTION: main
Process: com.example.sensor, PID: 25335
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.sensor/com.example.sensor.MainActivity}: java.lang.IllegalArgumentException: callback is null
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4169)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4325)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2574)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8779)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:604)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
Caused by: java.lang.IllegalArgumentException: callback is null
at android.bluetooth.le.BluetoothLeScanner.startScan(BluetoothLeScanner.java:136)
at com.example.sensor.data.ble.ScanDevices.run(ScanDevices.kt:40)
at com.example.sensor.data.ble.ScanDevices.<init>(ScanDevices.kt:35)
at com.example.sensor.MainActivity.onCreate(MainActivity.kt:62)
at android.app.Activity.performCreate(Activity.java:8591)
at android.app.Activity.performCreate(Activity.java:8570)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1384)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4150)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4325)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2574)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8779)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:604)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
2024-03-12 13:36:00.334 25335-25335 Process com.example.sensor I Sending signal. PID: 25335 SIG: 9
scandevice.kt
@SuppressLint("MissingPermission")
class ScanDevices(
var bluetoothAdapter: BluetoothAdapter,
val context: Context
):Thread() {
val DEVICE_NAME = "WHEELSERV"
private var isScanning = false
private var bluetoothLeScaner = bluetoothAdapter.bluetoothLeScanner
private var device: BluetoothDevice? = null
private val latch = CountDownLatch(1);
init {
run()
}
override fun run() {
bluetoothLeScaner.startScan(scanCallback)
isScanning = true
latch.await()
val socket = device?.createL2capChannel(0)
try {
socket?.connect()
Log.d("CREATION", "yay connected ")
} catch (e: IOException) {
println("didnt connect to device")
}
}
val scanCallback = object : ScanCallback() {
override fun onScanResult(
callbackType: Int,
result: ScanResult
) {
super.onScanResult(callbackType, result)
if (result.device.name == DEVICE_NAME) {//filter
if (isScanning) {
isScanning = false
//bluetoothLeScaner.stopScan(scanCallback)
bluetoothAdapter.cancelDiscovery()
device = result.device
latch.countDown()
}
}
}
}
}
When debugging the code, I can see that bluetoothLeScanner is non-null. So then, I thought maybe it is an issue with permissions, so I tested it out in my MainActivity.kt. As you can see on the stack-trace and xml file, all permissions are setup, requested, and granted. I ran out of ideas on what the issue might be and would appreciate some advice on what I should test next.
In kotlin,
initblocks and property initializers are executed in the order in which they appear.We can illustrate this with the following simple example:
Which is equivalent to the following Java code:
As you can see, the callback is initialized after the call to
run. So it's entirely possible to end up with anullcallback whenstartScanis called in your case.If you changed the code around like so:
you'd instead get this:
which should work.
Although I'm not entirely sure why you see the need to spawn a new thread for the scanner(?). That seems unnecessary to me.