Commit 1f825025 authored by 张宏's avatar 张宏

3

parent 8ff902b4
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:laki_icu_app/services/usb_camera_service.dart';
import 'camera_controls.dart'; import 'camera_controls.dart';
...@@ -9,6 +10,7 @@ import 'camera_controls.dart'; ...@@ -9,6 +10,7 @@ import 'camera_controls.dart';
/// 职责: /// 职责:
/// - 通过 AndroidView 嵌入 Android 原生 USBCameraTextureView 预览画面 /// - 通过 AndroidView 嵌入 Android 原生 USBCameraTextureView 预览画面
/// - 底部控制栏:拍照、录像、刷新按钮 /// - 底部控制栏:拍照、录像、刷新按钮
/// - 通过 [UsbCameraService] 与原生层通信
/// ///
/// 涉及页面:首页监护舱页面 /// 涉及页面:首页监护舱页面
class MonitoringScreen extends StatefulWidget { class MonitoringScreen extends StatefulWidget {
...@@ -32,6 +34,13 @@ class _MonitoringScreenState extends State<MonitoringScreen> { ...@@ -32,6 +34,13 @@ class _MonitoringScreenState extends State<MonitoringScreen> {
bool _cameraReady = false; bool _cameraReady = false;
@override @override
void dispose() {
// 退出页面时关闭摄像头
UsbCameraService.closeCamera();
super.dispose();
}
@override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
...@@ -67,32 +76,20 @@ class _MonitoringScreenState extends State<MonitoringScreen> { ...@@ -67,32 +76,20 @@ class _MonitoringScreenState extends State<MonitoringScreen> {
/// 构建 USB 摄像头预览画面(通过 PlatformView) /// 构建 USB 摄像头预览画面(通过 PlatformView)
Widget _buildCameraPreview() { Widget _buildCameraPreview() {
// AndroidView 需要 Android API 20+,且仅在 Android 平台有效 return ClipRRect(
// 在其他平台或未连接 USB 摄像头时显示占位符 borderRadius: BorderRadius.circular(20.r),
try { child: SizedBox.expand(
return ClipRRect( child: AndroidView(
borderRadius: BorderRadius.circular(20.r), viewType: 'usb_camera_view',
child: SizedBox.expand( onPlatformViewCreated: (_) {
child: _buildAndroidView(), setState(() {
_cameraReady = true;
});
},
creationParams: const <String, dynamic>{},
creationParamsCodec: const StandardMessageCodec(),
), ),
); ),
} catch (_) {
return const SizedBox.shrink();
}
}
/// 构建 Android 原生 PlatformView
Widget _buildAndroidView() {
// ignore: undefined_platform_specific_widget
return AndroidView(
viewType: 'usb_camera_view',
onPlatformViewCreated: (_) {
setState(() {
_cameraReady = true;
});
},
creationParams: const <String, dynamic>{},
creationParamsCodec: const StandardMessageCodec(),
); );
} }
...@@ -131,30 +128,23 @@ class _MonitoringScreenState extends State<MonitoringScreen> { ...@@ -131,30 +128,23 @@ class _MonitoringScreenState extends State<MonitoringScreen> {
/// 拍照 /// 拍照
Future<void> _onTakePhoto() async { Future<void> _onTakePhoto() async {
// 调用 Service 层拍照 final path = await UsbCameraService.takePhoto();
final cameraService = await _getCameraService(); if (path != null && mounted) {
if (cameraService != null) { _showSnackBar('拍照成功: $path');
final path = await cameraService.takePhoto();
if (path != null && mounted) {
_showSnackBar('拍照成功: $path');
}
} }
widget.onSnapshot?.call(); widget.onSnapshot?.call();
} }
/// 切换录像状态 /// 切换录像状态
Future<void> _onToggleRecord() async { Future<void> _onToggleRecord() async {
final cameraService = await _getCameraService();
if (cameraService == null) return;
if (_isRecording) { if (_isRecording) {
final path = await cameraService.stopRecord(); final path = await UsbCameraService.stopRecord();
if (path != null && mounted) { if (path != null && mounted) {
_showSnackBar('录像已保存: $path'); _showSnackBar('录像已保存: $path');
} }
setState(() => _isRecording = false); setState(() => _isRecording = false);
} else { } else {
final success = await cameraService.startRecord(); final success = await UsbCameraService.startRecord();
if (success) { if (success) {
setState(() => _isRecording = true); setState(() => _isRecording = true);
if (mounted) _showSnackBar('开始录像'); if (mounted) _showSnackBar('开始录像');
...@@ -163,18 +153,6 @@ class _MonitoringScreenState extends State<MonitoringScreen> { ...@@ -163,18 +153,6 @@ class _MonitoringScreenState extends State<MonitoringScreen> {
widget.onRecord?.call(); widget.onRecord?.call();
} }
/// 获取摄像头服务实例
Future<dynamic> _getCameraService() async {
// 延迟导入,避免在非 Android 平台导入时出现问题
try {
// 动态调用 UsbCameraService
// ignore: depend_on_referenced_packages
return _UsbCameraServiceProxy();
} catch (_) {
return null;
}
}
void _showSnackBar(String message) { void _showSnackBar(String message) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
...@@ -189,41 +167,3 @@ class _MonitoringScreenState extends State<MonitoringScreen> { ...@@ -189,41 +167,3 @@ class _MonitoringScreenState extends State<MonitoringScreen> {
); );
} }
} }
/// USB 摄像头服务代理 —— 避免硬依赖导致非 Android 平台编译错误
class _UsbCameraServiceProxy {
Future<String?> takePhoto({String? path}) async {
// 通过 MethodChannel 直接调用(与 UsbCameraService 使用同一个 channel)
const channel = MethodChannel('usb_camera');
try {
final result = await channel.invokeMethod('takePhoto', {
if (path != null) 'path': path,
});
return result as String?;
} catch (_) {
return null;
}
}
Future<bool> startRecord({String? path}) async {
const channel = MethodChannel('usb_camera');
try {
final result = await channel.invokeMethod('startRecord', {
if (path != null) 'path': path,
});
return result == true;
} catch (_) {
return false;
}
}
Future<String?> stopRecord() async {
const channel = MethodChannel('usb_camera');
try {
final result = await channel.invokeMethod('stopRecord');
return result as String?;
} catch (_) {
return null;
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment