I have been building an App, that should connect to an ESP32 Module with BLE support to send and receive UTF-8 Messages between both devices. Unfortunately though I am stuck at a certain point where I don't see my mistake and neither get any error messages to identify what the issue might be.
The Bluetooth Adapter of my Mobile Phone scans as usually and seems to work fine (though as ordered it only looks in low power mode which means only BLE devices appear and therefore none appear which is the problem)
The ESP32 Module is not the issue because it runs well with nRF Connect but my App just doesn't find it.
Here is a look into my Bluetooth Class I have built (I am sorry I am a newbie in Android Development you might take a shit on my code but I just need a resolution of my issue):
lateinit var context: Context
var bluetoothManager: BluetoothManager
var bluetoothAdapter: BluetoothAdapter
var bluetoothLeScanner: BluetoothLeScanner
private var SERVICE_UUID: UUID = UUID.fromString("4fafc201-1fb5-459e-8fcc-c5c9c331914b")
private var serviceUUIDs = arrayOf(SERVICE_UUID)
var myDevices = HashMap<Int, BluetoothDevice>()
var deviceCounter = 0
var scanning = false
var handler = Handler()
val TAGe: String = "JOST_TAG_ERROR:: "
val TAGs: String = "JOST_TAG_SUCCESS:: "
lateinit var scanFilters: List<ScanFilter>
val scanSettings: ScanSettings = ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
.setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE)
.setNumOfMatches(ScanSettings.MATCH_NUM_MAX_ADVERTISEMENT)
.setReportDelay(0)
.build()
@RequiresApi(Build.VERSION_CODES.S)
constructor(transmitted_context: Context){
this.context = transmitted_context
bluetoothManager = transmitted_context.getSystemService(BluetoothManager::class.java)
bluetoothAdapter = bluetoothManager.adapter
bluetoothLeScanner = bluetoothAdapter.bluetoothLeScanner
if(serviceUUIDs != null){
scanFilters = ArrayList<ScanFilter>()
for(service: UUID in serviceUUIDs) {
val filter = ScanFilter.Builder()
.setServiceUuid(ParcelUuid(SERVICE_UUID))
.build()
(scanFilters as ArrayList<ScanFilter>).add(filter)
}
}
this.lookingfordevices()
this.scanLeDevice()
}
var scanCallback: ScanCallback = object : ScanCallback() {
@RequiresApi(Build.VERSION_CODES.S)
override fun onScanResult(callbackType: Int, result: ScanResult) {
Toast.makeText(context, "Starting onScanResult", Toast.LENGTH_LONG).show()
var bluetoothGatt: BluetoothGatt? = null
var device: BluetoothDevice = result.device as BluetoothDevice
Toast.makeText(context, ""+result.device.uuids.toString(), Toast.LENGTH_LONG).show()
myDevices[deviceCounter] = device
deviceCounter++
if (ActivityCompat.checkSelfPermission(
context,
Manifest.permission.BLUETOOTH_CONNECT
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(context as Activity, arrayOf(Manifest.permission.BLUETOOTH_CONNECT), 1)
}
if ((result != null) && result.device.uuids.contentEquals(serviceUUIDs)) {
Toast.makeText(context, "Scanresult isn't null and device UUID fits", Toast.LENGTH_LONG).show()
bluetoothGatt = result.device.connectGatt(context, false, bluetoothGattCallback,
BluetoothDevice.TRANSPORT_LE
)
Toast.makeText(context, "Connecting ot Gatt: "+bluetoothGatt.device.address,
Toast.LENGTH_LONG).show()
} else {
Log.e(TAGe, "THERE ARE NO DEVICES FOUND FROM YOUR SCAN RESULT")
Toast.makeText(context, "There are no devices found!", Toast.LENGTH_LONG).show()
}
}
override fun onScanFailed(errorCode: Int) {
super.onScanFailed(errorCode)
Toast.makeText(context, "onScan Failed!", Toast.LENGTH_LONG).show()
}
}
private val bluetoothGattCallback = object: BluetoothGattCallback() {
@RequiresApi(Build.VERSION_CODES.S)
override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
if(ActivityCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(context as Activity, arrayOf(Manifest.permission.BLUETOOTH_CONNECT),1)
}
if(status == BluetoothGatt.GATT_SUCCESS){
Toast.makeText(context, "GATT_SUCCESS", Toast.LENGTH_LONG).show()
if(newState == BluetoothProfile.STATE_CONNECTED){
Toast.makeText(context, "GATT FINALLY CONNECTED", Toast.LENGTH_LONG).show()
var bondstate = gatt?.device?.bondState
if(bondstate == BluetoothDevice.BOND_NONE || bondstate == BluetoothDevice.BOND_BONDED){
gatt?.discoverServices()
} else if (bondstate == BluetoothDevice.BOND_BONDING){
Toast.makeText(context, "Waiting Bonding to complete", Toast.LENGTH_LONG).show()
}
} else if (newState == BluetoothProfile.STATE_DISCONNECTED){
gatt?.close()
} else {
//TODO
}
} else {
Toast.makeText(context, "NO SUCCES IN GATT", Toast.LENGTH_LONG).show()
gatt?.close()
}
}
}
private val SCAN_PERIOD: Long = 10000
//stops scanning after 10 seconds
fun scanLeDevice(){
Toast.makeText(context, "Scanning Devices", Toast.LENGTH_LONG).show()
if(bluetoothAdapter.isEnabled){
Toast.makeText(context, "b_adapter_enabled", Toast.LENGTH_LONG).show()
if(!scanning){
Toast.makeText(context, "Scanning was false", Toast.LENGTH_LONG).show()
handler.postDelayed({
scanning = false
if (ActivityCompat.checkSelfPermission(
context,
Manifest.permission.BLUETOOTH_SCAN
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
context as Activity,
arrayOf(Manifest.permission.BLUETOOTH_SCAN), 1
)
}
bluetoothLeScanner.stopScan(scanCallback)
}, SCAN_PERIOD)
scanning = true
Toast.makeText(context, "Starting Scan therefore", Toast.LENGTH_LONG).show()
bluetoothLeScanner.startScan(scanFilters,scanSettings,scanCallback)
} else {
Toast.makeText(context, "Scanned", Toast.LENGTH_LONG).show()
scanning = false
bluetoothLeScanner.stopScan(scanCallback)
}
}
}
fun lookingfordevices(){
CoroutineScope(Dispatchers.IO).launch {
handler.postDelayed({
Log.d(TAGs, myDevices.size.toString())
scanLeDevice()
lookingfordevices()
},15000)
}
}
@RequiresApi(Build.VERSION_CODES.S)
fun checkinitialpermissionstate(){
if(!PermissionCheck().requestPermissionState(context)){
PermissionCheck().requestPermissions(context)
}
}
} ```
Final and obvious answer was: An BLE ESP32 Module does obviously not advertise UUID Data of its services for characteristics. Therefore hence it was more senseful to scan and connect to a device here by the MAC Address rather than the UUID information. The UUID information is still useful to have though because later on when addressing an ESP32 Module you might want to communicate with it via UTF-8 or other standards. The characteristics retrieved by such a device can be used to do exactly that.