首页 > 解决方案 > 尝试从图库中检索视频时,Flutter image_picker 包返回 null

问题描述

我正在尝试构建一个应用程序,让用户选择视频并上传它们,所以为此,我使用了 image_picker 包。但是,我目前正在运行测试,每当我尝试从图库中选择视频时,我都没有取回文件,而是返回 null。我不知道问题出在我如何使用包或权限上,尽管根据包你不需要 android 的权限。

在我的代码中给我带来麻烦的函数下方:

handleChooseFromGallery() async {
Navigator.pop(context);
File filePicked = await ImagePicker.pickVideo(
  source: ImageSource.gallery,
  maxDuration: Duration(seconds: 90),
);
//This line always returns false
print({'is file not null': filePicked != null});
setState(() {
  if (filePicked != null) {
    this.files.add(filePicked);
    this.selected = true;
  } else {
    showError();
  }
});
  }

完整的代码(减去完全不相关的东西):

import 'dart:io';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:golfapp/data/course_data.dart';
import 'package:golfapp/data/user_data.dart';
import 'package:provider/provider.dart';
import 'package:image_picker/image_picker.dart';
import 'package:uuid/uuid.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

import 'package:golfapp/data/semana_data.dart';
import 'package:golfapp/widgets/chewie_item.dart';

final StorageReference storageRef = FirebaseStorage.instance.ref();
final postsRef = Firestore.instance.collection('posts');
final DateTime timestamp = DateTime.now();

class DetailScreen extends StatefulWidget {
  final int index;
  final String photoUrl;
  final String videoUrl;

  DetailScreen({this.index, this.photoUrl, this.videoUrl});

  @override
  _DetailScreenState createState() => _DetailScreenState();
}

class _DetailScreenState extends State<DetailScreen> {
  bool isUploading = false;
  bool selected = false;
  List<File> files = [];
  String postId = Uuid().v4();
  TextEditingController captionController = TextEditingController();

