In my app, I would like to know if a user enables/disables Bluetooth using the status bar and display a relevant piece of UI. For that, I think that I need to keep track of the current BluetoothAdapter.isEnabled
status in my @Composable
functions. This is what I have:
class MainActivity : ComponentActivity() {
private val bluetoothAdapter: BluetoothAdapter by lazy {
val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
bluetoothManager.adapter
}
override fun onCreate(savedInstanceState: Bundle?) {
var isBluetoothEnabled = bluetoothAdapter.isEnabled
setContent {
AppTheme {
MainScreen(isBluetoothEnabled)
}
}
}
}
@Composable
private fun MainScreen(
isBluetoothEnabled: Boolean
) {
if (isBluetoothEnabled) {
// Display some UI
} else {
// Display different UI
}
}
When the app is launched, I can get the correct status of Bluetooth for the app, but since BluetoothAdapter.isEnabled
is not part of the @Composable
lifecycle, I'm not able to track it afterwards and react to changes like it's a piece of reactive state. Is there any way to achieve the behavior that I want here?
I was able to solve this just by using mutableStateOf
. It doesn't have to be initialized inside of a @Composable
function to be reactive, which is what I misunderstood in the first place.
mutableStateOf
value and a BroadcastReceiver
that will track the state of BluetoothAdapter
. When Bluetooth state changes, update the value. private var isBluetoothEnabled = mutableStateOf(false)
private val mReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (intent?.action == BluetoothAdapter.ACTION_STATE_CHANGED) {
when (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)) {
BluetoothAdapter.STATE_OFF -> {
isBluetoothEnabled.value = false
Log.i("Bluetooth", "State OFF")
}
BluetoothAdapter.STATE_ON -> {
isBluetoothEnabled.value = true
Log.i("Bluetooth", "State ON")
}
}
}
}
}
@Composable
function, use this value as usual:@Composable
private fun MainScreen(
isBluetoothEnabled: MutableState<Boolean>
) {
if (isBluetoothEnabled) {
// Display some UI
} else {
// Display different UI
}
}
And that's it!