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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 16:20:42