Search code examples
androidkotlinbluetooth-lowenergyesp32arduino-esp32

BLE Scanner in Android doesn't find anything on Scan Results


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)
       }
   }


}  ```

Solution

  • 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.