diff --git a/app/src/main/java/com/geeksville/mesh/MainActivity.kt b/app/src/main/java/com/geeksville/mesh/MainActivity.kt index d9c79159..0d52760f 100644 --- a/app/src/main/java/com/geeksville/mesh/MainActivity.kt +++ b/app/src/main/java/com/geeksville/mesh/MainActivity.kt @@ -32,7 +32,6 @@ import androidx.viewpager2.adapter.FragmentStateAdapter import com.geeksville.mesh.android.* import com.geeksville.mesh.concurrent.handledLaunch import com.geeksville.mesh.databinding.ActivityMainBinding -import com.geeksville.mesh.model.BTScanModel import com.geeksville.mesh.model.BluetoothViewModel import com.geeksville.mesh.model.ChannelSet import com.geeksville.mesh.model.DeviceVersion @@ -113,8 +112,7 @@ class MainActivity : AppCompatActivity(), Logging { private val mainScope = CoroutineScope(Dispatchers.Main + Job()) private val bluetoothViewModel: BluetoothViewModel by viewModels() - private val scanModel: BTScanModel by viewModels() - val model: UIViewModel by viewModels() + private val model: UIViewModel by viewModels() private val requestPermissionsLauncher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions -> @@ -629,7 +627,6 @@ class MainActivity : AppCompatActivity(), Logging { unregisterMeshReceiver() // No point in receiving updates while the GUI is gone, we'll get them when the user launches the activity unbindMeshService() - scanModel.changeDeviceAddress.removeObservers(this) model.connectionState.removeObservers(this) bluetoothViewModel.enabled.removeObservers(this) model.requestChannelUrl.removeObservers(this) @@ -640,20 +637,6 @@ class MainActivity : AppCompatActivity(), Logging { override fun onStart() { super.onStart() - scanModel.changeDeviceAddress.observe(this) { newAddr -> - newAddr?.let { - try { - model.meshService?.let { service -> - MeshService.changeDeviceAddress(this, service, newAddr) - } - scanModel.changeSelectedAddress(newAddr) // if it throws the change will be discarded - } catch (ex: RemoteException) { - errormsg("changeDeviceSelection failed, probably it is shutting down $ex.message") - // ignore the failure and the GUI won't be updating anyways - } - } - } - model.connectionState.observe(this) { connected -> updateConnectionStatusImage(connected) } diff --git a/app/src/main/java/com/geeksville/mesh/model/BTScanModel.kt b/app/src/main/java/com/geeksville/mesh/model/BTScanModel.kt index aca6d763..5c0208c8 100644 --- a/app/src/main/java/com/geeksville/mesh/model/BTScanModel.kt +++ b/app/src/main/java/com/geeksville/mesh/model/BTScanModel.kt @@ -108,7 +108,7 @@ class BTScanModel @Inject constructor( private var scanner: BluetoothLeScanner? = null - val selectedBluetooth: Boolean get() = selectedAddress?.get(0) == 'x' + val selectedBluetooth: Boolean get() = selectedAddress?.getOrNull(0) == 'x' /// Use the string for the NopInterface val selectedNotNull: String get() = selectedAddress ?: "n" @@ -141,9 +141,6 @@ class BTScanModel @Inject constructor( fullAddr, isBonded ) - // If nothing was selected, by default select the first valid thing we see - if (selectedAddress == null && entry.bonded) - changeDeviceAddress(fullAddr) addDevice(entry) // Add/replace entry } } @@ -195,11 +192,6 @@ class BTScanModel @Inject constructor( ) devices.value = (testnodes.map { it.fullAddress to it }).toMap().toMutableMap() - - // If nothing was selected, by default select the first thing we see - if (selectedAddress == null) - changeDeviceAddress(testnodes.first().fullAddress) - true } else { if (scanner == null) { @@ -344,20 +336,10 @@ class BTScanModel @Inject constructor( ) } - private val _changeDeviceAddress = MutableLiveData(null) - val changeDeviceAddress: LiveData get() = _changeDeviceAddress - - /// Change to a new macaddr selection, updating GUI and radio - fun changeDeviceAddress(newAddr: String) { - info("Changing device to ${newAddr.anonymize}") - _changeDeviceAddress.value = newAddr - } - /** - * Called immediately after activity observes changeDeviceAddress + * Called immediately after activity calls MeshService.changeDeviceAddress */ fun changeSelectedAddress(newAddress: String) { - _changeDeviceAddress.value = null selectedAddress = newAddress devices.value = devices.value // Force a GUI update } diff --git a/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt index 07a70c99..3dacfcb4 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt @@ -13,6 +13,7 @@ import android.hardware.usb.UsbManager import android.os.Bundle import android.os.Handler import android.os.Looper +import android.os.RemoteException import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -286,10 +287,13 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { binding.usernameEditText.setText(name) } + scanModel.devices.observe(viewLifecycleOwner) { devices -> + updateDevicesButtons(devices) + } + // Only let user edit their name or set software update while connected to a radio model.connectionState.observe(viewLifecycleOwner) { updateNodeInfo() - updateDevicesButtons(scanModel.devices.value) } model.localConfig.asLiveData().observe(viewLifecycleOwner) { @@ -323,10 +327,6 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { updateNodeInfo() } - scanModel.devices.observe(viewLifecycleOwner) { devices -> - updateDevicesButtons(devices) - } - scanModel.errorText.observe(viewLifecycleOwner) { errMsg -> if (errMsg != null) { binding.scanStatusText.text = errMsg @@ -510,12 +510,24 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { } } + private fun changeDeviceAddress(address: String) { + try { + model.meshService?.let { service -> + MeshService.changeDeviceAddress(requireActivity(), service, address) + } + scanModel.changeSelectedAddress(address) // if it throws the change will be discarded + } catch (ex: RemoteException) { + errormsg("changeDeviceSelection failed, probably it is shutting down $ex.message") + // ignore the failure and the GUI won't be updating anyways + } + } + /// Called by the GUI when a new device has been selected by the user /// Returns true if we were able to change to that item private fun onSelected(it: BTScanModel.DeviceListEntry): Boolean { // If the device is paired, let user select it, otherwise start the pairing flow if (it.bonded) { - scanModel.changeDeviceAddress(it.fullAddress) + changeDeviceAddress(it.fullAddress) return true } else { // Handle requesting USB or bluetooth permissions for the device @@ -529,7 +541,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { requestBonding(device) { state -> if (state == BluetoothDevice.BOND_BONDED) { scanModel.setErrorText(getString(R.string.pairing_completed)) - scanModel.changeDeviceAddress(it.fullAddress) + changeDeviceAddress(it.fullAddress) } else { scanModel.setErrorText(getString(R.string.pairing_failed_try_again)) } @@ -555,7 +567,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { ) ) { info("User approved USB access") - scanModel.changeDeviceAddress(it.fullAddress) + changeDeviceAddress(it.fullAddress) } else { errormsg("USB permission denied for device $device") }