diff --git a/local_plugins/native_plugin/.gitignore b/local_plugins/floating_ui_plugin/.gitignore similarity index 100% rename from local_plugins/native_plugin/.gitignore rename to local_plugins/floating_ui_plugin/.gitignore diff --git a/local_plugins/native_plugin/.metadata b/local_plugins/floating_ui_plugin/.metadata similarity index 100% rename from local_plugins/native_plugin/.metadata rename to local_plugins/floating_ui_plugin/.metadata diff --git a/local_plugins/native_plugin/CHANGELOG.md b/local_plugins/floating_ui_plugin/CHANGELOG.md similarity index 100% rename from local_plugins/native_plugin/CHANGELOG.md rename to local_plugins/floating_ui_plugin/CHANGELOG.md diff --git a/local_plugins/native_plugin/LICENSE b/local_plugins/floating_ui_plugin/LICENSE similarity index 100% rename from local_plugins/native_plugin/LICENSE rename to local_plugins/floating_ui_plugin/LICENSE diff --git a/local_plugins/floating_ui_plugin/README.md b/local_plugins/floating_ui_plugin/README.md new file mode 100644 index 000000000..369c2ee35 --- /dev/null +++ b/local_plugins/floating_ui_plugin/README.md @@ -0,0 +1,120 @@ +# floating_ui_plugin + +该目录是一个本地 Flutter 插件包,当前在项目中主要承担「悬浮 UI」相关的原生能力: + +- Android:翻译悬浮窗(系统悬浮窗 / overlay window)+ 录音悬浮条(计时/暂停/关闭)+ 悬浮窗权限检查/跳转。 +- iOS:为系统画中画(PiP)提供可渲染的原生内容 View,并支持动态更新翻译文本。 + +> 说明:Flutter 包名为 floating_ui_plugin(见本插件 pubspec.yaml),主工程通过 path 依赖引用本目录。 + +## 主要能力 + +### 1) Android 翻译悬浮窗(Translation Floating Window) + +- 通道:`MethodChannel('floating_window')` +- 原理:Flutter 调用通道方法 → Android 启动/更新 `FloatingWindowService` → service 通过系统 WindowManager 显示 overlay view。 +- 交互回传:service 会反向调用同一通道,把状态/点击/关闭事件回传给 Flutter。 + +支持的方法(Flutter → Android): +- `enableFloatingWindow`:启动悬浮窗服务(如果已在运行,相当于确保存在)。 +- `disableFloatingWindow`:停止悬浮窗服务。 +- `showFloatingWindow`:显示悬浮窗(当前实现等价于启动服务)。 +- `hideFloatingWindow`:隐藏悬浮窗(stopSelf)。 +- `updateContent(Map)`:更新展示内容。 +- `setPosition({x,y})`:设置悬浮窗位置。 + +回传的方法(Android → Flutter): +- `onFloatingWindowStateChanged({state})`:`hidden|minimized|expanded` +- `onFloatingWindowClosed()`:用户关闭。 +- `onFloatingWindowClicked()`:用户点击语言区域(service 内部会 bringAppToFront)。 + +数据协议(updateContent): +- `sourceText` / `translatedText` +- `sourceLanguage` / `targetLanguage` +- `timestamp`(毫秒时间戳) +- `isIntermediate`(是否中间态) + +对应实现: +- Android 插件入口:[NativePlugin.kt](file:///Users/liuxiamin/work/flutter_projects/deep_voice/local_plugins/floating_ui_plugin/android/src/main/kotlin/com/example/native_plugin/NativePlugin.kt) +- 悬浮窗服务:[FloatingWindowService.kt](file:///Users/liuxiamin/work/flutter_projects/deep_voice/local_plugins/floating_ui_plugin/android/src/main/kotlin/com/example/native_plugin/FloatingWindowService.kt) + +### 2) Android 悬浮窗权限(Overlay Permission) + +- 通道:`MethodChannel('overlay_permission')` +- 方法: + - `hasOverlayPermission`:是否具备 SYSTEM_ALERT_WINDOW + - `requestOverlayPermission`:跳转系统页面申请 + +对应实现:[NativePlugin.kt](file:///Users/liuxiamin/work/flutter_projects/deep_voice/local_plugins/floating_ui_plugin/android/src/main/kotlin/com/example/native_plugin/NativePlugin.kt) + +### 3) Android 录音悬浮条(Recording Floating Bar) + +- 通道:`MethodChannel('native_plugin')` +- 原理:Flutter 下发 show/update/hide → Android 启动/更新 `RecordingFloatingService` → service 以 overlay 方式显示一个小型悬浮条。 + +支持的方法(Flutter → Android): +- `showRecordingFloatingBar({duration, recordingType, isPaused})` +- `updateRecordingFloatingBar({duration, recordingType, isPaused})` +- `hideRecordingFloatingBar()` + +用户操作回传(Android → Flutter): +- 事件通道:`EventChannel('native_plugin/recording_floating_actions')` +- action 字符串: + - `togglePause`:点击暂停/继续 + - `openMeetingRecord`:点击中间区域,拉起 App 并打开录音页 + - `closeFloatingBar`:关闭悬浮条 + +对应实现: +- 服务:[RecordingFloatingService.kt](file:///Users/liuxiamin/work/flutter_projects/deep_voice/local_plugins/floating_ui_plugin/android/src/main/kotlin/com/example/native_plugin/RecordingFloatingService.kt) +- 事件桥接:[NativePlugin.emitRecordingFloatingAction](file:///Users/liuxiamin/work/flutter_projects/deep_voice/local_plugins/floating_ui_plugin/android/src/main/kotlin/com/example/native_plugin/NativePlugin.kt#L26-L39) + +## iOS:PiP 内容 View(Picture-in-Picture Content View) + +- 通道:`MethodChannel('native_plugin')` +- 目标:创建一个用于 PiP 渲染的原生 `UIView`(`PlayerView`),并支持后续更新显示内容。 + +支持的方法: +- `createPipContentView()`:返回一个 `viewId`(本质是 PlayerView 的指针值)。 +- `updatePipContentView({viewId?, lang, cn, en})`:更新内容。 +- `disposePipContentView(viewId)`:释放。 + +对应实现: +- 插件入口:[NativePlugin.swift](file:///Users/liuxiamin/work/flutter_projects/deep_voice/local_plugins/floating_ui_plugin/ios/Classes/NativePlugin.swift) +- 具体 UI:[PlayerView.swift](file:///Users/liuxiamin/work/flutter_projects/deep_voice/local_plugins/floating_ui_plugin/ios/Classes/PlayerView.swift) + +## 在主工程中的调用链路(现状) + +### Android:翻译悬浮窗 + +- 入口:翻译页控制器 [TranslationController](file:///Users/liuxiamin/work/flutter_projects/deep_voice/lib/modules/translation/controllers/translation_controller.dart) + - `toggleFloatingWindow()` → `_enableFloatingWindow()` +- 管理器:[FloatingWindowManager](file:///Users/liuxiamin/work/flutter_projects/deep_voice/lib/core/services/floating_window_manager.dart) + - `enableFloatingWindow()`:先通过 [OverlayPermissionUtil](file:///Users/liuxiamin/work/flutter_projects/deep_voice/lib/core/utils/overlay_permission_util.dart) 请求权限,再调用 `TranslationFloatingWindowApi.enable()` + - `_setupMethodCallHandler()`:接收 `onFloatingWindowStateChanged/onFloatingWindowClicked/onFloatingWindowClosed` 并更新状态/路由跳转 +- 内容更新:`TranslationController._updateFloatingWindowWithTranslation()` → `FloatingWindowManager.updateFloatingWindowContent()` → `updateContent(Map)` + +### Android:录音悬浮条 + +- 入口:会议录音控制器 [MeetingRecordController](file:///Users/liuxiamin/work/flutter_projects/deep_voice/lib/modules/meeting/controllers/meeting_record_controller.dart) + - `showBackgroundRecordingIndicator()` → `_startAndroidRecordingFloatingBar()` → `NativePlugin.showRecordingFloatingBar()` + - 定时器每秒 `updateRecordingFloatingBar()` 更新 duration/isPaused + - `_setupRecordingFloatingBarActionListener()` 监听 `recordingFloatingActionStream` 并处理 `togglePause/openMeetingRecord/closeFloatingBar` + +### iOS:翻译悬浮显示(PiP) + +- 入口同样在 [TranslationController](file:///Users/liuxiamin/work/flutter_projects/deep_voice/lib/modules/translation/controllers/translation_controller.dart) + - `_startPip()`:`NativePlugin.createPipContentView()` → 将 viewId 传给第三方 PiP 组件的 `PipOptions.contentView` + - `_updateFloatingWindowWithTranslation()`:`NativePlugin.updatePipContentView({viewId, cn, en, lang})` + +## 权限与 Manifest + +- Android 需要:`android.permission.SYSTEM_ALERT_WINDOW` +- 本插件自带 AndroidManifest 声明(包含两项 service): + - [android/src/main/AndroidManifest.xml](file:///Users/liuxiamin/work/flutter_projects/deep_voice/local_plugins/floating_ui_plugin/android/src/main/AndroidManifest.xml) + +## 平台差异与注意事项 + +- Android 与 iOS 的“悬浮显示”实现不同:Android 用系统悬浮窗;iOS 走系统 PiP。 +- `createPipContentView/updatePipContentView/disposePipContentView` 仅 iOS 实现;Android 侧没有实现这些 method,请务必用 `Platform.isIOS` 保护调用。 +- `floating_window` / `overlay_permission` / `native_plugin/recording_floating_actions` 都是固定通道名,避免在其他地方重复注册同名通道。 +- 工程 `android/app/src/main/kotlin/com/saitong/voitrans/` 下存在同名通道的旧实现文件(未在 MainActivity 注册),当前实际走的是本插件实现;如后续要启用 app 侧实现,需要先解决通道名冲突与 service 声明问题。 diff --git a/local_plugins/native_plugin/analysis_options.yaml b/local_plugins/floating_ui_plugin/analysis_options.yaml similarity index 100% rename from local_plugins/native_plugin/analysis_options.yaml rename to local_plugins/floating_ui_plugin/analysis_options.yaml diff --git a/local_plugins/native_plugin/android/.gitignore b/local_plugins/floating_ui_plugin/android/.gitignore similarity index 100% rename from local_plugins/native_plugin/android/.gitignore rename to local_plugins/floating_ui_plugin/android/.gitignore diff --git a/local_plugins/native_plugin/android/build.gradle b/local_plugins/floating_ui_plugin/android/build.gradle similarity index 100% rename from local_plugins/native_plugin/android/build.gradle rename to local_plugins/floating_ui_plugin/android/build.gradle diff --git a/local_plugins/floating_ui_plugin/android/settings.gradle b/local_plugins/floating_ui_plugin/android/settings.gradle new file mode 100644 index 000000000..2f81ceefc --- /dev/null +++ b/local_plugins/floating_ui_plugin/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'floating_ui_plugin' diff --git a/local_plugins/native_plugin/android/src/main/AndroidManifest.xml b/local_plugins/floating_ui_plugin/android/src/main/AndroidManifest.xml similarity index 100% rename from local_plugins/native_plugin/android/src/main/AndroidManifest.xml rename to local_plugins/floating_ui_plugin/android/src/main/AndroidManifest.xml diff --git a/local_plugins/native_plugin/android/src/main/kotlin/com/example/native_plugin/FloatingWindowService.kt b/local_plugins/floating_ui_plugin/android/src/main/kotlin/com/example/native_plugin/FloatingWindowService.kt similarity index 100% rename from local_plugins/native_plugin/android/src/main/kotlin/com/example/native_plugin/FloatingWindowService.kt rename to local_plugins/floating_ui_plugin/android/src/main/kotlin/com/example/native_plugin/FloatingWindowService.kt diff --git a/local_plugins/native_plugin/android/src/main/kotlin/com/example/native_plugin/NativePlugin.kt b/local_plugins/floating_ui_plugin/android/src/main/kotlin/com/example/native_plugin/NativePlugin.kt similarity index 100% rename from local_plugins/native_plugin/android/src/main/kotlin/com/example/native_plugin/NativePlugin.kt rename to local_plugins/floating_ui_plugin/android/src/main/kotlin/com/example/native_plugin/NativePlugin.kt diff --git a/local_plugins/native_plugin/android/src/main/kotlin/com/example/native_plugin/RecordingFloatingService.kt b/local_plugins/floating_ui_plugin/android/src/main/kotlin/com/example/native_plugin/RecordingFloatingService.kt similarity index 100% rename from local_plugins/native_plugin/android/src/main/kotlin/com/example/native_plugin/RecordingFloatingService.kt rename to local_plugins/floating_ui_plugin/android/src/main/kotlin/com/example/native_plugin/RecordingFloatingService.kt diff --git a/local_plugins/native_plugin/android/src/test/java/com/example/native_plugin/NativePluginTest.java b/local_plugins/floating_ui_plugin/android/src/test/java/com/example/native_plugin/NativePluginTest.java similarity index 100% rename from local_plugins/native_plugin/android/src/test/java/com/example/native_plugin/NativePluginTest.java rename to local_plugins/floating_ui_plugin/android/src/test/java/com/example/native_plugin/NativePluginTest.java diff --git a/local_plugins/native_plugin/ios/.gitignore b/local_plugins/floating_ui_plugin/ios/.gitignore similarity index 100% rename from local_plugins/native_plugin/ios/.gitignore rename to local_plugins/floating_ui_plugin/ios/.gitignore diff --git a/local_plugins/native_plugin/ios/Assets/.gitkeep b/local_plugins/floating_ui_plugin/ios/Assets/.gitkeep similarity index 100% rename from local_plugins/native_plugin/ios/Assets/.gitkeep rename to local_plugins/floating_ui_plugin/ios/Assets/.gitkeep diff --git a/local_plugins/native_plugin/ios/Classes/FLNativeView.swift b/local_plugins/floating_ui_plugin/ios/Classes/FLNativeView.swift similarity index 100% rename from local_plugins/native_plugin/ios/Classes/FLNativeView.swift rename to local_plugins/floating_ui_plugin/ios/Classes/FLNativeView.swift diff --git a/local_plugins/native_plugin/ios/Classes/NativePlugin.swift b/local_plugins/floating_ui_plugin/ios/Classes/NativePlugin.swift similarity index 100% rename from local_plugins/native_plugin/ios/Classes/NativePlugin.swift rename to local_plugins/floating_ui_plugin/ios/Classes/NativePlugin.swift diff --git a/local_plugins/native_plugin/ios/Classes/PlayerView.swift b/local_plugins/floating_ui_plugin/ios/Classes/PlayerView.swift similarity index 100% rename from local_plugins/native_plugin/ios/Classes/PlayerView.swift rename to local_plugins/floating_ui_plugin/ios/Classes/PlayerView.swift diff --git a/local_plugins/native_plugin/ios/Resources/PrivacyInfo.xcprivacy b/local_plugins/floating_ui_plugin/ios/Resources/PrivacyInfo.xcprivacy similarity index 100% rename from local_plugins/native_plugin/ios/Resources/PrivacyInfo.xcprivacy rename to local_plugins/floating_ui_plugin/ios/Resources/PrivacyInfo.xcprivacy diff --git a/local_plugins/native_plugin/ios/floating_ui_plugin.podspec b/local_plugins/floating_ui_plugin/ios/floating_ui_plugin.podspec similarity index 100% rename from local_plugins/native_plugin/ios/floating_ui_plugin.podspec rename to local_plugins/floating_ui_plugin/ios/floating_ui_plugin.podspec diff --git a/local_plugins/native_plugin/lib/native_plugin.dart b/local_plugins/floating_ui_plugin/lib/native_plugin.dart similarity index 100% rename from local_plugins/native_plugin/lib/native_plugin.dart rename to local_plugins/floating_ui_plugin/lib/native_plugin.dart diff --git a/local_plugins/native_plugin/lib/native_plugin_method_channel.dart b/local_plugins/floating_ui_plugin/lib/native_plugin_method_channel.dart similarity index 100% rename from local_plugins/native_plugin/lib/native_plugin_method_channel.dart rename to local_plugins/floating_ui_plugin/lib/native_plugin_method_channel.dart diff --git a/local_plugins/native_plugin/lib/native_plugin_platform_interface.dart b/local_plugins/floating_ui_plugin/lib/native_plugin_platform_interface.dart similarity index 100% rename from local_plugins/native_plugin/lib/native_plugin_platform_interface.dart rename to local_plugins/floating_ui_plugin/lib/native_plugin_platform_interface.dart diff --git a/local_plugins/native_plugin/pubspec.yaml b/local_plugins/floating_ui_plugin/pubspec.yaml similarity index 100% rename from local_plugins/native_plugin/pubspec.yaml rename to local_plugins/floating_ui_plugin/pubspec.yaml diff --git a/local_plugins/native_plugin/README.md b/local_plugins/native_plugin/README.md deleted file mode 100644 index bc8261f01..000000000 --- a/local_plugins/native_plugin/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# native_plugin - -A new Flutter plugin project. - -## Getting Started - -This project is a starting point for a Flutter -[plug-in package](https://flutter.dev/to/develop-plugins), -a specialized package that includes platform-specific implementation code for -Android and/or iOS. - -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev), which offers tutorials, -samples, guidance on mobile development, and a full API reference. - diff --git a/local_plugins/native_plugin/android/settings.gradle b/local_plugins/native_plugin/android/settings.gradle deleted file mode 100644 index 9f756a98c..000000000 --- a/local_plugins/native_plugin/android/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'native_plugin' diff --git a/pubspec.yaml b/pubspec.yaml index a6420566b..e7d6eb828 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -117,7 +117,7 @@ dependencies: qq_music: path: local_plugins/qq_music floating_ui_plugin: - path: local_plugins/native_plugin + path: local_plugins/floating_ui_plugin test: path: local_plugins/test