1. Are you ready for the Galaxy S20? Here is everything we know so far!

Bluetooth discovery issue - Jetpack Compose + Kotlin

Discussion in 'Android Development' started by Cody Molisee, Jul 28, 2021.

  1. Cody Molisee

    Cody Molisee Lurker
    Thread Starter

    Hey all. I am new to android development. I discovered compose and kotlin working with react and figured I would learn and get good at something new.
    I am trying to figure out how to use bluetooth. I followed the developer guides and have done a bunch of looking around but can't seem to solve the issue. My problem is that when I call
    Code (Text):
    1.  startDiscovery()
    I don't actually discover any devices.

    in manifest :
    Code (Text):
    1.  
    2. <uses-feature android:name="android.hardware.bluetooth" android:required="false"/>
    3.  
    4. <uses-permission android:name="android.permission.BLUETOOTH" />
    5. <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    6. <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    7.  
    8. <permission android:name="android.permission.BLUETOOTH"/>
    9. <permission android:name="android.permission.BLUETOOTH_ADMIN" />
    10. <permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    11.  
    My very unpolished code is here:
    Code (Text):
    1.  
    2. class MainActivity : ComponentActivity() {
    3.     private val PERMISSION_CODE = 1
    4.     private val bluetoothAdapter: BluetoothAdapter = getDefaultAdapter()
    5.  
    6.     private val activityResultLauncher = registerForActivityResult(
    7.         ActivityResultContracts.StartActivityForResult()) { result ->
    8.         if (result.resultCode == RESULT_OK) {
    9.             Log.i("bluetooth", "request permission result OK")
    10.         } else {
    11.             Log.i("bluetooth", "request permission result CANCELED/DENIED")
    12.         }
    13.     }
    14.  
    15.     private fun requestBluetoothPermission() {
    16.         val enableBluetoothIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
    17.         activityResultLauncher.launch(enableBluetoothIntent)
    18.     }
    19.  
    20.     var pairedDevices: Set<BluetoothDevice> = bluetoothAdapter.bondedDevices
    21.     var discoveredDevices: Set<BluetoothDevice> = emptySet()
    22.  
    23.     val receiver = object : BroadcastReceiver() {
    24.         override fun onReceive(context: Context?, intent: Intent) {
    25.             when (intent.action) {
    26.                 BluetoothDevice.ACTION_FOUND -> {
    27.                     val device: BluetoothDevice? = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
    28.                     if (device != null) {
    29.                         val updated = discoveredDevices.plus(device)
    30.                         discoveredDevices = updated
    31.                     }
    32.                     Log.i("bluetooth", "device found")
    33.                 }
    34.                 BluetoothAdapter.ACTION_DISCOVERY_STARTED -> {
    35.                     Log.i("bluetooth", "started discovery")
    36.                 }
    37.                 BluetoothAdapter.ACTION_DISCOVERY_FINISHED -> {
    38.                     Log.i("bluetooth", "finished discovery")
    39.                 }
    40.             }
    41.         }
    42.     }
    43.  
    44.     @RequiresApi(Build.VERSION_CODES.M)
    45.     fun scan(): Set<BluetoothDevice> {
    46.         if (bluetoothAdapter.isDiscovering) {
    47.             bluetoothAdapter.cancelDiscovery()
    48.             bluetoothAdapter.startDiscovery()
    49.         } else {
    50.             bluetoothAdapter.startDiscovery()
    51.         }
    52.  
    53.         Handler(Looper.getMainLooper()).postDelayed({
    54.             bluetoothAdapter.cancelDiscovery()
    55.         }, 10000L)
    56.         return discoveredDevices
    57.     }
    58.  
    59.     @RequiresApi(Build.VERSION_CODES.M)
    60.     override fun onCreate(savedInstanceState: Bundle?) {
    61.         super.onCreate(savedInstanceState)
    62.  
    63.         val foundFilter = IntentFilter(BluetoothDevice.ACTION_FOUND)
    64.         val startFilter = IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED)
    65.         val endFilter = IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)
    66.         registerReceiver(receiver, foundFilter)
    67.         registerReceiver(receiver, startFilter)
    68.         registerReceiver(receiver, endFilter)
    69.         Log.i("bluetooth", "filters registered")
    70.  
    71.         if (!bluetoothAdapter.isEnabled) {
    72.             requestBluetoothPermission()
    73.         }
    74.  
    75.         if (SDK_INT >= Build.VERSION_CODES.Q) {
    76.             if (ContextCompat.checkSelfPermission(
    77.                     baseContext,
    78.                     android.Manifest.permission.ACCESS_BACKGROUND_LOCATION
    79.                 ) != PackageManager.PERMISSION_GRANTED) {
    80.                 ActivityCompat.requestPermissions(
    81.                     this,
    82.                     arrayOf(android.Manifest.permission.ACCESS_BACKGROUND_LOCATION),
    83.                     PERMISSION_CODE
    84.                 )
    85.             }
    86.         }
    87.  
    88.         setContent {
    89.             var devices: Set<BluetoothDevice> by remember {
    90.                 mutableStateOf(emptySet())
    91.             }
    92.             MyappTheme {
    93.                 Surface(color = MaterialTheme.colors.background) {
    94.                     Column(
    95.                         Modifier.fillMaxHeight()
    96.                     ) {
    97.                         Button(onClick = {
    98.                             devices = scan()
    99.                         }) {
    100.                             Text(text = "Scan", style = MaterialTheme.typography.h3)
    101.                         }
    102.                         Text(text = "PAIRED DEVICES", style = MaterialTheme.typography.h4)
    103.                         Divider(color = Color.Black)
    104.                         pairedDevices.forEach { device ->
    105.                             Card {
    106.                                 Column {
    107.                                     Text(text = device.name)
    108.                                     Text(text = device.address)
    109.                                 }
    110.                             }
    111.                         }
    112.                         Text(text = "DISCOVERED DEVICES", style = MaterialTheme.typography.h4)
    113.                         Divider(color = Color.Black)
    114.                         devices.forEach { device ->
    115.                             Card {
    116.                                 Column {
    117.                                     Text(text = device.name)
    118.                                     Text(text = device.address)
    119.                                 }
    120.                             }
    121.                         }
    122.                     }
    123.                 }
    124.             }
    125.         }
    126.     }
    127.  
    128.     override fun onDestroy() {
    129.         super.onDestroy()
    130.         if (bluetoothAdapter.isDiscovering) bluetoothAdapter.cancelDiscovery()
    131.         unregisterReceiver(receiver)
    132.     }
    133. }
    134.  
    I think the issue might be something to do with the broadcast receiver. Looking at Logcat when I hit 'scan' I get 'discovery strarted' from 'BluetoothAdapter' but I never get any of the info logs from the broadcast receiver and my device list doesn't populate with anything. Any guidance or help is much appreciated.
     



    1. Download the Forums for Android™ app!


      Download

       
  2. Cody Molisee

    Cody Molisee Lurker
    Thread Starter

    UPDATE: I got it to actually respond and log via the broadcast receiver that it was discovering devices. My first thought after taking a break and returning with a clear head was that the Broadcast receiver was returning before it ever received anything. I also refactored my code a bit and discovered that permissions for bluetooth and location are not actually getting requested properly. I will refactor and clean stuff up to make testing/proving this more productive. There still might be a need to run the broadcast receiver asynchronously via coroutine but I will start with assumption that it is just permissions for now. I will update when I figure it out. Still open to any suggestions!
     
Loading...

Share This Page

Loading...