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.
This commit is contained in:
mckero committed 2026-08-05 02:50:40 +00:00
1 parent 88a8e795d1
commit 920af7bde2
4 files changed
+16 -10

No files matched your search

+2 -1
View File
@@ -50,6 +50,7 @@
<service
android:name="com.rtbishop.look4sat.app.AprsForegroundService"
android:exported="false" />
android:exported="false"
android:foregroundServiceType="dataSync" />
</application>
</manifest>
@@ -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()
}
}
@@ -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()
@@ -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)
)