Files
emergency/lib/services/country_code_sources/sim_country_code_source.dart
T
rootandClaude Sonnet 5 e3aa088bc2 Notrufnummern-Datenbasis, Ländererkennung, State-Management und Lokalisierung (AP1-AP7)
Implementiert den kompletten Kern-Flow der Emergency App gemäß docs/plan.md:
- Notrufnummern-Datenbasis für 199 Länder + Modelle/Repository (AP1)
- DialerService für tel:-Notrufe ohne Auto-Dial (AP2)
- Statisches UI mit Panik-Button-Fallback (AP3)
- Priorisierte Ländererkennung: SIM/Netz -> GPS/Geocoding -> Cache (AP4)
- EmergencyProvider verdrahtet Repository/LocationService mit der UI (AP5)
- Manuelle Länderauswahl als Fallback samt eigener Priorität (AP6)
- UI-Lokalisierung (de/en/fr/es), an erkanntes Land gekoppelt (AP7)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-24 11:29:38 +02:00

86 lines
3.1 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:carrier_info/carrier_info.dart';
import 'package:flutter/foundation.dart';
import 'country_code_source.dart';
/// Ermittelt den ISO-Ländercode aus SIM-/Netzwerk-Informationen via
/// `carrier_info` (`docs/plan.md`, Abschnitt 2 + 3: primäre, offline
/// verfügbare Quelle).
///
/// **Android:** Priorität liegt auf `networkCountryIso` des aktuell
/// eingebuchten Mobilfunknetzes (aus `telephonyInfo`) nicht auf dem
/// Heimatland der SIM. Genau dieses Netz wickelt einen Notruf ab, ändert
/// sich also korrekt bei Roaming (siehe Plan, Zeile "Bei Konflikt ...
/// gewinnt automatisch die SIM-Quelle"). Fällt zurück auf
/// `isoCountryCode` (SIM-Ausgabeland laut Telephony API) und zuletzt auf
/// `countryIso` aus `subscriptionsInfo`.
///
/// **iOS:** Apple hat `CTCarrier` ab iOS 16 deprecated (`docs/plan.md`,
/// Abschnitt 9 verbleibendes Risiko). `carrier_info` liefert auf iOS
/// 16+ für `isoCountryCode` verlässlich `null` zurück (siehe Paket-Doku
/// `iOS_16_DEPRECATION_NOTICE.md`). Das ist eine bekannte Plattform-
/// Einschränkung, kein Bug: Diese Quelle liefert dann einfach `null`,
/// wodurch `LocationService` automatisch auf GPS/Reverse-Geocoding
/// zurückfällt.
///
/// Alle Plugin-Aufrufe sind defensiv in try/catch gekapselt: Auf
/// Emulatoren, Geräten ohne SIM oder bei Plugin-Fehlern kann
/// `carrier_info` werfen oder leere/`null`-Werte liefern in jedem Fall
/// liefert [resolve] dann `null`, nie eine Exception.
class SimCountryCodeSource implements CountryCodeSource {
const SimCountryCodeSource();
@override
Future<String?> resolve() async {
try {
switch (defaultTargetPlatform) {
case TargetPlatform.android:
return await _resolveAndroid();
case TargetPlatform.iOS:
return await _resolveIos();
default:
// Kein Mobilfunk-Stack auf Desktop/Web-Zielen (auch wenn diese
// App laut Scope nur Android/iOS unterstützt, siehe Plan
// Abschnitt 7 defensiv trotzdem abgedeckt).
return null;
}
} catch (_) {
return null;
}
}
Future<String?> _resolveAndroid() async {
final info = await CarrierInfo.getAndroidInfo();
if (info == null) return null;
for (final telephony in info.telephonyInfo) {
final code = _normalize(telephony.networkCountryIso);
if (code != null) return code;
}
for (final telephony in info.telephonyInfo) {
final code = _normalize(telephony.isoCountryCode);
if (code != null) return code;
}
for (final subscription in info.subscriptionsInfo) {
final code = _normalize(subscription.countryIso);
if (code != null) return code;
}
return null;
}
Future<String?> _resolveIos() async {
final info = await CarrierInfo.getIosInfo();
for (final carrier in info.carrierData) {
final code = _normalize(carrier.isoCountryCode);
if (code != null) return code;
}
return null;
}
String? _normalize(String? code) {
final trimmed = code?.trim();
if (trimmed == null || trimmed.isEmpty) return null;
return trimmed.toUpperCase();
}
}