mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
Fix #38: USB host mode now fully supported
thanks @sexycyborg for the idea!
This commit is contained in:
parent
c747cecc31
commit
cba3e85d03
2 changed files with 69 additions and 52 deletions
|
|
@ -414,6 +414,9 @@ class MainActivity : AppCompatActivity(), Logging,
|
|||
|
||||
private var requestedChannelUrl: Uri? = null
|
||||
|
||||
/** We keep the usb device here, so later we can give it to our service */
|
||||
private var usbDevice: UsbDevice? = null
|
||||
|
||||
/// Handle any itents that were passed into us
|
||||
private fun handleIntent(intent: Intent) {
|
||||
val appLinkAction = intent.action
|
||||
|
|
@ -434,7 +437,7 @@ class MainActivity : AppCompatActivity(), Logging,
|
|||
UsbManager.ACTION_USB_DEVICE_ATTACHED -> {
|
||||
val device: UsbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)!!
|
||||
debug("Handle USB device attached! $device")
|
||||
showSettingsPage() // Later in the boot we should show the settings page
|
||||
usbDevice = device
|
||||
}
|
||||
|
||||
Intent.ACTION_MAIN -> {
|
||||
|
|
@ -683,6 +686,12 @@ class MainActivity : AppCompatActivity(), Logging,
|
|||
override fun onConnected(service: com.geeksville.mesh.IMeshService) = exceptionReporter {
|
||||
model.meshService = service
|
||||
|
||||
usbDevice?.let { usb ->
|
||||
debug("Switching to USB radio ${usb.deviceName}")
|
||||
service.setDeviceAddress(SerialInterface.toInterfaceName(usb.deviceName))
|
||||
usbDevice = null // Only switch once - thereafter it should be stored in settings
|
||||
}
|
||||
|
||||
// We don't start listening for packets until after we are connected to the service
|
||||
registerMeshReceiver()
|
||||
|
||||
|
|
@ -746,23 +755,25 @@ class MainActivity : AppCompatActivity(), Logging,
|
|||
override fun onStart() {
|
||||
super.onStart()
|
||||
|
||||
// Ensures Bluetooth is available on the device and it is enabled. If not,
|
||||
// displays a dialog requesting user permission to enable Bluetooth.
|
||||
if (!isInTestLab) {
|
||||
bluetoothAdapter?.takeIf { !it.isEnabled }?.apply {
|
||||
val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
|
||||
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT)
|
||||
// Ask to start bluetooth if no USB devices are visible
|
||||
val hasUSB = SerialInterface.findDrivers(this).isNotEmpty()
|
||||
if (!isInTestLab && !hasUSB) {
|
||||
bluetoothAdapter?.let {
|
||||
if (!it.isEnabled) {
|
||||
val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
|
||||
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bindMeshService()
|
||||
|
||||
val bonded = RadioInterfaceService.getBondedDeviceAddress(this) != null
|
||||
if (!bonded)
|
||||
if (!bonded && usbDevice == null) // we will handle USB later
|
||||
showSettingsPage()
|
||||
}
|
||||
|
||||
fun showSettingsPage() {
|
||||
private fun showSettingsPage() {
|
||||
pager.currentItem = 5
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ class BTScanModel(app: Application) : AndroidViewModel(app), Logging {
|
|||
|
||||
class USBDeviceListEntry(usbManager: UsbManager, val usb: UsbSerialDriver) : DeviceListEntry(
|
||||
usb.device.deviceName,
|
||||
"s${usb.device.deviceName}",
|
||||
SerialInterface.toInterfaceName(usb.device.deviceName),
|
||||
SerialInterface.assumePermission || usbManager.hasPermission(usb.device)
|
||||
)
|
||||
|
||||
|
|
@ -277,14 +277,17 @@ class BTScanModel(app: Application) : AndroidViewModel(app), Logging {
|
|||
/// The following call might return null if the user doesn't have bluetooth access permissions
|
||||
val s: BluetoothLeScanner? = bluetoothAdapter.bluetoothLeScanner
|
||||
|
||||
if (s == null) {
|
||||
val usbDrivers = SerialInterface.findDrivers(context)
|
||||
|
||||
/* model.bluetoothEnabled.value */
|
||||
|
||||
if (s == null && usbDrivers.isEmpty()) {
|
||||
errorText.value =
|
||||
context.getString(R.string.requires_bluetooth)
|
||||
|
||||
false
|
||||
} else {
|
||||
if (scanner == null) {
|
||||
debug("starting scan")
|
||||
|
||||
// Clear the old device list
|
||||
devices.value?.clear()
|
||||
|
|
@ -292,23 +295,27 @@ class BTScanModel(app: Application) : AndroidViewModel(app), Logging {
|
|||
// Include a placeholder for "None"
|
||||
addDevice(DeviceListEntry(context.getString(R.string.none), "n", true))
|
||||
|
||||
SerialInterface.findDrivers(context).forEach { d ->
|
||||
usbDrivers.forEach { d ->
|
||||
addDevice(
|
||||
USBDeviceListEntry(usbManager, d)
|
||||
)
|
||||
}
|
||||
|
||||
// filter and only accept devices that have our service
|
||||
val filter =
|
||||
ScanFilter.Builder()
|
||||
.setServiceUuid(ParcelUuid(BluetoothInterface.BTM_SERVICE_UUID))
|
||||
.build()
|
||||
if (s != null) { // could be null if bluetooth is disabled
|
||||
debug("starting scan")
|
||||
|
||||
val settings =
|
||||
ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
|
||||
.build()
|
||||
s.startScan(listOf(filter), settings, scanCallback)
|
||||
scanner = s
|
||||
// filter and only accept devices that have our service
|
||||
val filter =
|
||||
ScanFilter.Builder()
|
||||
.setServiceUuid(ParcelUuid(BluetoothInterface.BTM_SERVICE_UUID))
|
||||
.build()
|
||||
|
||||
val settings =
|
||||
ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
|
||||
.build()
|
||||
s.startScan(listOf(filter), settings, scanCallback)
|
||||
scanner = s
|
||||
}
|
||||
} else {
|
||||
debug("scan already running")
|
||||
}
|
||||
|
|
@ -597,8 +604,9 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
|||
// Turn off the widgets for the new API (we turn on/off hte classic widgets when we start scanning
|
||||
changeRadioButton.visibility = View.GONE
|
||||
|
||||
showClassicWidgets(View.VISIBLE)
|
||||
|
||||
model.bluetoothEnabled.observe(viewLifecycleOwner, Observer { enabled ->
|
||||
showClassicWidgets(if (enabled) View.VISIBLE else View.GONE)
|
||||
if (enabled)
|
||||
scanModel.startScan()
|
||||
else
|
||||
|
|
@ -616,39 +624,36 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
|||
deviceRadioGroup.removeAllViews()
|
||||
|
||||
val adapter = scanModel.bluetoothAdapter
|
||||
if (adapter != null && adapter.isEnabled) {
|
||||
// This code requres BLE to be enabled
|
||||
|
||||
var hasShownOurDevice = false
|
||||
devices.values.forEach { device ->
|
||||
if (device.address == scanModel.selectedNotNull)
|
||||
hasShownOurDevice = true
|
||||
addDeviceButton(device, true)
|
||||
}
|
||||
var hasShownOurDevice = false
|
||||
devices.values.forEach { device ->
|
||||
if (device.address == scanModel.selectedNotNull)
|
||||
hasShownOurDevice = true
|
||||
addDeviceButton(device, true)
|
||||
}
|
||||
|
||||
// The device the user is already paired with is offline currently, still show it
|
||||
// it in the list, but greyed out
|
||||
if (!hasShownOurDevice) {
|
||||
if (scanModel.selectedBluetooth != null) {
|
||||
val bDevice =
|
||||
scanModel.bluetoothAdapter!!.getRemoteDevice(scanModel.selectedBluetooth)
|
||||
if (bDevice.name != null) { // ignore nodes that node have a name, that means we've lost them since they appeared
|
||||
val curDevice = BTScanModel.DeviceListEntry(
|
||||
bDevice.name,
|
||||
scanModel.selectedAddress!!,
|
||||
bDevice.bondState == BOND_BONDED
|
||||
)
|
||||
addDeviceButton(curDevice, false)
|
||||
}
|
||||
} else if (scanModel.selectedUSB != null) {
|
||||
// Must be a USB device, show a placeholder disabled entry
|
||||
// The device the user is already paired with is offline currently, still show it
|
||||
// it in the list, but greyed out
|
||||
if (!hasShownOurDevice) {
|
||||
if (scanModel.selectedBluetooth != null && adapter != null && adapter.isEnabled) {
|
||||
val bDevice =
|
||||
adapter.getRemoteDevice(scanModel.selectedBluetooth)
|
||||
if (bDevice.name != null) { // ignore nodes that node have a name, that means we've lost them since they appeared
|
||||
val curDevice = BTScanModel.DeviceListEntry(
|
||||
scanModel.selectedUSB!!,
|
||||
bDevice.name,
|
||||
scanModel.selectedAddress!!,
|
||||
false
|
||||
bDevice.bondState == BOND_BONDED
|
||||
)
|
||||
addDeviceButton(curDevice, false)
|
||||
}
|
||||
} else if (scanModel.selectedUSB != null) {
|
||||
// Must be a USB device, show a placeholder disabled entry
|
||||
val curDevice = BTScanModel.DeviceListEntry(
|
||||
scanModel.selectedUSB!!,
|
||||
scanModel.selectedAddress!!,
|
||||
false
|
||||
)
|
||||
addDeviceButton(curDevice, false)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -747,11 +752,12 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
|||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (!hasCompanionDeviceApi && model.bluetoothEnabled.value!!)
|
||||
if (!hasCompanionDeviceApi)
|
||||
scanModel.startScan()
|
||||
|
||||
// Keep reminding user BLE is still off
|
||||
if (scanModel.bluetoothAdapter?.isEnabled != true) {
|
||||
val hasUSB = activity?.let { SerialInterface.findDrivers(it).isNotEmpty() } ?: true
|
||||
if (scanModel.bluetoothAdapter?.isEnabled != true && !hasUSB) {
|
||||
Toast.makeText(
|
||||
requireContext(),
|
||||
R.string.error_bluetooth,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue