diff --git a/app/src/main/java/com/geeksville/mesh/MainActivity.kt b/app/src/main/java/com/geeksville/mesh/MainActivity.kt index aaa758981..b3509b158 100644 --- a/app/src/main/java/com/geeksville/mesh/MainActivity.kt +++ b/app/src/main/java/com/geeksville/mesh/MainActivity.kt @@ -47,6 +47,7 @@ import com.geeksville.mesh.android.getLocationPermissions import com.geeksville.mesh.android.getBackgroundPermissions import com.geeksville.mesh.android.getCameraPermissions import com.geeksville.mesh.android.getMissingPermissions +import com.geeksville.mesh.android.getScanPermissions import com.geeksville.mesh.database.entity.Packet import com.geeksville.mesh.databinding.ActivityMainBinding import com.geeksville.mesh.model.ChannelSet @@ -293,6 +294,9 @@ class MainActivity : AppCompatActivity(), Logging, return getMissingPermissions(perms) } + /** Ask the user to grant Bluetooth scan/discovery permission */ + fun requestScanPermission() = requestPermission(getScanPermissions(), true) + /** Ask the user to grant camera permission */ fun requestCameraPermission() = requestPermission(getCameraPermissions(), false) @@ -338,7 +342,7 @@ class MainActivity : AppCompatActivity(), Logging, * * @return true if we already have the needed permissions */ - fun requestPermission( + private fun requestPermission( missingPerms: List = getMinimumPermissions(), shouldShowDialog: Boolean = true ): Boolean = diff --git a/app/src/main/java/com/geeksville/mesh/android/ContextServices.kt b/app/src/main/java/com/geeksville/mesh/android/ContextServices.kt index 6e8eed03d..71e22b0b3 100644 --- a/app/src/main/java/com/geeksville/mesh/android/ContextServices.kt +++ b/app/src/main/java/com/geeksville/mesh/android/ContextServices.kt @@ -8,6 +8,7 @@ import android.content.pm.PackageManager import android.hardware.usb.UsbManager import android.os.Build import androidx.core.content.ContextCompat +import com.geeksville.mesh.service.BluetoothInterface /** * @return null on platforms without a BlueTooth driver (i.e. the emulator) @@ -28,6 +29,25 @@ fun Context.getMissingPermissions(perms: List) = perms.filter { ) != PackageManager.PERMISSION_GRANTED } +/** + * Bluetooth scan/discovery permissions (or empty if we already have what we need) + */ +fun Context.getScanPermissions(): List { + val perms = mutableListOf() + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + perms.add(Manifest.permission.BLUETOOTH_SCAN) + } else if (!BluetoothInterface.hasCompanionDeviceApi(this)) { + perms.add(Manifest.permission.ACCESS_FINE_LOCATION) + perms.add(Manifest.permission.BLUETOOTH_ADMIN) + } + + return getMissingPermissions(perms) +} + +/** @return true if the user already has Bluetooth scan/discovery permission */ +fun Context.hasScanPermission() = getScanPermissions().isEmpty() + /** * Camera permission (or empty if we already have what we need) */ @@ -49,7 +69,7 @@ fun Context.getLocationPermissions(): List { return getMissingPermissions(perms) } -/** @return true if the user already has camera permission */ +/** @return true if the user already has location permission */ fun Context.hasLocationPermission() = getLocationPermissions().isEmpty() /** 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 f5dbbbcea..b19290a2e 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt @@ -34,6 +34,7 @@ import com.geeksville.mesh.MainActivity import com.geeksville.mesh.R import com.geeksville.mesh.RadioConfigProtos import com.geeksville.mesh.android.bluetoothManager +import com.geeksville.mesh.android.hasScanPermission import com.geeksville.mesh.android.hasLocationPermission import com.geeksville.mesh.android.hasBackgroundPermission import com.geeksville.mesh.android.usbManager @@ -642,9 +643,9 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { } }) - scanModel.devices.observe( - viewLifecycleOwner, - { devices -> updateDevicesButtons(devices) }) + scanModel.devices.observe(viewLifecycleOwner, { devices -> + updateDevicesButtons(devices) + }) binding.updateFirmwareButton.setOnClickListener { doFirmwareUpdate() @@ -733,9 +734,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { scanModel.onSelected(myActivity, device) if (!b.isSelected) { - binding.warningNotPaired.visibility = View.VISIBLE - binding.scanStatusText.text = getString(R.string.not_paired_yet) - // binding.scanStatusText.text = getString(R.string.please_pair) + binding.scanStatusText.text = getString(R.string.please_pair) } } } @@ -794,15 +793,22 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { if (curRadio != null && !MockInterface.addressValid(requireContext(), "")) { binding.warningNotPaired.visibility = View.GONE // binding.scanStatusText.text = getString(R.string.current_pair).format(curRadio) + } else { + binding.warningNotPaired.visibility = View.VISIBLE + binding.scanStatusText.text = getString(R.string.not_paired_yet) } } private fun initClassicScan() { binding.changeRadioButton.setOnClickListener { - if (myActivity.warnMissingPermissions()) { - myActivity.requestPermission() - } else scanLeDevice() + debug("User clicked changeRadioButton") + if (!myActivity.hasScanPermission()) { + myActivity.requestScanPermission() + } else { + checkLocationEnabled() + scanLeDevice() + } } } @@ -830,7 +836,13 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { private fun initModernScan() { binding.changeRadioButton.setOnClickListener { - myActivity.startCompanionScan() + debug("User clicked changeRadioButton") + if (!myActivity.hasScanPermission()) { + myActivity.requestScanPermission() + } else { + // checkLocationEnabled() // ? some phones still need location turned on + myActivity.startCompanionScan() + } } }