  showError() {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Row(
            children: [
              Padding(
                padding: EdgeInsets.only(right: 10.0),
                child: Text('Error'),
              ),
              Icon(Icons.error_outline, size: 60.0),
            ],
          ),
          content: SingleChildScrollView(
            child: ListBody(
              children: [
                Text(
                  'Hubo un error con el video seleccionado.',
                  style: TextStyle(
                    fontFamily: 'Montserrat',
                    fontWeight: FontWeight.w600,
                    fontSize: 17.0,
                  ),
                ),
              ],
            ),
          ),
        );
      },
    );
  }

  clearImage() {
    setState(() {
      this.selected = false;
    });
  }

  handleTakePhoto() async {
    Navigator.pop(context);
    File fileTaken = await ImagePicker.pickVideo(
      source: ImageSource.camera,
      maxDuration: Duration(seconds: 90),
    );
    setState(() {
      if (fileTaken != null) {
        this.files.add(fileTaken);
        this.selected = true;
      } else {
        showError();
      }
    });
  }

  handleChooseFromGallery() async {
    Navigator.pop(context);
    File filePicked = await ImagePicker.pickVideo(
      source: ImageSource.gallery,
      maxDuration: Duration(seconds: 90),
    );
    print({'is file not null': filePicked != null});
    setState(() {
      if (filePicked != null) {
        this.files.add(filePicked);
        this.selected = true;
      } else {
        showError();
      }
    });
  }

  selectImage(parentContext) {
    return showDialog(
      context: parentContext,
      builder: (context) {
        return SimpleDialog(
          title: Text("Seleccionar video"),
          children: <Widget>[
            SimpleDialogOption(
              child: Text("Tomar video"),
              onPressed: handleTakePhoto,
            ),
            SimpleDialogOption(
              child: Text("Video de la galería"),
              onPressed: handleChooseFromGallery,
            ),
            SimpleDialogOption(
              child: Text("Cancelar"),
              onPressed: () => Navigator.pop(context),
            )
          ],
        );
      },
    );
  }

  Future<String> uploadVideo(imageFile) async {
    StorageUploadTask uploadTask = storageRef
        .child(Provider.of<UserData>(context, listen: false).user.id)
        .child(Provider.of<CourseData>(context, listen: false).course.uid)
        .child(Provider.of<SemanaData>(context, listen: false).semana.uid)
        .putFile(imageFile, StorageMetadata(contentType: 'video/mp4'));
    StorageTaskSnapshot storageSnap = await uploadTask.onComplete;
    String downloadUrl = await storageSnap.ref.getDownloadURL();
    return downloadUrl;
  }

  createPostInFirestore({List<String> mediaUrl, String description}) {
    postsRef
        .document(Provider.of<UserData>(context, listen: false).user.id)
        .collection("userPosts")
        .document(Provider.of<CourseData>(context, listen: false).course.uid)
        .setData({
      "semana": Provider.of<SemanaData>(context, listen: false).semana.uid,
      "postId": postId,
      "ownerId": Provider.of<UserData>(context, listen: false).user.id,
      "username": Provider.of<UserData>(context, listen: false).user.username,
      "mediaUrl": mediaUrl,
      "description": description,
      "timestamp": timestamp,
      "likes": {},
    });
  }

  handleSubmit() async {
    setState(() {
      isUploading = true;
    });
    List<String> mediaUrlS = [];
    for (File fileLoop in files) {
      String mediaUrl = await uploadVideo(fileLoop);
      mediaUrlS.add(mediaUrl);
    }
    createPostInFirestore(
      mediaUrl: mediaUrlS,
      description: captionController.text,
    );
    captionController.clear();
    setState(() {
      files = [];
      isUploading = false;
      postId = Uuid().v4();
      selected = false;
    });
  }

  Scaffold buildUploadForm() {
    return Scaffold(
      appBar: AppBar(
        title: Text(
          "Tu video",
          style: TextStyle(color: Colors.black),
        ),
        actions: [
          FlatButton(
            onPressed: files.length < 2 ? selectImage(context) : null,
            child: Text(
              'Seleccionar otro video',
            ),
          ),
          FlatButton(
            onPressed: isUploading ? null : () => handleSubmit(),
            child: Text(
              "Mandar",
            ),
          ),
        ],
      ),
      body: ListView.builder(
          scrollDirection: Axis.vertical,
          shrinkWrap: true,
          itemCount: files.length,
          itemBuilder: (BuildContext context, int index) {
            final File fileBuilder = files[index];
            return Container(
              height: 220.0,
              width: MediaQuery.of(context).size.width * 0.8,
              child: Center(
                child: AspectRatio(
                  aspectRatio: 16 / 9,
                  child: Container(
                    child: ChewieListItem(
                      videoUrl: fileBuilder.path,
                      network: false,
                      file: fileBuilder,
                    ),
                  ),
                ),
              ),
            );
          }),
    );
  }

  Widget buildNormalScreen () {
    return Container(
      child: GestureDetector(
        onTap: () {
          selectImage(context);
        },
        child: Container(
          height: 50.0,
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(30.0),
            color: Theme.of(context).accentColor,
          ),
          child: Center(
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  'Subir videos',
                  style: TextStyle(
                    fontFamily: 'Comfortaa',
                    fontSize: 17.0,
                    color: Colors.white,
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return !selected
        ? buildNormalScreen()
        : buildUploadForm();
  }
}

在顶部的功能中,我也尝试过类似的操作ImagePicker.pickVideo().then((file){...}),但没有奏效。我还添加<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>到我的“android/app/src/main/AndroidManifest.xml”文件中。我还尝试在我的“android/app/src/main/AndroidManifest.xml”文件中android:requestLegacyExternalStorage="true"<application>标签内添加,但随后出现错误: 控制台打印输出

我不知道我应该在我的代码或 android 文件夹中的一个文件中更改什么,非常感谢任何帮助。

非常感谢您提前

标签: flutterdart

解决方案


将条件放在同一个函数中。

handleChooseFromGallery() async {
Navigator.pop(context);
File filePicked = await ImagePicker.pickVideo(
  source: ImageSource.gallery,
  maxDuration: Duration(seconds: 90),
  //This line always returns false
  print({'is file not null': filePicked != null});
  setState(() {
    if (filePicked != null) {
      this.files.add(filePicked);
      this.selected = true;
    } else {
      showError();
    }
  });
}

);


推荐阅读