Browse Source
添加 NativeLocalizationSync 服务,用于将Flutter应用的本地化字符串同步到Android原生前台服务通知中。在应用启动、语言切换和应用生命周期恢复时自动同步,确保原生通知内容与当前应用语言保持一致。 主要修改: 1. 新增 native_localization_sync.dart 服务,通过MethodChannel将本地化字符串传递给Android原生 2. 在MainApp、SettingsController和AppLifecycleManager中添加同步调用 3. 更新所有Android前台服务(音频录制、BLE代理、QQ音乐、导航、音乐服务)以使用同步的本地化字符串 4. 添加中英文通知文本到翻译文件 5. 在MainActivity中实现原生端字符串接收和存储逻辑weicu
12 changed files with 289 additions and 17 deletions
@ -0,0 +1,87 @@ |
|||||
|
import 'dart:io'; |
||||
|
import 'dart:ui'; |
||||
|
import 'package:flutter/services.dart'; |
||||
|
import 'package:get/get.dart'; |
||||
|
import '../translations/app_translations.dart'; |
||||
|
|
||||
|
class NativeLocalizationSync { |
||||
|
static const MethodChannel _channel = |
||||
|
MethodChannel('com.saitong.voitrans/native_localization'); |
||||
|
|
||||
|
static const List<String> nativeKeys = <String>[ |
||||
|
'native.notification.appName', |
||||
|
'native.notification.navigation.title', |
||||
|
'native.notification.navigation.keepRunning', |
||||
|
'native.notification.bleAgent.running', |
||||
|
'native.notification.audioRecording.recording', |
||||
|
'native.notification.music.waiting', |
||||
|
'native.notification.music.previous', |
||||
|
'native.notification.music.next', |
||||
|
'native.notification.music.play', |
||||
|
'native.notification.music.pause', |
||||
|
'native.notification.qqMusic.playing', |
||||
|
'unknownSong', |
||||
|
'unknownArtist', |
||||
|
]; |
||||
|
|
||||
|
static String? _lastLocaleKey; |
||||
|
static int? _lastPayloadHash; |
||||
|
static bool _isSyncing = false; |
||||
|
|
||||
|
static Future<void> syncToNative({bool force = false}) async { |
||||
|
if (!Platform.isAndroid) return; |
||||
|
if (_isSyncing) return; |
||||
|
|
||||
|
final Locale locale = Get.locale ?? |
||||
|
AppTranslations.deviceLocale() ?? |
||||
|
AppTranslations.fallbackLocale; |
||||
|
final String localeKey = _toAppTranslationsLocaleKey(locale); |
||||
|
|
||||
|
final Map<String, String> payload = _buildPayload(localeKey); |
||||
|
final int payloadHash = Object.hashAll( |
||||
|
payload.entries.map((e) => Object.hash(e.key, e.value)), |
||||
|
); |
||||
|
|
||||
|
if (!force && |
||||
|
_lastLocaleKey == localeKey && |
||||
|
_lastPayloadHash == payloadHash) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
_isSyncing = true; |
||||
|
try { |
||||
|
await _channel.invokeMethod('updateNativeStrings', <String, dynamic>{ |
||||
|
'locale': localeKey, |
||||
|
'strings': payload, |
||||
|
}); |
||||
|
_lastLocaleKey = localeKey; |
||||
|
_lastPayloadHash = payloadHash; |
||||
|
} finally { |
||||
|
_isSyncing = false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
static Map<String, String> _buildPayload(String localeKey) { |
||||
|
final Map<String, Map<String, String>> all = AppTranslations().keys; |
||||
|
final Map<String, String>? current = all[localeKey]; |
||||
|
final Map<String, String>? fallback = |
||||
|
all['en_US'] ?? all[AppTranslations.fallbackLocale.toString()]; |
||||
|
|
||||
|
final Map<String, String> result = <String, String>{}; |
||||
|
for (final String key in nativeKeys) { |
||||
|
final String? value = current?[key] ?? fallback?[key]; |
||||
|
if (value == null || value.isEmpty) continue; |
||||
|
result[key] = value; |
||||
|
} |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
static String _toAppTranslationsLocaleKey(Locale locale) { |
||||
|
final String language = locale.languageCode; |
||||
|
final String? country = locale.countryCode; |
||||
|
if (country == null || country.isEmpty) { |
||||
|
return language.toLowerCase(); |
||||
|
} |
||||
|
return '${language.toLowerCase()}_${country.toUpperCase()}'; |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue