mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-05-11 16:15:24 -04:00
fix: Resolve top Crashlytics issues for 29320633 beta release (#5278)
This commit is contained in:
@@ -17,7 +17,7 @@
|
||||
package org.meshtastic.app.map.component
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import androidx.lifecycle.compose.LocalLifecycleOwner
|
||||
@@ -49,11 +49,13 @@ fun NodeClusterMarkers(
|
||||
val savedStateRegistryOwner = LocalSavedStateRegistryOwner.current
|
||||
|
||||
// Workaround for https://github.com/googlemaps/android-maps-compose/issues/858
|
||||
// and https://github.com/googlemaps/android-maps-compose/issues/875
|
||||
// The maps clustering library creates an internal ComposeView to snapshot markers.
|
||||
// If that view is not attached to the hierarchy (which it often isn't during rendering),
|
||||
// it fails to find the Lifecycle and SavedState owners. We propagate them to the root view
|
||||
// so the internal snapshot view can find them when walking up the tree.
|
||||
LaunchedEffect(view, lifecycleOwner, savedStateRegistryOwner) {
|
||||
// We do this in a SideEffect to ensure it happens before or during composition of children.
|
||||
SideEffect {
|
||||
val root = view.rootView
|
||||
if (root.findViewTreeLifecycleOwner() == null) {
|
||||
root.setViewTreeLifecycleOwner(lifecycleOwner)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.meshtastic.core.ble
|
||||
|
||||
import co.touchlab.kermit.Logger
|
||||
import com.juul.kable.NotConnectedException
|
||||
import com.juul.kable.Peripheral
|
||||
import com.juul.kable.PeripheralBuilder
|
||||
import com.juul.kable.State
|
||||
@@ -259,6 +260,9 @@ class KableBleConnection(private val scope: CoroutineScope, private val loggingC
|
||||
private suspend fun safeClosePeripheral(tag: String) {
|
||||
try {
|
||||
peripheral?.disconnect()
|
||||
} catch (_: NotConnectedException) {
|
||||
// Silence "Disconnect requested" which Kable throws if already disconnected.
|
||||
// This is a common non-fatal reported in Crashlytics that is safe to ignore here.
|
||||
} catch (e: Exception) {
|
||||
Logger.w(e) { "[$tag] Failed to disconnect peripheral" }
|
||||
}
|
||||
|
||||
@@ -356,6 +356,9 @@ class BleRadioTransport(
|
||||
// materially speeds up the initial config drain and any bulk fromRadio reads.
|
||||
if (bleConnection.requestHighConnectionPriority()) {
|
||||
Logger.d { "[$address] Requested high BLE connection priority" }
|
||||
// Wait for the connection parameter update to succeed before starting the heavy traffic
|
||||
// in onConnect(). Otherwise, the Android BLE stack may disconnect with GATT 147.
|
||||
delay(1.seconds)
|
||||
}
|
||||
|
||||
this@BleRadioTransport.callback.onConnect()
|
||||
|
||||
@@ -159,9 +159,24 @@ class MeshService : Service() {
|
||||
0
|
||||
}
|
||||
|
||||
startForegroundSafely(notification, foregroundServiceType)
|
||||
|
||||
return if (!wantForeground) {
|
||||
Logger.i { "Stopping mesh service because no device is selected" }
|
||||
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE)
|
||||
stopSelf()
|
||||
START_NOT_STICKY
|
||||
} else {
|
||||
START_STICKY
|
||||
}
|
||||
}
|
||||
|
||||
private fun startForegroundSafely(notification: android.app.Notification, foregroundServiceType: Int) {
|
||||
@Suppress("TooGenericExceptionCaught")
|
||||
try {
|
||||
ServiceCompat.startForeground(this, SERVICE_NOTIFY_ID, notification, foregroundServiceType)
|
||||
} catch (ex: android.app.ForegroundServiceStartNotAllowedException) {
|
||||
Logger.e(ex) { "ForegroundServiceStartNotAllowedException: OS restricted background start." }
|
||||
} catch (ex: SecurityException) {
|
||||
// On Android 14+ starting a location FGS from the background can fail with SecurityException
|
||||
// if the app is not in an allowed state. Retry without the location type if that was requested.
|
||||
@@ -177,6 +192,8 @@ class MeshService : Service() {
|
||||
}
|
||||
try {
|
||||
ServiceCompat.startForeground(this, SERVICE_NOTIFY_ID, notification, connectedDeviceOnly)
|
||||
} catch (retryEx: android.app.ForegroundServiceStartNotAllowedException) {
|
||||
Logger.e(retryEx) { "ForegroundServiceStartNotAllowedException on retry." }
|
||||
} catch (retryEx: Exception) {
|
||||
Logger.e(retryEx) { "Failed to start foreground service even after retry" }
|
||||
}
|
||||
@@ -185,16 +202,6 @@ class MeshService : Service() {
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
Logger.e(ex) { "Error starting foreground service" }
|
||||
return START_NOT_STICKY
|
||||
}
|
||||
|
||||
return if (!wantForeground) {
|
||||
Logger.i { "Stopping mesh service because no device is selected" }
|
||||
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE)
|
||||
stopSelf()
|
||||
START_NOT_STICKY
|
||||
} else {
|
||||
START_STICKY
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user