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 6e37d63e7..9843253e7 100644 --- a/app/src/main/java/com/geeksville/mesh/model/BTScanModel.kt +++ b/app/src/main/java/com/geeksville/mesh/model/BTScanModel.kt @@ -5,6 +5,7 @@ import android.app.Application import android.bluetooth.BluetoothDevice import android.companion.AssociationRequest import android.companion.BluetoothDeviceFilter +import android.companion.BluetoothLeDeviceFilter import android.companion.CompanionDeviceManager import android.content.* import android.hardware.usb.UsbManager @@ -267,6 +268,11 @@ class BTScanModel @Inject constructor( } } + fun onSelectedBle(address: String): Boolean { + val device = bluetoothRepository.getRemoteDevice(address) ?: return false + return onSelected(BLEDeviceListEntry(device)) + } + private val _spinner = MutableLiveData(false) val spinner: LiveData get() = _spinner @@ -281,24 +287,24 @@ class BTScanModel @Inject constructor( } @SuppressLint("NewApi") - private fun associationRequest(): AssociationRequest { - // 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(BLE_NAME_PATTERN)) - // .addServiceUuid(ParcelUuid(BluetoothInterface.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. - return AssociationRequest.Builder() - .addDeviceFilter(deviceFilter) - .setSingleDevice(false) - .build() - } + private fun associationRequest(): AssociationRequest = AssociationRequest.Builder() + .addDeviceFilter( + BluetoothDeviceFilter.Builder() + .setNamePattern(Pattern.compile(BLE_NAME_PATTERN)) + .build() + ) + .addDeviceFilter( + BluetoothLeDeviceFilter.Builder() + .setNamePattern(Pattern.compile(BLE_NAME_PATTERN)) + // .setScanFilter( + // ScanFilter.Builder() + // .setServiceUuid(ParcelUuid(BluetoothInterface.BTM_SERVICE_UUID)) + // .build() + // ) + .build() + ) + .setSingleDevice(false) + .build() @SuppressLint("NewApi") private fun startCompanionScan(context: Context) { 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 944436ff1..fd2305e21 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt @@ -1,7 +1,5 @@ package com.geeksville.mesh.ui -import android.bluetooth.BluetoothDevice -import android.companion.CompanionDeviceManager import android.content.BroadcastReceiver import android.content.Context import android.content.Intent @@ -35,7 +33,7 @@ import com.geeksville.mesh.repository.location.LocationRepository import com.geeksville.mesh.service.MeshService import com.geeksville.mesh.service.SoftwareUpdateService import com.geeksville.mesh.util.exceptionToSnackbar -import com.geeksville.mesh.util.getParcelableExtraCompat +import com.geeksville.mesh.util.getAssociationResult import com.geeksville.mesh.util.onEditorAction import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint @@ -57,9 +55,6 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { private val hasGps by lazy { requireContext().hasGps() } 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 -> @@ -224,8 +219,8 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { ActivityResultContracts.StartIntentSenderForResult() ) { it.data - ?.getParcelableExtraCompat(CompanionDeviceManager.EXTRA_DEVICE) - ?.let { device -> scanModel.onSelected(BTScanModel.BLEDeviceListEntry(device)) } + ?.getAssociationResult() + ?.let { address -> scanModel.onSelectedBle(address) } } val requestBackgroundAndCheckLauncher = @@ -489,7 +484,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { scanModel.stopScan() }, SCAN_PERIOD) scanning = true - scanModel.startScan(requireActivity().takeIf { useCompanionDeviceApi }) + scanModel.startScan(requireActivity().takeIf { hasCompanionDeviceApi }) } else { scanning = false scanModel.stopScan() diff --git a/app/src/main/java/com/geeksville/mesh/util/CompatExtensions.kt b/app/src/main/java/com/geeksville/mesh/util/CompatExtensions.kt index cfad127aa..a05b78426 100644 --- a/app/src/main/java/com/geeksville/mesh/util/CompatExtensions.kt +++ b/app/src/main/java/com/geeksville/mesh/util/CompatExtensions.kt @@ -1,6 +1,9 @@ package com.geeksville.mesh.util import android.app.PendingIntent +import android.bluetooth.BluetoothDevice +import android.companion.AssociationInfo +import android.companion.CompanionDeviceManager import android.content.Intent import android.content.pm.PackageInfo import android.content.pm.PackageManager @@ -35,3 +38,16 @@ fun PackageManager.getPackageInfoCompat(packageName: String, flags: Int = 0): Pa } else { @Suppress("DEPRECATION") getPackageInfo(packageName, flags) } + +fun Intent.getAssociationResult(): String? = when { + android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU -> + getParcelableExtraCompat(CompanionDeviceManager.EXTRA_ASSOCIATION) + ?.deviceMacAddress?.toString()?.uppercase() + + android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O -> + @Suppress("DEPRECATION") + getParcelableExtra(CompanionDeviceManager.EXTRA_DEVICE) + ?.address + + else -> null +}