diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 940195c5d..91cfdb93d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -44,6 +44,9 @@
+
+
diff --git a/app/src/main/java/com/geeksville/mesh/MainActivity.kt b/app/src/main/java/com/geeksville/mesh/MainActivity.kt
index e380da5ae..dd91a3397 100644
--- a/app/src/main/java/com/geeksville/mesh/MainActivity.kt
+++ b/app/src/main/java/com/geeksville/mesh/MainActivity.kt
@@ -6,6 +6,8 @@ import android.app.Activity
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothManager
+import android.companion.AssociationRequest
+import android.companion.BluetoothDeviceFilter
import android.companion.CompanionDeviceManager
import android.content.*
import android.content.pm.PackageInfo
@@ -70,6 +72,7 @@ import java.lang.Runnable
import java.nio.charset.Charset
import java.text.DateFormat
import java.util.*
+import java.util.regex.Pattern
import kotlin.math.roundToInt
@@ -131,8 +134,7 @@ class MainActivity : AppCompatActivity(), Logging,
const val REQUEST_ENABLE_BT = 10
const val DID_REQUEST_PERM = 11
const val RC_SIGN_IN = 12 // google signin completed
- const val RC_SELECT_DEVICE =
- 13 // seems to be hardwired in CompanionDeviceManager to add 65536
+ const val SELECT_DEVICE_REQUEST_CODE = 13
const val CREATE_CSV_FILE = 14
}
@@ -194,11 +196,52 @@ class MainActivity : AppCompatActivity(), Logging,
}
}
-
private val btStateReceiver = BluetoothStateReceiver { _ ->
updateBluetoothEnabled()
}
+ fun startCompanionScan() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val deviceManager: CompanionDeviceManager by lazy {
+ getSystemService(Context.COMPANION_DEVICE_SERVICE) as CompanionDeviceManager
+ }
+
+ // To skip filtering based on name and supported feature flags (UUIDs),
+ // don't include calls to setNamePattern() and addServiceUuid(),
+ // respectively. This example uses Bluetooth.
+ // We only look for Mesh (rather than the full name) because NRF52 uses a very short name
+ val deviceFilter: BluetoothDeviceFilter = BluetoothDeviceFilter.Builder()
+ .setNamePattern(Pattern.compile("Mesh.*"))
+ // .addServiceUuid(ParcelUuid(RadioInterfaceService.BTM_SERVICE_UUID), null)
+ .build()
+
+ // The argument provided in setSingleDevice() determines whether a single
+ // device name or a list of device names is presented to the user as
+ // pairing options.
+ val pairingRequest: AssociationRequest = AssociationRequest.Builder()
+ .addDeviceFilter(deviceFilter)
+ .setSingleDevice(false)
+ .build()
+
+ // When the app tries to pair with the Bluetooth device, show the
+ // appropriate pairing request dialog to the user.
+ deviceManager.associate(pairingRequest,
+ object : CompanionDeviceManager.Callback() {
+ override fun onDeviceFound(chooserLauncher: IntentSender) {
+ startIntentSenderForResult(chooserLauncher,
+ SELECT_DEVICE_REQUEST_CODE, null, 0, 0, 0)
+ }
+
+ override fun onFailure(error: CharSequence?) {
+ warn("BLE selection service failed $error")
+ // changeDeviceSelection(mainActivity, null) // deselect any device
+ }
+ }, null
+ )
+ }
+ else warn("startCompanionScan should not run on SDK < 26")
+ }
+
/**
* Don't tell our app we have bluetooth until we have bluetooth _and_ location access
*/
@@ -410,7 +453,6 @@ class MainActivity : AppCompatActivity(), Logging,
}
}
-
/// Ask user to rate in play store
private fun askToRate() {
exceptionReporter { // Got one IllegalArgumentException from inside this lib, but we don't want to crash our app because of bugs in this optional feature
@@ -497,7 +539,6 @@ class MainActivity : AppCompatActivity(), Logging,
requestPermission()
}
-
private fun initToolbar() {
val toolbar =
findViewById(R.id.toolbar) as Toolbar
@@ -601,25 +642,18 @@ class MainActivity : AppCompatActivity(), Logging,
GoogleSignIn.getSignedInAccountFromIntent(data)
handleSignInResult(task)
}
- (65536 + RC_SELECT_DEVICE) -> when (resultCode) {
+ (SELECT_DEVICE_REQUEST_CODE) -> when (resultCode) {
Activity.RESULT_OK -> {
- // User has chosen to pair with the Bluetooth device.
- val device: BluetoothDevice =
+ val deviceToPair: BluetoothDevice =
data?.getParcelableExtra(CompanionDeviceManager.EXTRA_DEVICE)!!
- debug("Received BLE pairing ${device.address}")
- if (device.bondState != BluetoothDevice.BOND_BONDED) {
- device.createBond()
- // FIXME - wait for bond to complete
+ if (deviceToPair.bondState != BluetoothDevice.BOND_BONDED) {
+ deviceToPair.createBond()
}
-
- // ... Continue interacting with the paired device.
model.meshService?.let { service ->
- MeshService.changeDeviceAddress(this@MainActivity, service, device.address)
+ MeshService.changeDeviceAddress(this@MainActivity, service, "x${deviceToPair.address}")
}
}
-
- else ->
- warn("BLE device select intent failed")
+ else -> warn("BLE device select intent failed")
}
CREATE_CSV_FILE -> {
if (resultCode == Activity.RESULT_OK) {
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 3d9a4feb5..bb8f0a9ff 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt
@@ -7,9 +7,6 @@ import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothDevice.BOND_BONDED
import android.bluetooth.BluetoothDevice.BOND_BONDING
import android.bluetooth.le.*
-import android.companion.AssociationRequest
-import android.companion.BluetoothDeviceFilter
-import android.companion.CompanionDeviceManager
import android.content.*
import android.content.pm.PackageManager
import android.hardware.usb.UsbDevice
@@ -56,7 +53,6 @@ import com.hoho.android.usbserial.driver.UsbSerialDriver
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
-import java.util.regex.Pattern
object SLogging : Logging
@@ -106,7 +102,6 @@ private fun requestBonding(
device.createBond()
}
-
class BTScanModel(app: Application) : AndroidViewModel(app), Logging {
private val context: Context get() = getApplication().applicationContext
@@ -123,7 +118,6 @@ class BTScanModel(app: Application) : AndroidViewModel(app), Logging {
else
null
-
override fun toString(): String {
return "DeviceListEntry(name=${name.anonymize}, addr=${address.anonymize})"
}
@@ -187,7 +181,7 @@ class BTScanModel(app: Application) : AndroidViewModel(app), Logging {
if ((result.device.name?.startsWith("Mesh") == true)) {
val addr = result.device.address
- val fullAddr = "x$addr" // full address with the bluetooh prefix
+ val fullAddr = "x$addr" // full address with the bluetooth prefix added
// prevent logspam because weill get get lots of redundant scan results
val isBonded = result.device.bondState == BluetoothDevice.BOND_BONDED
val oldDevs = devices.value!!
@@ -456,10 +450,6 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
BluetoothInterface.hasCompanionDeviceApi(requireContext())
}
- private val deviceManager: CompanionDeviceManager by lazy {
- requireContext().getSystemService(CompanionDeviceManager::class.java)
- }
-
private val myActivity get() = requireActivity() as MainActivity
override fun onDestroy() {
@@ -540,6 +530,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
val isConnected = connected == MeshService.ConnectionState.CONNECTED
binding.nodeSettings.visibility = if (isConnected) View.VISIBLE else View.GONE
+ binding.provideLocationCheckbox.visibility = if (isConnected) View.VISIBLE else View.GONE
if (connected == MeshService.ConnectionState.DISCONNECTED)
model.ownerName.value = ""
@@ -720,7 +711,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
device.address == scanModel.selectedNotNull && device.bonded // Only show checkbox if device is still paired
binding.deviceRadioGroup.addView(b)
- // Once we have at least one device, don't show the "looking for" animation - it makes uers think
+ // Once we have at least one device, don't show the "looking for" animation - it makes users think
// something is busted
binding.scanProgressBar.visibility = View.INVISIBLE
@@ -830,56 +821,6 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
{ updateDevicesButtons(scanModel.devices.value) })
}
- /// Start running the modern scan, once it has one result we enable the
- private fun startBackgroundScan() {
- // Disable the change button until our scan has some results
- binding.changeRadioButton.isEnabled = false
-
- // To skip filtering based on name and supported feature flags (UUIDs),
- // don't include calls to setNamePattern() and addServiceUuid(),
- // respectively. This example uses Bluetooth.
- // We only look for Mesh (rather than the full name) because NRF52 uses a very short name
- val deviceFilter: BluetoothDeviceFilter = BluetoothDeviceFilter.Builder()
- .setNamePattern(Pattern.compile("Mesh.*"))
- // .addServiceUuid(ParcelUuid(RadioInterfaceService.BTM_SERVICE_UUID), null)
- .build()
-
- // The argument provided in setSingleDevice() determines whether a single
- // device name or a list of device names is presented to the user as
- // pairing options.
- val pairingRequest: AssociationRequest = AssociationRequest.Builder()
- .addDeviceFilter(deviceFilter)
- .setSingleDevice(false)
- .build()
-
- // When the app tries to pair with the Bluetooth device, show the
- // appropriate pairing request dialog to the user.
- deviceManager.associate(
- pairingRequest,
- object : CompanionDeviceManager.Callback() {
-
- override fun onDeviceFound(chooserLauncher: IntentSender) {
- debug("Found one device - enabling button")
- binding.changeRadioButton.isEnabled = true
- binding.changeRadioButton.setOnClickListener {
- debug("User clicked BLE change button")
-
- // Request code seems to be ignored anyways
- startIntentSenderForResult(
- chooserLauncher,
- MainActivity.RC_SELECT_DEVICE, null, 0, 0, 0, null
- )
- }
- }
-
- override fun onFailure(error: CharSequence?) {
- warn("BLE selection service failed $error")
- // changeDeviceSelection(mainActivity, null) // deselect any device
- }
- }, null
- )
- }
-
private fun initModernScan() {
// Turn off the widgets for the classic API
binding.scanProgressBar.visibility = View.GONE
@@ -895,8 +836,9 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
binding.scanStatusText.text = getString(R.string.not_paired_yet)
binding.changeRadioButton.setText(R.string.select_radio)
}
-
- startBackgroundScan()
+ binding.changeRadioButton.setOnClickListener {
+ myActivity.startCompanionScan()
+ }
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {