Drop SSID display from settings, connection pill shows generic "Connected"
Real hardware testing (Pixel 10a) showed NetworkCapabilities.getTransportInfo() consistently returns a redacted WifiInfo (SSID "<unknown ssid>", masked BSSID) even for the app's own self-requested WifiNetworkSpecifier network, disproving this codebase's prior assumption of a self-request exemption from ACCESS_FINE_LOCATION for that API path (confirmed via native diagnostic logging cross-checked against `adb shell dumpsys wifi`, which does show and correctly attribute the true SSID at the OS level). Rather than add a location permission with a runtime prompt purely for this cosmetic display, the settings pill now just shows "Connected". Documented as decision 4.24.
This commit is contained in:
@@ -164,6 +164,7 @@ Enthält u. a.:
|
|||||||
| 4.21 | **Protokoll-Parsing in eigenem Isolate (Flutter-Ziel)** | Verhindert UI-Ruckeln bei hoher Telemetrie-Rate; Isolates kommunizieren nur über Message-Passing, kein Shared Memory |
|
| 4.21 | **Protokoll-Parsing in eigenem Isolate (Flutter-Ziel)** | Verhindert UI-Ruckeln bei hoher Telemetrie-Rate; Isolates kommunizieren nur über Message-Passing, kein Shared Memory |
|
||||||
| 4.22 | **Mission-Domain-Layer + Protokoll-Adapter als eigenständiges reines Dart-Package (Flutter-Ziel)** | Isoliert unit-testbar ohne Emulator; wiederverwendbar für z. B. CLI-Tools oder Backend-Simulatoren |
|
| 4.22 | **Mission-Domain-Layer + Protokoll-Adapter als eigenständiges reines Dart-Package (Flutter-Ziel)** | Isoliert unit-testbar ohne Emulator; wiederverwendbar für z. B. CLI-Tools oder Backend-Simulatoren |
|
||||||
| 4.23 | **`go_router` für Navigation (Flutter-Ziel)** | Typisierte Übergänge, passend zum expliziten Mode-Wechsel-Trigger der State-Machine |
|
| 4.23 | **`go_router` für Navigation (Flutter-Ziel)** | Typisierte Übergänge, passend zum expliziten Mode-Wechsel-Trigger der State-Machine |
|
||||||
|
| 4.24 | **SSID-Anzeige in den Settings aufgegeben, Verbindungspille zeigt nur generisches "Connected"** | Auf echter Hardware (Pixel-Gerät, Android 16) liefert `NetworkCapabilities.getTransportInfo()` konsequent ein redigiertes `WifiInfo` (SSID `<unknown ssid>`, BSSID maskiert) — bestätigt per natives `Log.d` in `MlrsNetworkPlugin.onAvailable()`/`onCapabilitiesChanged()`, gegengeprüft mit `adb shell dumpsys wifi` (Shell-Kontext kennt und ordnet die echte SSID korrekt der App zu, das App-API liefert sie aber nicht). Die im Code angenommene "Ausnahme für selbst angefragte `WifiNetworkSpecifier`-Netze ohne `ACCESS_FINE_LOCATION`" gilt offenbar nur für `WifiManager.getConnectionInfo()`, nicht für diesen `NetworkCapabilities`-Weg über `ConnectivityManager.NetworkCallback`. Statt `ACCESS_FINE_LOCATION` (inkl. Laufzeit-Prompt) nur für diese kosmetische Anzeige hinzuzufügen, hat der Nutzer sich bewusst dagegen entschieden — die zugrundeliegende SSID-Merk-Logik (`UdpTransport.connectedSsid`/`_rememberSsid`, `preferredSsid` für stilles Reconnect) bleibt bestehen, liefert im Regelfall aber `null`/keinen Effekt |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -171,7 +171,8 @@ class MlrsNetworkPlugin(
|
|||||||
val linkProperties = connectivityManager.getLinkProperties(network)
|
val linkProperties = connectivityManager.getLinkProperties(network)
|
||||||
val gateway = gatewayAddressOf(linkProperties)
|
val gateway = gatewayAddressOf(linkProperties)
|
||||||
val broadcast = broadcastAddressOf(linkProperties)
|
val broadcast = broadcastAddressOf(linkProperties)
|
||||||
val ssid = ssidOf(connectivityManager.getNetworkCapabilities(network))
|
val capabilities = connectivityManager.getNetworkCapabilities(network)
|
||||||
|
val ssid = ssidOf(capabilities)
|
||||||
if (ssid != null) reportedSsid = ssid
|
if (ssid != null) reportedSsid = ssid
|
||||||
eventSink?.success(
|
eventSink?.success(
|
||||||
mapOf(
|
mapOf(
|
||||||
@@ -260,10 +261,21 @@ class MlrsNetworkPlugin(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ermittelt die tatsaechliche SSID des verbundenen Netzes. Erfordert
|
* Ermittelt die tatsaechliche SSID des verbundenen Netzes - liefert auf
|
||||||
* normalerweise ACCESS_FINE_LOCATION, ausser fuer die anfragende App
|
* echter Hardware (getestet: Pixel-Geraet, Android 16) zuverlaessig
|
||||||
* selbst bei einem ueber WifiNetworkSpecifier bewilligten Netz - genau
|
* `null`, da `NetworkCapabilities.getTransportInfo()` ohne
|
||||||
* unser Fall, siehe `WifiInfo.getSSID()`-Dokumentation.
|
* ACCESS_FINE_LOCATION konsequent ein redigiertes `WifiInfo` liefert
|
||||||
|
* (SSID `<unknown ssid>`, BSSID maskiert), auch fuer ein selbst per
|
||||||
|
* WifiNetworkSpecifier angefragtes/bewilligtes Netz. Mit
|
||||||
|
* `dumpsys wifi` (Shell-Kontext, volle Rechte) bestaetigt: das System
|
||||||
|
* kennt die echte SSID und ordnet sie korrekt dieser App zu
|
||||||
|
* (`Requesting package name`) - die dokumentierte Ausnahme "kein
|
||||||
|
* ACCESS_FINE_LOCATION noetig fuer selbst angefragte Netze" gilt in der
|
||||||
|
* Praxis offenbar nur fuer `WifiManager.getConnectionInfo()`, nicht fuer
|
||||||
|
* diesen `NetworkCapabilities`-Weg ueber `ConnectivityManager.
|
||||||
|
* NetworkCallback`. ACCESS_FINE_LOCATION bewusst NICHT hinzugefuegt nur
|
||||||
|
* fuer diese kosmetische Anzeige (Nutzerentscheidung) - der Aufrufer
|
||||||
|
* (UdpTransport) behandelt ein dauerhaftes `null` hier als Normalfall.
|
||||||
*/
|
*/
|
||||||
private fun ssidOf(capabilities: NetworkCapabilities?): String? {
|
private fun ssidOf(capabilities: NetworkCapabilities?): String? {
|
||||||
val wifiInfo = capabilities?.transportInfo as? WifiInfo ?: return null
|
val wifiInfo = capabilities?.transportInfo as? WifiInfo ?: return null
|
||||||
|
|||||||
@@ -35,15 +35,6 @@ final wifiLinkErrorReasonProvider = Provider<LinkErrorReason?>((ref) {
|
|||||||
return ref.watch(wifiTransportProvider).lastErrorReason;
|
return ref.watch(wifiTransportProvider).lastErrorReason;
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Reaktive tatsaechliche SSID des verbundenen Netzes (Doku: "connected
|
|
||||||
/// pille soll den WiFi-Namen anzeigen") - eigener Stream statt Ableitung aus
|
|
||||||
/// [wifiLinkStateProvider], weil Android die SSID fuer WifiNetworkSpecifier-
|
|
||||||
/// Netze oft erst nachtraeglich liefert (siehe UdpTransport.connectedSsidChanges/
|
|
||||||
/// MlrsNetworkPlugin.kt), also ohne begleitenden LinkState-Wechsel.
|
|
||||||
final wifiConnectedSsidProvider = StreamProvider<String?>((ref) {
|
|
||||||
final transport = ref.watch(wifiTransportProvider);
|
|
||||||
return transport.connectedSsidChanges;
|
|
||||||
});
|
|
||||||
|
|
||||||
/// Zeigt an, ob gerade UDP-Pakete ankommen ("receiving"/"not receiving"),
|
/// Zeigt an, ob gerade UDP-Pakete ankommen ("receiving"/"not receiving"),
|
||||||
/// unabhaengig vom (binaeren) Verbindungszustand - der Socket kann offen
|
/// unabhaengig vom (binaeren) Verbindungszustand - der Socket kann offen
|
||||||
|
|||||||
@@ -136,7 +136,6 @@ class _WifiPanel extends ConsumerWidget {
|
|||||||
final connectionSettings = ref.watch(connectionSettingsProvider).value;
|
final connectionSettings = ref.watch(connectionSettingsProvider).value;
|
||||||
final log = ref.watch(wifiConnectionLogProvider);
|
final log = ref.watch(wifiConnectionLogProvider);
|
||||||
final packetCount = ref.watch(wifiPacketCountProvider);
|
final packetCount = ref.watch(wifiPacketCountProvider);
|
||||||
final connectedSsid = ref.watch(wifiConnectedSsidProvider).value;
|
|
||||||
|
|
||||||
// telemetryProvider loest selbst keinen Verbindungsversuch aus, solange
|
// telemetryProvider loest selbst keinen Verbindungsversuch aus, solange
|
||||||
// WLAN/MSP noch nicht ueber den "Connect"-Knopf verbunden ist (siehe
|
// WLAN/MSP noch nicht ueber den "Connect"-Knopf verbunden ist (siehe
|
||||||
@@ -175,7 +174,14 @@ class _WifiPanel extends ConsumerWidget {
|
|||||||
const Spacer(),
|
const Spacer(),
|
||||||
_StreamActivityPill(isReceiving: isReceiving, packetCount: packetCount),
|
_StreamActivityPill(isReceiving: isReceiving, packetCount: packetCount),
|
||||||
const SizedBox(width: 6),
|
const SizedBox(width: 6),
|
||||||
_StatePill(state: linkState, connectedLabel: connectedSsid ?? 'unknown'),
|
// Zeigt bewusst nur "Connected" statt "Connected to $ssid" (Doku
|
||||||
|
// Abschnitt 4: "SSID-Anzeige in den Settings aufgegeben") -
|
||||||
|
// NetworkCapabilities.getTransportInfo() liefert auf echter
|
||||||
|
// Hardware konsequent nur die redigierte SSID/BSSID
|
||||||
|
// ("<unknown ssid>"), siehe MlrsNetworkPlugin.ssidOf()-Doku fuer
|
||||||
|
// Details. Bewusst keine ACCESS_FINE_LOCATION-Berechtigung nur
|
||||||
|
// fuer diese kosmetische Anzeige hinzugefuegt.
|
||||||
|
_StatePill(state: linkState),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (errorReason != null) ...[
|
if (errorReason != null) ...[
|
||||||
@@ -385,22 +391,14 @@ class _StreamActivityPill extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _StatePill extends StatelessWidget {
|
class _StatePill extends StatelessWidget {
|
||||||
const _StatePill({required this.state, this.connectedLabel});
|
const _StatePill({required this.state});
|
||||||
|
|
||||||
final LinkState? state;
|
final LinkState? state;
|
||||||
|
|
||||||
/// WLAN-Netzname, falls bekannt - erscheint im verbundenen Zustand als
|
|
||||||
/// "Connected to {name}" statt des generischen "Connected" (Doku: "die
|
|
||||||
/// connected pille soll den WiFi-Namen anzeigen").
|
|
||||||
final String? connectedLabel;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final (label, color) = switch (state) {
|
final (label, color) = switch (state) {
|
||||||
LinkState.connected => (
|
LinkState.connected => ('Connected', DmcColors.liveGreen),
|
||||||
connectedLabel != null ? 'Connected to $connectedLabel' : 'Connected',
|
|
||||||
DmcColors.liveGreen,
|
|
||||||
),
|
|
||||||
LinkState.connecting => ('Connecting…', DmcColors.pafAmber),
|
LinkState.connecting => ('Connecting…', DmcColors.pafAmber),
|
||||||
LinkState.error => ('Error', DmcColors.warnRed),
|
LinkState.error => ('Error', DmcColors.warnRed),
|
||||||
LinkState.disconnected || null => ('Disconnected', Colors.grey),
|
LinkState.disconnected || null => ('Disconnected', Colors.grey),
|
||||||
|
|||||||
Reference in New Issue
Block a user