From 920af7bde2617874a6ce4c3ef479a4b9144c266f Mon Sep 17 00:00:00 2001 From: QIU Date: Wed, 5 Aug 2026 02:50:40 +0000 Subject: [PATCH] fix(aprs): crash when enabling APRS with callsign set (foreground service type) Root cause: user reported crash on enabling APRS with a callsign set (empty callsign worked because the service stops early and never reaches startForeground). Android 14+ requires the service to declare foregroundServiceType when startForeground passes a type; the service had none -> process died on toggle. - Manifest: add android:foregroundServiceType="dataSync" - AprsCard: use startForegroundService() for start/report actions (Android 8+ standard for foreground services) - AprsForegroundService: try-catch around startForeground, fallback stopSelf instead of killing the process - AprsReporter: passcode "-1" (APRSdroid "no auth" convention) also auto-computes from callsign - Merged upstream 418a05e3 (zh wording fix, no conflicts) Verified: compileDebugKotlin all modules BUILD SUCCESSFUL, check_strings 9 files OK. --- app/src/main/AndroidManifest.xml | 3 ++- .../rtbishop/look4sat/AprsForegroundService.kt | 15 ++++++++++----- .../look4sat/core/data/aprs/AprsReporter.kt | 2 +- .../look4sat/feature/settings/AprsCard.kt | 6 +++--- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d77e8971..c3b572d8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -50,6 +50,7 @@ + android:exported="false" + android:foregroundServiceType="dataSync" /> diff --git a/app/src/main/java/com/rtbishop/look4sat/AprsForegroundService.kt b/app/src/main/java/com/rtbishop/look4sat/AprsForegroundService.kt index b9a5aeca..087a604d 100644 --- a/app/src/main/java/com/rtbishop/look4sat/AprsForegroundService.kt +++ b/app/src/main/java/com/rtbishop/look4sat/AprsForegroundService.kt @@ -80,11 +80,16 @@ class AprsForegroundService : Service() { } private fun startForegroundWithNotification(cfg: AprsConfig) { - val notif = buildNotification(cfg) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - startForeground(NOTIF_ID, notif, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC) - } else { - startForeground(NOTIF_ID, notif) + try { + val notif = buildNotification(cfg) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + startForeground(NOTIF_ID, notif, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC) + } else { + startForeground(NOTIF_ID, notif) + } + } catch (e: Exception) { + // 厂商 ROM / 旧系统兼容兜底:启动前台失败只停服务,不崩进程 + stopSelf() } } diff --git a/core/data/src/main/java/com/rtbishop/look4sat/core/data/aprs/AprsReporter.kt b/core/data/src/main/java/com/rtbishop/look4sat/core/data/aprs/AprsReporter.kt index 0a2ef159..bc64d4f5 100644 --- a/core/data/src/main/java/com/rtbishop/look4sat/core/data/aprs/AprsReporter.kt +++ b/core/data/src/main/java/com/rtbishop/look4sat/core/data/aprs/AprsReporter.kt @@ -91,7 +91,7 @@ class AprsReporter( port = cfg.port, callsign = cfg.callsign, ssid = cfg.ssid, - passcode = cfg.passcode.toIntOrNull() ?: AprsPacket.passcode(cfg.callsign), + passcode = cfg.passcode.toIntOrNull()?.takeIf { it >= 0 } ?: AprsPacket.passcode(cfg.callsign), version = "Look4Sat 4.5.4" ).also { client = it } if (!c.isConnected) c.connect() diff --git a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/AprsCard.kt b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/AprsCard.kt index f9b6b4f1..ed5e91f0 100644 --- a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/AprsCard.kt +++ b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/AprsCard.kt @@ -69,7 +69,7 @@ fun AprsCard() { val intent = Intent() .setClassName(context.packageName, AprsStore.SERVICE_CLASS) .setAction(if (enabled) AprsStore.ACTION_START else AprsStore.ACTION_STOP) - context.startService(intent) + if (enabled) context.startForegroundService(intent) else context.startService(intent) } // 简洁信息行(不挤) Text( @@ -87,7 +87,7 @@ fun AprsCard() { val intent = Intent() .setClassName(context.packageName, AprsStore.SERVICE_CLASS) .setAction(AprsStore.ACTION_REPORT_NOW) - context.startService(intent) + context.startForegroundService(intent) }, text = stringResource(id = R.string.prefs_aprs_report_now), modifier = Modifier.fillMaxWidth() @@ -107,7 +107,7 @@ fun AprsCard() { Intent().setClassName(context.packageName, AprsStore.SERVICE_CLASS) .setAction(AprsStore.ACTION_STOP) ) - context.startService( + context.startForegroundService( Intent().setClassName(context.packageName, AprsStore.SERVICE_CLASS) .setAction(AprsStore.ACTION_START) )