Flutter应用已获相机权限却提示“No camera is found”问题求助
问题排查:Flutter相机提示“No camera is found”
问题场景
代码无语法报错,应用已获取相机权限,但运行时控制台输出如下日志:
I/flutter (12856): Model Response: Instance of 'Future'
I/tflite (12856): Replacing 31 node(s) with delegate >(TfLiteXNNPackDelegate) node, yielding 1 partitions.>
I/flutter (12856): No camera is found
提供的代码
import 'package:camera/camera.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:tflite/tflite.dart'; import 'dart:math' as math; typedef void Callback(List<dynamic> list, int h, int w); class Camera extends StatefulWidget { final List<CameraDescription> cameras; final Callback setRecognitions; const Camera({widget.cameras, widget.setRecognitions}); @override _CameraState createState() => _CameraState(); } class _CameraState extends State<Camera> { CameraController controller; bool isDetecting = false; static const platform = const MethodChannel('ondeviceML'); @override void initState() { super.initState(); if (widget.cameras == null || widget.cameras.length < 1) { print('No camera is found'); } else { controller = new CameraController( // widget.camera[0] for back camera // widget.camera[1] for front camera widget.cameras[1], ResolutionPreset.high, ); controller.initialize().then((_) { if (!mounted) { return; } setState(() {}); controller.startImageStream((CameraImage img) { if (!isDetecting) { isDetecting = true; int startTime = new DateTime.now().millisecondsSinceEpoch; Tflite.runPoseNetOnFrame( bytesList: img.planes.map((plane) { return plane.bytes; }).toList(), imageHeight: img.height, imageWidth: img.width, numResults: 1, rotation: -90, threshold: 0.2, nmsRadius: 10, ).then((recognitions) { int endTime = new DateTime.now().millisecondsSinceEpoch; print("Detection took ${endTime - startTime}"); widget.setRecognitions(recognitions, img.height, img.width); isDetecting = false; }); } }); }); } } @override void dispose() { controller?.dispose(); super.dispose(); } @override Widget build(BuildContext context) { if (controller == null || !controller.value.isInitialized) { return Container(); } var tmp = MediaQuery.of(context).size; var screenH = math.max(tmp.height, tmp.width); var screenW = math.min(tmp.height, tmp.width); tmp = controller.value.previewSize; var previewH = math.max(tmp.height, tmp.width); var previewW = math.min(tmp.height, tmp.width); var screenRatio = screenH / screenW; var previewRatio = previewH / previewW; return OverflowBox( maxHeight: screenRatio > previewRatio ? screenH : screenW / previewW * previewH, maxWidth: screenRatio > previewRatio ? screenH / previewH * previewW : screenW, child: CameraPreview(controller), ); } }
问题原因分析
- 构造函数参数绑定错误:
Camera类的构造函数写法违规,没有将传入的cameras和setRecognitions参数赋值给类成员变量,导致widget.cameras始终为null,触发了No camera is found的打印逻辑。 - 相机索引越界风险:即使参数传递正确,直接使用
widget.cameras[1]选择前置相机,在仅配备单相机的设备上会出现索引越界问题,同样导致相机初始化失败。
解决方案
1. 修复构造函数参数绑定
将Camera类的构造函数修改为正确的命名参数形式,确保参数被正确赋值:
class Camera extends StatefulWidget { final List<CameraDescription> cameras; final Callback setRecognitions; const Camera({required this.cameras, required this.setRecognitions}); @override _CameraState createState() => _CameraState(); }
2. 增加相机索引的安全判断
在初始化CameraController时,先检查相机列表长度,优先选择后置相机避免索引越界:
// 替换initState中的相机初始化逻辑 controller = CameraController( widget.cameras.length > 0 ? widget.cameras[0] : widget.cameras.first, ResolutionPreset.high, );
3. 确认相机列表的获取逻辑
在调用Camera组件的地方,确保已通过availableCameras()方法获取可用相机列表并传递给组件:
// 示例:在主页面中获取相机列表并传递 void main() async { WidgetsFlutterBinding.ensureInitialized(); final cameras = await availableCameras(); runApp(MyApp(cameras: cameras)); }
内容的提问来源于stack exchange,提问作者J L
相关产品推荐
相关产品推荐

