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 8a5e06ec..88d3b1ae 100644 --- a/app/src/main/java/com/geeksville/mesh/model/BTScanModel.kt +++ b/app/src/main/java/com/geeksville/mesh/model/BTScanModel.kt @@ -1,6 +1,7 @@ package com.geeksville.mesh.model import android.annotation.SuppressLint +import android.app.Activity import android.app.Application import android.bluetooth.BluetoothDevice import android.bluetooth.le.* @@ -91,10 +92,6 @@ class BTScanModel @Inject constructor( debug("BTScanModel cleared") } - val hasCompanionDeviceApi get() = application.hasCompanionDeviceApi() - val hasBluetoothPermission get() = application.hasBluetoothPermission() - private val usbManager get() = context.usbManager - var selectedAddress: String? = null val errorText = object : MutableLiveData(null) {} @@ -211,7 +208,7 @@ class BTScanModel @Inject constructor( val serialDevices by lazy { usbRepository.serialDevicesWithDrivers.value } serialDevices.forEach { (_, d) -> - addDevice(USBDeviceListEntry(usbManager, d)) + addDevice(USBDeviceListEntry(context.usbManager, d)) } } else { debug("scan already running") @@ -221,7 +218,7 @@ class BTScanModel @Inject constructor( } private var networkDiscovery: Job? = null - fun startScan() { + fun startScan(activity: Activity?) { _spinner.value = true // Start Network Service Discovery (find TCP devices) @@ -229,10 +226,7 @@ class BTScanModel @Inject constructor( .onEach { addDevice(TCPDeviceListEntry(it)) } .launchIn(viewModelScope) - if (hasBluetoothPermission) { - if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.S && hasCompanionDeviceApi) - startCompanionScan() else startClassicScan() - } + if (activity != null) startCompanionScan(activity) else startClassicScan() } @SuppressLint("MissingPermission") @@ -320,9 +314,9 @@ class BTScanModel @Inject constructor( } @SuppressLint("NewApi") - private fun startCompanionScan() { + private fun startCompanionScan(activity: Activity) { debug("starting companion scan") - context.companionDeviceManager?.associate( + activity.companionDeviceManager?.associate( associationRequest(), @SuppressLint("NewApi") object : CompanionDeviceManager.Callback() { diff --git a/app/src/main/java/com/geeksville/mesh/repository/bluetooth/BluetoothRepository.kt b/app/src/main/java/com/geeksville/mesh/repository/bluetooth/BluetoothRepository.kt index ad80a13e..a827e011 100644 --- a/app/src/main/java/com/geeksville/mesh/repository/bluetooth/BluetoothRepository.kt +++ b/app/src/main/java/com/geeksville/mesh/repository/bluetooth/BluetoothRepository.kt @@ -61,7 +61,9 @@ class BluetoothRepository @Inject constructor( } fun getBluetoothLeScanner(): BluetoothLeScanner? { - return bluetoothAdapterLazy.get()?.bluetoothLeScanner + return bluetoothAdapterLazy.get() + ?.takeIf { application.hasBluetoothPermission() } + ?.bluetoothLeScanner } @SuppressLint("MissingPermission") 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 8ff6a2a3..d6e333a6 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt @@ -79,6 +79,11 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { private val myActivity get() = requireActivity() as MainActivity + private val hasCompanionDeviceApi by lazy { requireContext().hasCompanionDeviceApi() } + private val useCompanionDeviceApi by lazy { + android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.S && hasCompanionDeviceApi + } + private fun doFirmwareUpdate() { model.meshService?.let { service -> @@ -264,9 +269,9 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions -> if (permissions.entries.all { it.value }) { // Older versions of android only need Location permission - if (myActivity.hasBackgroundPermission()) { + if (requireContext().hasBackgroundPermission()) { binding.provideLocationCheckbox.isChecked = true - } else requestBackgroundAndCheckLauncher.launch(myActivity.getBackgroundPermissions()) + } else requestBackgroundAndCheckLauncher.launch(requireContext().getBackgroundPermissions()) } else { debug("User denied location permission") showSnackbar(getString(R.string.why_background_required)) @@ -375,7 +380,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { binding.provideLocationCheckbox.setOnCheckedChangeListener { view, isChecked -> // Don't check the box until the system setting changes - view.isChecked = isChecked && myActivity.hasBackgroundPermission() + view.isChecked = isChecked && requireContext().hasBackgroundPermission() if (view.isPressed) { // We want to ignore changes caused by code (as opposed to the user) debug("User changed location tracking to $isChecked") @@ -389,10 +394,10 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { } .setPositiveButton(getString(R.string.accept)) { _, _ -> // Make sure we have location permission (prerequisite) - if (!myActivity.hasLocationPermission()) { - requestLocationAndBackgroundLauncher.launch(myActivity.getLocationPermissions()) + if (!requireContext().hasLocationPermission()) { + requestLocationAndBackgroundLauncher.launch(requireContext().getLocationPermissions()) } else { - requestBackgroundAndCheckLauncher.launch(myActivity.getBackgroundPermissions()) + requestBackgroundAndCheckLauncher.launch(requireContext().getBackgroundPermissions()) } } .show() @@ -501,7 +506,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { scanModel.stopScan() }, SCAN_PERIOD) scanning = true - scanModel.startScan() + scanModel.startScan(requireActivity().takeIf { useCompanionDeviceApi }) } else { scanning = false scanModel.stopScan() @@ -628,7 +633,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions -> if (permissions.entries.all { it.value }) { checkBTEnabled() - if (!scanModel.hasCompanionDeviceApi) checkLocationEnabled() + if (!hasCompanionDeviceApi) checkLocationEnabled() scanLeDevice() } else { errormsg("User denied scan permissions") @@ -640,9 +645,9 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { binding.changeRadioButton.setOnClickListener { debug("User clicked changeRadioButton") scanLeDevice() - if (scanModel.hasBluetoothPermission) { + if (requireContext().hasBluetoothPermission()) { checkBTEnabled() - if (!scanModel.hasCompanionDeviceApi) checkLocationEnabled() + if (!hasCompanionDeviceApi) checkLocationEnabled() } else { MaterialAlertDialogBuilder(requireContext()) .setTitle(getString(R.string.required_permissions)) @@ -652,7 +657,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { } .setPositiveButton(R.string.accept) { _, _ -> info("requesting scan permissions") - requestPermissionAndScanLauncher.launch(myActivity.getBluetoothPermissions()) + requestPermissionAndScanLauncher.launch(requireContext().getBluetoothPermissions()) } .show() } @@ -710,7 +715,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { scanModel.setupScan() // system permissions might have changed while we were away - binding.provideLocationCheckbox.isChecked = myActivity.hasBackgroundPermission() && (model.provideLocation.value ?: false) + binding.provideLocationCheckbox.isChecked = requireContext().hasBackgroundPermission() && (model.provideLocation.value ?: false) myActivity.registerReceiver(updateProgressReceiver, updateProgressFilter)