在flutter中从image_picker包中打开相机会导致真实设备上的应用程序崩溃,但在模拟器(android)中运行良好

Posted

技术标签:

【中文标题】在flutter中从image_picker包中打开相机会导致真实设备上的应用程序崩溃,但在模拟器(android)中运行良好【英文标题】:opening camera from image_picker package in flutter crashes app on real device but works fine in emulator (android) 【发布时间】:2019-12-05 23:52:59 【问题描述】:

我正在使用颤振 image_picker: ^0.6.0+17 来获取应用中产品的图像 它在模拟器上绝对可以正常工作,但在真正的 android 设备上,当我单击“打开相机”按钮时,应用程序崩溃并重新启动。

我已尝试将模拟器用作与我的设备相同的 api 级别 我在 Redmi 6A android oreo 8.1 上测试它 没发现问题扑医生 或颤振分析 从图库中选择图像对两者都适用。

import 'dart:io';

import 'package:firstapp/models/product.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';

class ImageInput extends StatefulWidget 
  final Function setImage;
  final Product product;

  ImageInput(this.setImage, this.product);

  @override
  State<StatefulWidget> createState() 
    return _ImageInputState();
  


class _ImageInputState extends State<ImageInput> 
  File _imageFile;

  Future _getImage(BuildContext context, ImageSource source) async 
    print('getting image');
    File image = await ImagePicker.pickImage(source: source, maxWidth: 600);
    if(image == null)
      return null;
    
    setState(() 
      print('file = image');
      _imageFile = image;
    );
    print('setting image');
    widget.setImage(image);
    Navigator.pop(context);
  

  void _openImagePicker(BuildContext context) 
    showModalBottomSheet(
        context: context,
        builder: (BuildContext context) 
          return Container(
            padding: EdgeInsets.all(10),
            height: 150,
            child: Column(children: <Widget>[
              Text(
                'Pick an Image',
                style: TextStyle(
                  fontWeight: FontWeight.bold,
                ),
              ),
              SizedBox(
                height: 10,
              ),
              FlatButton(
                textColor: Theme.of(context).primaryColor,
                child: Text('Use Camera'),
                onPressed: () 
                  _getImage(context, ImageSource.camera);
                ,
              ),
              FlatButton(
                textColor: Theme.of(context).primaryColor,
                child: Text('Use Gallery'),
                onPressed: () 
                  _getImage(context, ImageSource.gallery);
                ,
              )
            ]),
          );
        );
  

  @override
  Widget build(BuildContext context) 
    final buttonColor = Theme.of(context).primaryColor;
    Widget previewImage = Text('Please select an image.');
    if (_imageFile != null) 
      previewImage = Image.file(
        _imageFile,
        height: 300.0,
        width: MediaQuery.of(context).size.width,
        fit: BoxFit.cover,
        alignment: Alignment.center,
      );
     else if (widget.product != null) 
      previewImage = Image.network(
        widget.product.image,
        height: 300.0,
        width: MediaQuery.of(context).size.width,
        fit: BoxFit.cover,
        alignment: Alignment.center,
      );
    

    return Column(
      children: <Widget>[
        OutlineButton(
          onPressed: () 
            _openImagePicker(context);
          ,
          borderSide: BorderSide(color: buttonColor, width: 1),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Icon(
                Icons.camera_alt,
                color: buttonColor,
              ),
              SizedBox(
                width: 5.0,
              ),
              Text(
                'Add Image',
                style: TextStyle(color: buttonColor),
              )
            ],
          ),
        ),
        SizedBox(
          height: 10,
        ),
        previewImage,
      ],
    );
  


这些是我按下使用相机后的调试日志 然后应用重新启动

I/flutter (20143): getting image
D/Surface (20143): Surface::disconnect(this=0x9577d000,api=1)
D/GraphicBuffer(20143): unregister, handle(0xaa60e900) (w:720 h:1440 s:736 f:0x1 u:b00)
D/GraphicBuffer(20143): unregister, handle(0xaa610280) (w:720 h:1440 s:736 f:0x1 u:b00)
D/GraphicBuffer(20143): unregister, handle(0xaa610640) (w:720 h:1440 s:736 f:0x1 u:b00)
D/Surface (20143): Surface::disconnect(this=0x9577d000,api=-1)
D/Surface (20143): Surface::disconnect(this=0x9577c000,api=1)
D/GraphicBuffer(20143): unregister, handle(0x94f956c0) (w:720 h:1440 s:736 f:0x1 u:b00)
V/PhoneWindow(20143): DecorView setVisiblity: visibility = 4, Parent = ViewRootf21fea2 com.example.firstapp/com.example.firstapp.MainActivity,ident = 0, this = DecorView@5af733[MainActivity]
Lost connection to device.
Exited (sigterm)

这些是我正在使用的简单代码,只需从图像选择器包中将source 更改为ImageSource.camera

Future _getImage(BuildContext context, ImageSource source) async 
    print('getting image');
    File image = await ImagePicker.pickImage(source: source, maxWidth: 600);
    if(image == null)
      return null;
    
    setState(() 
      print('file = image');
      _imageFile = image;
    );
    print('setting image');
    widget.setImage(image);
    Navigator.pop(context);
  

提前致谢

【问题讨论】:

你能分享adb logcat 的输出吗?您粘贴的日志并没有说明崩溃。寻找 RuntimeException 或 NPE 请看这个...github.com/flutter/flutter/issues/48016#issuecomment-606538114 作为它在 github 上的公开问题,很多开发人员在 Redmi 设备上都有同样的问题。 不过,它发生在最新版本的图像选择器中。只有后置摄像头是问题,但它与前置摄像头配合得很好。 【参考方案1】:

在 runner Info.plist 文件中,为我添加这些作品

<string>Need to upload image</string>
<key>NSCameraUsageDescription</key>
<string>Need to upload image</string>
<key>NSMicrophoneUsageDescription</key>
<string>Need to upload image</string>

【讨论】:

以上是关于在flutter中从image_picker包中打开相机会导致真实设备上的应用程序崩溃,但在模拟器(android)中运行良好的主要内容,如果未能解决你的问题,请参考以下文章

如何在flutter中从record_mp3包中为api上传mp3文件

在通道 plugins.flutter.io/image_picke 上找不到方法 pickImage 的实现

flutter image_picker使用照相机

flutter 上传图片 image_picker 的使用

Flutter从相册选择图片和相机拍照(image_picker)

Flutter IOS 应用程序不会以 image_picker 开头:^0.6.3+4