diff --git a/app/build.gradle b/app/build.gradle index 1f703a316..d452d9026 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -31,8 +31,8 @@ android { applicationId "com.geeksville.mesh" minSdkVersion 21 // The oldest emulator image I have tried is 22 (though 21 probably works) targetSdkVersion 29 - versionCode 20146 // format is Mmmss (where M is 1+the numeric major number - versionName "1.1.46" + versionCode 20148 // format is Mmmss (where M is 1+the numeric major number + versionName "1.1.48" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" // per https://developer.android.com/studio/write/vector-asset-studio @@ -117,14 +117,14 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.core:core-ktx:1.3.2' - implementation 'androidx.fragment:fragment-ktx:1.2.5' + implementation 'androidx.fragment:fragment-ktx:1.3.0' implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.recyclerview:recyclerview:1.1.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'com.google.android.material:material:1.3.0' implementation 'androidx.viewpager2:viewpager2:1.0.0' implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' - implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0' + implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.0' implementation "androidx.room:room-runtime:$room_version" kapt "androidx.room:room-compiler:$room_version" diff --git a/app/src/main/java/com/geeksville/mesh/ui/AdvancedSettingsFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/AdvancedSettingsFragment.kt index 4c970bf90..75175a14e 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/AdvancedSettingsFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/AdvancedSettingsFragment.kt @@ -14,6 +14,7 @@ import com.geeksville.mesh.databinding.AdvancedSettingsBinding import com.geeksville.mesh.model.ChannelOption import com.geeksville.mesh.model.UIViewModel import com.geeksville.mesh.service.MeshService +import com.geeksville.util.exceptionToSnackbar import com.google.android.material.snackbar.Snackbar class AdvancedSettingsFragment : ScreenFragment("Advanced Settings"), Logging { @@ -54,7 +55,9 @@ class AdvancedSettingsFragment : ScreenFragment("Advanced Settings"), Logging { ?: ChannelOption.defaultMinBroadcastPeriod if (n != null && n < MAX_INT_DEVICE && (n == 0 || n >= minBroadcastPeriodSecs)) { - model.positionBroadcastSecs = n + exceptionToSnackbar(requireView()) { + model.positionBroadcastSecs = n + } } else { // restore the value in the edit field textEdit.setText(model.positionBroadcastSecs.toString()) @@ -73,7 +76,9 @@ class AdvancedSettingsFragment : ScreenFragment("Advanced Settings"), Logging { val str = binding.lsSleepEditText.text.toString() val n = str.toIntOrNull() if (n != null && n < MAX_INT_DEVICE && n >= 0) { - model.lsSleepSecs = n + exceptionToSnackbar(requireView()) { + model.lsSleepSecs = n + } } else { Snackbar.make(requireView(), "Bad value: $str", Snackbar.LENGTH_LONG).show() } 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 73fad2ec9..874c00af1 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt @@ -44,6 +44,7 @@ import com.geeksville.mesh.service.SoftwareUpdateService.Companion.ProgressNotSt import com.geeksville.mesh.service.SoftwareUpdateService.Companion.ProgressSuccess import com.geeksville.util.anonymize import com.geeksville.util.exceptionReporter +import com.geeksville.util.exceptionToSnackbar import com.google.android.gms.location.LocationRequest import com.google.android.gms.location.LocationServices import com.google.android.gms.location.LocationSettingsRequest @@ -226,8 +227,14 @@ class BTScanModel(app: Application) : AndroidViewModel(app), Logging { debug("onScanResult ${entry}") // If nothing was selected, by default select the first valid thing we see - val activity = + val activity: MainActivity? = try { GeeksvilleApplication.currentActivity as MainActivity? // Can be null if app is shutting down + } catch (_: ClassCastException) { + // Buggy "Z812" phones apparently have the wrong class type for this + errormsg("Unexpected class for main activity") + null + } + if (selectedAddress == null && entry.bonded && activity != null) changeScanSelection( activity, @@ -265,7 +272,10 @@ class BTScanModel(app: Application) : AndroidViewModel(app), Logging { debug("BTScan component active") selectedAddress = RadioInterfaceService.getDeviceAddress(context) - return if (bluetoothAdapter == null || RadioInterfaceService.isMockInterfaceAvailable(context)) { + return if (bluetoothAdapter == null || RadioInterfaceService.isMockInterfaceAvailable( + context + ) + ) { warn("No bluetooth adapter. Running under emulation?") val testnodes = listOf( @@ -495,8 +505,10 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { binding.updateProgressBar.visibility = View.VISIBLE binding.updateProgressBar.progress = 0 // start from scratch - // We rely on our broadcast receiver to show progress as this progresses - service.startFirmwareUpdate() + exceptionToSnackbar(requireView()) { + // We rely on our broadcast receiver to show progress as this progresses + service.startFirmwareUpdate() + } } } @@ -578,7 +590,6 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { }) - // Only let user edit their name or set software update while connected to a radio model.isConnected.observe(viewLifecycleOwner, Observer { connectionState -> val connected = connectionState == MeshService.ConnectionState.CONNECTED @@ -665,11 +676,12 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { binding.scanProgressBar.visibility = visible binding.deviceRadioGroup.visibility = visible } - private fun updateDevicesButtons( devices: MutableMap?) { + + private fun updateDevicesButtons(devices: MutableMap?) { // Remove the old radio buttons and repopulate binding.deviceRadioGroup.removeAllViews() - if(devices == null) return + if (devices == null) return val adapter = scanModel.bluetoothAdapter var hasShownOurDevice = false @@ -696,7 +708,10 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { scanModel.selectedAddress!!, bDevice.bondState == BOND_BONDED ) - addDeviceButton(curDevice, model.isConnected.value == MeshService.ConnectionState.CONNECTED) + addDeviceButton( + curDevice, + model.isConnected.value == MeshService.ConnectionState.CONNECTED + ) } } else if (scanModel.selectedUSB != null) { // Must be a USB device, show a placeholder disabled entry @@ -714,7 +729,8 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { // get rid of the warning text once at least one device is paired. // If we are running on an emulator, always leave this message showing so we can test the worst case layout - binding.warningNotPaired.visibility = if (hasBonded && !RadioInterfaceService.isMockInterfaceAvailable(requireContext())) View.GONE else View.VISIBLE + binding.warningNotPaired.visibility = + if (hasBonded && !RadioInterfaceService.isMockInterfaceAvailable(requireContext())) View.GONE else View.VISIBLE } /// Setup the GUI to do a classic (pre SDK 26 BLE scan) diff --git a/geeksville-androidlib b/geeksville-androidlib index ee6611838..fb14fb659 160000 --- a/geeksville-androidlib +++ b/geeksville-androidlib @@ -1 +1 @@ -Subproject commit ee6611838637d096b39e11365930eb90a5f0fd2e +Subproject commit fb14fb659d0b235d325a0d9195cb5f47424dff51