You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Web调用setFlashMode在Android Chrome报TypeError问题

Flutter Web启用闪光灯时出现类型错误:Type Error: true: type 'bool' is not a subtype of type 'JSArray<Object?>?'

问题详情

  • 开发Flutter Web应用,需实现手电筒/闪光灯功能
  • 在三星Galaxy S21、Google Pixel 6 Pro的Android版Chrome测试,均触发相同错误
  • 相机预览、录制功能正常,但调用controller.setFlashMode(FlashMode.always)时抛出类型错误
  • 完整代码如下:
import 'package:flutter/material.dart';

class CameraScreen extends StatefulWidget {
  const CameraScreen({super.key});

  @override
  State<CameraScreen> createState() => _CameraScreenState();
}

class _CameraScreenState extends State<CameraScreen> {
  late CameraController controller;
  bool isInitialised = false;

  Future<void> initialiseCamera() async {
    final cameras = await availableCameras();
    controller = CameraController(cameras.last, ResolutionPreset.max, enableAudio: false);
    if (!mounted) return;
    try {
      await controller.initialize();
      setState(() {
        isInitialised = true;
      });
    } catch (e) {
      if (e is CameraException) {
        switch (e.code) {
          case 'CameraAccessDenied':
            break;
          default:
            break;
        }
      }
    }
  }

  void enableFlash() {
    if (isInitialised) {
          controller.setFlashMode(FlashMode.always);
    }
  }

  @override
  void initState() {
    initialiseCamera();
    super.initState();
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          Align(
            alignment: Alignment.center,
            child: Builder(builder: (context) {
              if (!isInitialised) {
                return const CircularProgressIndicator();
              }
              return AspectRatio(
                  aspectRatio: 9 / 16, child: CameraPreview(controller));
            }),
          ),
          Align(
            alignment: Alignment.bottomCenter,
            child: ElevatedButton(
                onPressed: enableFlash,
                child: const Text("Flash"),
            ),
          ),
        ],
      ),
    );
  }
}

原因分析

该错误源于Flutter Web的camera插件在处理FlashMode时存在内部类型转换问题,Web端的MediaDevices API与移动端实现逻辑不同,直接调用setFlashMode未做适配导致类型不匹配。

解决方案

方案1:改用Web原生API控制闪光灯

由于Flutter官方camera插件对Web端闪光灯的支持不完善,可直接调用浏览器的MediaDevices API实现功能:

  1. 在Dart代码中引入dart:js,调用自定义JS方法:
import 'dart:js' as js;
// ... 其他代码保持不变

void enableFlash() {
  if (isInitialised) {
    js.context.callMethod('toggleFlash');
  }
}
  1. 在web/index.html中添加JavaScript逻辑:
<script>
let flashEnabled = false;
async function toggleFlash() {
  try {
    // 获取后置摄像头流
    const stream = await navigator.mediaDevices.getUserMedia({ 
      video: { facingMode: 'environment' } 
    });
    const videoTrack = stream.getVideoTracks()[0];
    
    // 检查设备是否支持闪光灯
    const capabilities = videoTrack.getCapabilities();
    if (!capabilities.torch) {
      console.error('当前设备不支持闪光灯');
      return;
    }

    // 切换闪光灯状态
    flashEnabled = !flashEnabled;
    await videoTrack.applyConstraints({ 
      advanced: [{ torch: flashEnabled }] 
    });
  } catch (err) {
    console.error('闪光灯控制失败:', err);
  }
}
</script>

方案2:升级相机插件并检查配置

  1. 确保pubspec.yaml中使用最新版的camera和camera_web插件:
dependencies:
  flutter:
    sdk: flutter
  camera: ^0.10.5+5
  camera_web: ^0.3.2+5
  1. 初始化相机时添加Web端适配配置:
Future<void> initialiseCamera() async {
  final cameras = await availableCameras();
  controller = CameraController(
    cameras.last, 
    ResolutionPreset.max, 
    enableAudio: false,
    imageFormatGroup: ImageFormatGroup.jpeg, // Web端推荐格式
  );
  // ... 其他代码保持不变
}

注意事项

  • 需确保用户已授予相机权限,浏览器才允许访问闪光灯
  • 部分浏览器或设备可能不支持MediaDevices的torch功能,需做兼容性判断

内容的提问来源于stack exchange,提问作者MikkelT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 09:47:21