From 40df5f0f0028e4547db82818ee585302e4da259b Mon Sep 17 00:00:00 2001 From: lxm <1274844347@qq.com> Date: Thu, 5 Feb 2026 20:24:04 +0800 Subject: [PATCH] =?UTF-8?q?feat(i18n):=20=E6=B7=BB=E5=8A=A0=E5=AE=89?= =?UTF-8?q?=E5=8D=93=E5=89=8D=E5=8F=B0=E6=9C=8D=E5=8A=A1=E9=80=9A=E7=9F=A5?= =?UTF-8?q?=E7=9A=84=E5=A4=9A=E8=AF=AD=E8=A8=80=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 为支持安卓前台服务的通知本地化,在多个语言文件中新增翻译键值。 同时在对应的安卓服务文件中添加注释,说明前台通知的触发条件。 --- lib/core/translations/language/ar_sa.dart | 15 ++++++++++ lib/core/translations/language/de_de.dart | 15 ++++++++++ lib/core/translations/language/fr_fr.dart | 16 ++++++++++ lib/core/translations/language/ja_jp.dart | 30 +++++++++++++++---- lib/core/translations/language/ko_kr.dart | 15 ++++++++++ lib/core/translations/language/ru_ru.dart | 15 ++++++++++ lib/core/translations/language/zh_hk.dart | 13 ++++++++ lib/core/translations/language/zh_tw.dart | 13 ++++++++ .../agent_service/BleMediaService.kt | 4 +++ .../amap_service/NavigationService.kt | 7 +++++ .../tools/AudioRecordingForegroundService.kt | 4 +++ .../music_service/MusicService.kt | 5 ++++ 12 files changed, 146 insertions(+), 6 deletions(-) diff --git a/lib/core/translations/language/ar_sa.dart b/lib/core/translations/language/ar_sa.dart index cadfa48dc..4699dee38 100644 --- a/lib/core/translations/language/ar_sa.dart +++ b/lib/core/translations/language/ar_sa.dart @@ -1064,6 +1064,21 @@ const Map arSA = { 'storagePermissionPermanentDenial': 'تم اكتشاف أنك رفضت إذن التخزين بشكل دائم. للمتابعة في استخدام هذه الميزة، يرجى الانتقال إلى إعدادات التطبيق لتمكين إذن التخزين يدويًا.', + // 原生前台服务通知(Android) + 'native.notification.appName': 'VOITRANS', // VOITRANS + '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': 'يتم تشغيل الموسيقى', // 正在播放音乐 + //permission_util.dart 'permissionUtilNeed': 'يحتاج ', 'permissionUtilPermission': ' إذن', diff --git a/lib/core/translations/language/de_de.dart b/lib/core/translations/language/de_de.dart index 309b3b72b..dabb17783 100644 --- a/lib/core/translations/language/de_de.dart +++ b/lib/core/translations/language/de_de.dart @@ -1101,6 +1101,21 @@ const Map deDE = { 'storagePermissionPermanentDenial': 'Speicherberechtigung wurde dauerhaft verweigert. Um diese Funktion weiterhin nutzen zu können, gehen Sie bitte zu den App-Einstellungen, um die Speicherberechtigung manuell zu aktivieren.', + // 原生前台服务通知(Android) + 'native.notification.appName': 'VOITRANS', // VOITRANS + 'native.notification.navigation.title': 'Navigation läuft', // 导航进行中 + 'native.notification.navigation.keepRunning': + 'Navigation läuft, App geöffnet lassen', // 正在导航中,请保持应用运行 + 'native.notification.bleAgent.running': 'Sprachassistent läuft', // 语音助手正在运行 + 'native.notification.audioRecording.recording': + 'Audioaufnahme läuft, tippen um zur App zurückzukehren', // 正在录音,点击返回应用 + 'native.notification.music.waiting': 'Warte auf Wiedergabe', // 等待播放 + 'native.notification.music.previous': 'Vorheriger Titel', // 上一首 + 'native.notification.music.next': 'Nächster Titel', // 下一首 + 'native.notification.music.play': 'Wiedergabe', // 播放 + 'native.notification.music.pause': 'Pause', // 暂停 + 'native.notification.qqMusic.playing': 'Musik wird wiedergegeben', // 正在播放音乐 + //permission_util.dart 'permissionUtilNeed': 'Benötige ', 'permissionUtilPermission': ' Berechtigung', diff --git a/lib/core/translations/language/fr_fr.dart b/lib/core/translations/language/fr_fr.dart index a1eda3df3..b6a26d25f 100644 --- a/lib/core/translations/language/fr_fr.dart +++ b/lib/core/translations/language/fr_fr.dart @@ -1088,6 +1088,22 @@ const Map frFR = { 'storagePermissionPermanentDenial': 'Storage permission has been permanently denied. To continue using this feature, please go to app settings to manually enable storage permission.', + // 原生前台服务通知(Android) + 'native.notification.appName': 'VOITRANS', // VOITRANS + 'native.notification.navigation.title': 'Navigation en cours', // 导航进行中 + 'native.notification.navigation.keepRunning': + 'Navigation en cours, gardez l’application active', // 正在导航中,请保持应用运行 + 'native.notification.bleAgent.running': + 'Assistant vocal en cours d’exécution', // 语音助手正在运行 + 'native.notification.audioRecording.recording': + 'Enregistrement audio, appuyez pour revenir à l’application', // 正在录音,点击返回应用 + 'native.notification.music.waiting': 'En attente de lecture', // 等待播放 + 'native.notification.music.previous': 'Précédent', // 上一首 + 'native.notification.music.next': 'Suivant', // 下一首 + 'native.notification.music.play': 'Lecture', // 播放 + 'native.notification.music.pause': 'Pause', // 暂停 + 'native.notification.qqMusic.playing': 'Musique en cours de lecture', // 正在播放音乐 + //permission_util.dart 'permissionUtilNeed': 'Need ', 'permissionUtilPermission': ' Permission', diff --git a/lib/core/translations/language/ja_jp.dart b/lib/core/translations/language/ja_jp.dart index d34d1fe17..ea62a1e32 100644 --- a/lib/core/translations/language/ja_jp.dart +++ b/lib/core/translations/language/ja_jp.dart @@ -439,11 +439,15 @@ const Map jaJP = { 'meetingRecordStopFailed': '録音を停止できませんでした。もう一度お試しください。', // 结束录音失败,请重试 'meetingRecordSaveFailed': '録音を保存できませんでした。もう一度お試しください。', // 保存录音失败,请重试 'meetingRecordRecordingNotificationTitle': '録音中', // 录音进行中 - 'meetingRecordRecordingNotificationBody': 'バックグラウンドで録音しています。タップしてアプリに戻ります。', // 正在后台录音,点击返回应用 + 'meetingRecordRecordingNotificationBody': + 'バックグラウンドで録音しています。タップしてアプリに戻ります。', // 正在后台录音,点击返回应用 'overlayPermissionTitle': '他のアプリの上に表示', // 悬浮窗权限 - 'overlayPermissionTranslationDesc': '通話中または音声/動画翻訳中に翻訳結果を表示するため、他のアプリの上に表示する権限が必要です。これにより、他のアプリを使用中でもリアルタイム翻訳を確認できます。', // 为了在通话或音视频翻译时显示翻译结果,需要悬浮窗权限。这样您就可以在使用其他应用时看到实时翻译。 - 'overlayPermissionRecordingDesc': '録音中に録音フローティングバー(タイマー/一時停止/再開)を表示するため、他のアプリの上に表示する権限が必要です。', // 为了在录音过程中显示录音悬浮条(计时/暂停/继续),需要悬浮窗权限。 - 'overlayPermissionOpenSettingsFailed': 'システム設定を自動で開けませんでした。設定を開き、手動で「他のアプリの上に表示」を有効にしてください。', // 无法自动跳转到系统设置,请手动前往系统设置开启悬浮窗权限。 + 'overlayPermissionTranslationDesc': + '通話中または音声/動画翻訳中に翻訳結果を表示するため、他のアプリの上に表示する権限が必要です。これにより、他のアプリを使用中でもリアルタイム翻訳を確認できます。', // 为了在通话或音视频翻译时显示翻译结果,需要悬浮窗权限。这样您就可以在使用其他应用时看到实时翻译。 + 'overlayPermissionRecordingDesc': + '録音中に録音フローティングバー(タイマー/一時停止/再開)を表示するため、他のアプリの上に表示する権限が必要です。', // 为了在录音过程中显示录音悬浮条(计时/暂停/继续),需要悬浮窗权限。 + 'overlayPermissionOpenSettingsFailed': + 'システム設定を自動で開けませんでした。設定を開き、手動で「他のアプリの上に表示」を有効にしてください。', // 无法自动跳转到系统设置,请手动前往系统设置开启悬浮窗权限。 'transcribing': 'Transcribing...', 'summarizing': 'Summarizing...', 'analyzing': 'Analyzing...', @@ -618,8 +622,7 @@ const Map jaJP = { // Meeting模块 - 发言者相关 'applyToAllParagraphs': 'この話者のすべての段落に適用', - 'summaryWillBeUpdatedAutomatically': - '要約はテンプレートに基づいて自動的に更新されます', + 'summaryWillBeUpdatedAutomatically': '要約はテンプレートに基づいて自動的に更新されます', 'nameCurrentSpeaker': 'Name Current Speaker', 'recentlyUsedNames': 'Recently Used Names', 'applyToCurrentParagraph': 'Apply to Current Paragraph', @@ -1032,6 +1035,21 @@ const Map jaJP = { 'storagePermissionPermanentDenial': 'Storage permission has been permanently denied. To continue using this feature, please go to app settings to manually enable storage permission.', + // 原生前台服务通知(Android) + 'native.notification.appName': 'VOITRANS', // VOITRANS + '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': '音楽を再生中', // 正在播放音乐 + //permission_util.dart 'permissionUtilNeed': 'Need ', 'permissionUtilPermission': ' Permission', diff --git a/lib/core/translations/language/ko_kr.dart b/lib/core/translations/language/ko_kr.dart index 82c25d615..3b2dd7431 100644 --- a/lib/core/translations/language/ko_kr.dart +++ b/lib/core/translations/language/ko_kr.dart @@ -1027,6 +1027,21 @@ const Map koKR = { 'storagePermissionPermanentDenial': 'Storage permission has been permanently denied. To continue using this feature, please go to app settings to manually enable storage permission.', + // 原生前台服务通知(Android) + 'native.notification.appName': 'VOITRANS', // VOITRANS + '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': '음악 재생 중', // 正在播放音乐 + //permission_util.dart 'permissionUtilNeed': 'Need ', 'permissionUtilPermission': ' Permission', diff --git a/lib/core/translations/language/ru_ru.dart b/lib/core/translations/language/ru_ru.dart index eccc6e122..13b6be6c8 100644 --- a/lib/core/translations/language/ru_ru.dart +++ b/lib/core/translations/language/ru_ru.dart @@ -1093,6 +1093,21 @@ const Map ruRU = { 'storagePermissionPermanentDenial': '检测到您已永久拒绝存储权限。如需继续使用此功能,请前往应用设置中手动开启存储权限。', + // 原生前台服务通知(Android) + 'native.notification.appName': 'VOITRANS', // VOITRANS + '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': 'Воспроизведение музыки', // 正在播放音乐 + //permission_util.dart 'permissionUtilNeed': 'Need ', 'permissionUtilPermission': ' Permission', diff --git a/lib/core/translations/language/zh_hk.dart b/lib/core/translations/language/zh_hk.dart index 3629577cf..e56869de0 100644 --- a/lib/core/translations/language/zh_hk.dart +++ b/lib/core/translations/language/zh_hk.dart @@ -980,6 +980,19 @@ const Map zhHK = { 'storagePermissionPermanentDenial': '檢測到您已永久拒絕儲存權限。如需繼續使用此功能,請前往應用設定中手動開啟儲存權限。', + // 原生前台服务通知(Android) + 'native.notification.appName': 'VOITRANS', + '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': '正在播放音樂', + //permission_util.dart 'permissionUtilNeed': '需要', 'permissionUtilPermission': '權限', diff --git a/lib/core/translations/language/zh_tw.dart b/lib/core/translations/language/zh_tw.dart index 47967b8ab..27d0afa85 100644 --- a/lib/core/translations/language/zh_tw.dart +++ b/lib/core/translations/language/zh_tw.dart @@ -980,6 +980,19 @@ const Map zhTW = { 'storagePermissionPermanentDenial': '檢測到您已永久拒絕儲存權限。如需繼續使用此功能,請前往應用設定中手動開啟儲存權限。', + // 原生前台服务通知(Android) + 'native.notification.appName': 'VOITRANS', + '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': '正在播放音樂', + //permission_util.dart 'permissionUtilNeed': '需要', 'permissionUtilPermission': '權限', diff --git a/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/BleMediaService.kt b/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/BleMediaService.kt index 2e9c91893..d2111244b 100644 --- a/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/BleMediaService.kt +++ b/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/BleMediaService.kt @@ -415,6 +415,10 @@ private var companionManager: BleCompanionManager? = null // 设置服务状态 isRunning.set(true) + // 前台通知显示条件: + // - 只要 BleMediaService 被启动(Flutter 调用 AgentService.startAgentService),onCreate 会立刻执行 startForeground(); + // - 渠道使用 IMPORTANCE_LOW,通常不会弹出“抬头横幅(Heads-up)”,但会在下拉通知栏里显示常驻通知; + // - Flutter 侧常见入口:PairingController 跳过配对时会调用 BleManager.startAgentService()。 startForeground(NOTIFICATION_ID, createNotification()) // 初始化BLE伴侣设备管理器 - 使用单例模式获取实例 companionManager = BleCompanionManager.getInstance(this) diff --git a/local_plugins/amap_service/android/src/main/kotlin/com/yunqiinnovation/amap_service/NavigationService.kt b/local_plugins/amap_service/android/src/main/kotlin/com/yunqiinnovation/amap_service/NavigationService.kt index 6ec4d9e2e..d6490ac9e 100644 --- a/local_plugins/amap_service/android/src/main/kotlin/com/yunqiinnovation/amap_service/NavigationService.kt +++ b/local_plugins/amap_service/android/src/main/kotlin/com/yunqiinnovation/amap_service/NavigationService.kt @@ -61,6 +61,11 @@ class NavigationService: Service(),AMapNaviListener { override fun onCreate() { super.onCreate() instance = this + // 前台通知显示条件: + // - 只要该 Service 被启动(ContextCompat.startForegroundService / startForegroundService),onCreate 就会立刻调用 startForeground(); + // - 通知渠道使用 IMPORTANCE_LOW,通常不会弹出“抬头横幅(Heads-up)”,但会在下拉通知栏里出现常驻通知; + // - Flutter 侧需要调用插件 com.yunqiinnovation.amap_service 的 "start"(会走 NavigationServiceHelper.startNavigation -> 启动该 Service), + // 调用 "open" 只会打开导航页面,不会启动该前台服务,因此不会有通知。 startForegroundNotification() // 注册广播监听器 @@ -150,6 +155,8 @@ class NavigationService: Service(),AMapNaviListener { .setOngoing(true) .build() + // 触发系统显示“前台服务常驻通知”的关键点:startForeground() + // 如果 Android 13+ 未授予通知权限 / 用户关闭了该渠道通知,可能导致通知不可见或启动前台服务失败(不同 ROM 行为可能不同)。 startForeground(NOTIFICATION_ID, notification) } diff --git a/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/tools/AudioRecordingForegroundService.kt b/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/tools/AudioRecordingForegroundService.kt index 77f3fbacb..46b9957a8 100644 --- a/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/tools/AudioRecordingForegroundService.kt +++ b/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/tools/AudioRecordingForegroundService.kt @@ -65,6 +65,10 @@ class AudioRecordingForegroundService : Service() { // 创建前台通知 val notification = createNotification() + // 前台通知显示条件: + // - 只要该 Service 被启动(AzureSpeechPlugin/AzureAsrHelper 在 enableRecord 时会启动它),就会在 onStartCommand 里立刻调用 startForeground(); + // - 渠道为 IMPORTANCE_LOW,通常不会弹出“抬头横幅(Heads-up)”,但会在下拉通知栏显示常驻通知; + // - Android 13+ 如果未授予通知权限 / 用户关闭通知,可能出现通知不可见或启动前台服务失败(不同 ROM 行为可能不同)。 // 必须立即调用 startForeground 以满足 Android 8.0+ 的要求 startForeground(NOTIFICATION_ID, notification) diff --git a/local_plugins/music_service/android/src/main/kotlin/com/yunqiinnovation/music_service/MusicService.kt b/local_plugins/music_service/android/src/main/kotlin/com/yunqiinnovation/music_service/MusicService.kt index d1dad6aaa..dc57b1917 100644 --- a/local_plugins/music_service/android/src/main/kotlin/com/yunqiinnovation/music_service/MusicService.kt +++ b/local_plugins/music_service/android/src/main/kotlin/com/yunqiinnovation/music_service/MusicService.kt @@ -154,6 +154,11 @@ class MusicService : MediaBrowserServiceCompat() { setupMediaSession() val waitingTitle = getNativeLocalizedString("native.notification.music.waiting", "等待播放") val appName = getNativeLocalizedString("native.notification.appName", "Voitrans") + // 前台通知显示条件: + // - 只要 MusicService 被启动(Flutter 调用 com.yunqiinnovation.music_service 的 play/playlist 等会启动该服务), + // onCreate 会立刻调用 startForeground(),因此下拉通知栏会出现常驻通知(哪怕还没真正开始播放); + // - 渠道为 IMPORTANCE_LOW,通常不会弹出“抬头横幅(Heads-up)”,但会在通知栏里常驻; + // - stop/close 会在 completeStop() 里 stopForeground(true)+stopSelf(),通知随之消失。 startForeground(NOTIFICATION_ID, createNotification(waitingTitle, appName, "")) audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager