I have a bluetooth headset which is paired with my Nexus 5X (running Android 7.1) and I would like to connect to a GATT Server of the headset. I tried it with the following
This may help
I will explain in two steps: connecting and discovering services
connecting: connect from mainthread
set auto-reconnect to false
if version greater than or equals to M, set Transport type
else directly use reflection and handle it properly
Handler(applicationContext.mainLooper).post {
Log.d(TAG, " Post is called inside mainlooper")
mBluetoothGatt = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Log.d(TAG, " Is Or Greater than M $mBluetoothDevice")
mBluetoothDevice!!.connectGatt(this, false,
onGhattListener, TRANSPORT_LE)
} else {
Log.d(TAG, " Less than M")
try {
Log.d(TAG, " Trying TRANPORT LE with reflection")
val m = mBluetoothDevice!!.javaClass.getDeclaredMethod("connectGatt", Context::class.java, Boolean::class.javaPrimitiveType, BluetoothGattCallback::class.java, Int::class.javaPrimitiveType)
m.isAccessible = true
val transport = mBluetoothDevice!!.javaClass.getDeclaredField("TRANSPORT_LE").getInt(null)
m.invoke(mBluetoothDevice, this, false, onGhattListener, transport) as BluetoothGatt
} catch (e: Exception) {
e.printStackTrace()
Log.d(TAG, " Catch to call normal connection")
mBluetoothDevice!!.connectGatt(this, false,
onGhattListener)
}
}
Log.d(TAG, "mBluetooth gatt is $mBluetoothGatt")
mBluetoothGatt?.let {
refreshDeviceCache(mBluetoothGatt!!)
}
}
discover services : in onGhattListener , if device is connected fire discoverServices() from main thread
override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int,
newState: Int) {
Log.d(TAG, "onConnectionStateChange $gatt and status $status and newstate $newState")
when (newState) {
BluetoothGatt.STATE_CONNECTED -> {
Handler(Looper.getMainLooper()).post {
gatt.discoverServices()
}
}
BluetoothGatt.STATE_DISCONNECTED -> {
}
BluetoothGatt.STATE_CONNECTING -> {
}
BluetoothGatt.STATE_DISCONNECTING -> {
}
}
}
this may solve your problem
call refresh method with reflection
fun refreshDeviceCache(gatt: BluetoothGatt): Boolean {
try {
val localMethod = gatt.javaClass.getMethod("refresh")
if (localMethod != null) {
return localMethod.invoke(gatt) as Boolean
}
} catch (localException: Exception) {
Log.e(TAG, "An exception occured while refreshing device")
localException.printStackTrace()
}
return false
}