Flutter WebRTC摄像头仅在锁屏解锁后工作问题求助
解决flutter_webrtc摄像头显示问题
一、模拟器无法显示摄像头的原因及解决
Android模拟器本身无物理摄像头,默认未加载虚拟摄像头,可按以下方式处理:
- 打开模拟器设置(右上角三点按钮)→ Virtual Sensors → 找到Camera选项,选择模拟摄像头(如
webcam0或虚拟视频文件),保存后重启模拟器。 - 优先使用Android真机测试,模拟器的摄像头模拟存在兼容性局限。
二、Android真机锁屏解锁后才显示的问题修复
你的代码存在异步流程未同步、未触发UI更新、权限缺失等问题,以下是针对性修复:
1. 同步异步流程并触发UI刷新
initState中直接调用异步函数会导致渲染器未初始化完成就设置媒体流,且设置后未通知UI更新。修改初始化逻辑:
@override void initState() { super.initState(); _initCamera(); // 封装为异步初始化方法 } Future<void> _initCamera() async { await initRenderers(); // 等待渲染器初始化完成 final stream = await _getUserMedia(); setState(() { // 触发UI重新构建 _localVideoRenderer.srcObject = stream; }); }
同时清理_getUserMedia中重复的流设置代码,并明确摄像头方向:
Future<MediaStream> _getUserMedia() async { final Map<String, dynamic> mediaConstraints = { 'audio': true, 'video': { 'facingMode': 'user', // 指定前置摄像头,提升兼容性 }, }; return await navigator.mediaDevices.getUserMedia(mediaConstraints); }
2. 配置并动态申请权限
Android 6.0+需动态申请摄像头和麦克风权限:
- 在
android/app/src/main/AndroidManifest.xml添加权限声明:
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" />
- 添加
permission_handler插件(在pubspec.yaml中添加permission_handler: ^10.2.0),修改_initCamera先申请权限:
import 'package:permission_handler/permission_handler.dart'; Future<void> _initCamera() async { final cameraStatus = await Permission.camera.request(); final micStatus = await Permission.microphone.request(); if (cameraStatus.isDenied || micStatus.isDenied) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('需要摄像头和麦克风权限才能使用')), ); return; } await initRenderers(); final stream = await _getUserMedia(); setState(() { _localVideoRenderer.srcObject = stream; }); }
3. 添加渲染器初始化异常捕获
避免初始化失败导致后续流程卡住:
Future<void> initRenderers() async { try { await _localVideoRenderer.initialize(); } catch (e) { print('渲染器初始化失败: $e'); } }
三、完整修改后的代码
import 'package:flutter/material.dart'; import 'package:flutter_webrtc/flutter_webrtc.dart'; import 'package:permission_handler/permission_handler.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(title: 'Flutter Demo Home Page'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({super.key, required this.title}); final String title; @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { final _localVideoRenderer = RTCVideoRenderer(); MediaStream? _localStream; Future<void> initRenderers() async { try { await _localVideoRenderer.initialize(); } catch (e) { print('渲染器初始化失败: $e'); } } Future<MediaStream> _getUserMedia() async { final Map<String, dynamic> mediaConstraints = { 'audio': true, 'video': { 'facingMode': 'user', }, }; return await navigator.mediaDevices.getUserMedia(mediaConstraints); } Future<void> _initCamera() async { final cameraStatus = await Permission.camera.request(); final micStatus = await Permission.microphone.request(); if (cameraStatus.isDenied || micStatus.isDenied) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('需要摄像头和麦克风权限才能正常使用')), ); return; } await initRenderers(); final stream = await _getUserMedia(); setState(() { _localStream = stream; _localVideoRenderer.srcObject = stream; }); } @override void initState() { super.initState(); _initCamera(); } @override void dispose() async { _localStream?.dispose(); await _localVideoRenderer.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Stack( children: [ Positioned.fill( child: RTCVideoView(_localVideoRenderer), ), ], ), ); } }
内容的提问来源于stack exchange,提问作者omegaGoat
相关产品推荐
相关产品推荐

