我无法弄清楚如何保存到相机胶卷(相当于React Native' s CameraRoll
saveToCameraRoll()
。
Flutter camera建议使用path_provider
来获取应用程序目录,但它似乎没有选项来获取相机胶卷目录路径。
我在CameraController.capture
相关更改(以及差异形式的相关更改)位于:https://gist.github.com/briankung/45f9d8438baab59ddcd3b6f3fe811d99
我的整个main.dart
位于下方以便轻松复制(搜索QUESTION:
以查找相关部分):
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
List<CameraDescription> cameras;
Future<Null> main() async {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown
]);
cameras = await availableCameras();
runApp(new CameraApp());
}
class CameraApp extends StatefulWidget {
@override
_CameraAppState createState() => new _CameraAppState();
}
class _CameraAppState extends State<CameraApp> {
String _appDirectoryPath;
CameraController controller;
Future<void> _requestAppDirectory() async {
// QUESTION: `path_provider` doesn't have getCameraRollDirectory()
Directory _appDirectory = await getApplicationDocumentsDirectory();
setState(() {
_appDirectoryPath = _appDirectory.path;
});
}
@override
void initState() {
super.initState();
_requestAppDirectory();
controller = new CameraController(cameras[0], ResolutionPreset.medium);
controller.initialize().then((_) {
if (!mounted) {
return;
}
setState(() {});
});
}
@override
void dispose() {
controller?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
if (!controller.value.initialized) {
return new Container();
}
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.red,
),
home: new Scaffold(
body: new Center(
child: new AspectRatio(
aspectRatio: controller.value.aspectRatio,
child: new CameraPreview(controller),
),
),
floatingActionButton: new FloatingActionButton(
tooltip: 'Increment',
child: new Icon(Icons.camera),
onPressed: () {
print('capturing');
print(_appDirectoryPath);
// QUESTION: this errors out
controller.capture(_appDirectoryPath);
},
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
),
);
}
}
日志信息如下:
I/flutter ( 5471): capturing
I/flutter ( 5471): /data/user/0/com.example.mycameraapp/app_flutter
W/LegacyRequestMapper( 5471): convertRequestMetadata - control.awbRegions setting is not supported, ignoring value
W/LegacyRequestMapper( 5471): Only received metering rectangles with weight 0.
W/LegacyRequestMapper( 5471): Only received metering rectangles with weight 0.
I/RequestThread-0( 5471): Received jpeg.
I/RequestThread-0( 5471): Producing jpeg buffer...
W/LegacyRequestMapper( 5471): convertRequestMetadata - control.awbRegions setting is not supported, ignoring value
W/LegacyRequestMapper( 5471): Only received metering rectangles with weight 0.
W/LegacyRequestMapper( 5471): Only received metering rectangles with weight 0.
E/flutter ( 5471): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception:
E/flutter ( 5471): CameraException(IOError, Failed saving image)
E/flutter ( 5471): #0 CameraController.capture (package:camera/camera.dart:234:7)
E/flutter ( 5471): <asynchronous suspension>
E/flutter ( 5471): #1 _CameraAppState.build.<anonymous closure> (file:///Users/briankung/workspace/mobile/flutter/my_camera_app/lib/main.dart:84:24)
E/flutter ( 5471): #2 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:478:14)
E/flutter ( 5471): #3 _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:530:30)
E/flutter ( 5471): #4 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:102:24)
E/flutter ( 5471): #5 TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:161:9)
E/flutter ( 5471): #6 TapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:123:7)
E/flutter ( 5471): #7 GestureArenaManager.sweep (package:flutter/src/gestures/arena.dart:156:27)
E/flutter ( 5471): #8 _WidgetsFlutterBinding&BindingBase&GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:147:20)
E/flutter ( 5471): #9 _WidgetsFlutterBinding&BindingBase&GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:121:22)
E/flutter ( 5471): #10 _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:101:7)
E/flutter ( 5471): #11 _WidgetsFlutterBinding&BindingBase&GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:64:7)
E/flutter ( 5471): #12 _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:48:7)
E/flutter ( 5471): #13 _invoke1 (dart:ui/hooks.dart:134:13)
E/flutter ( 5471): #14 _dispatchPointerDataPacket (dart:ui/hooks.dart:91:5)
I/RequestQueue( 5471): Repeating capture request cancelled.
谢谢!
忘记版本号:
$ flutter --version
Flutter 0.2.8 • channel beta • https://github.com/flutter/flutter.git
Framework • revision b397406561 (10 days ago) • 2018-04-02 13:53:20 -0700
Engine • revision c903c217a1
Tools • Dart 2.0.0-dev.43.0.flutter-52afcba357
// pubspec.yaml
camera:
dependency: "direct main"
description:
name: camera
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.2"
path_provider:
dependency: "direct main"
description:
name: path_provider
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.0"
答案 0 :(得分:4)
您可以使用pub.dev/packages/gallery_saver中的 gallery_saver ,将视频和图像同时保存在Android和iOS的图库/照片中。
您只需要为其提供文件或URL的临时路径,即可保存本地文件和来自网络的文件。
这是它的用法:
GallerySaver.saveVideo(String path);
GallerySaver.saveImage(String path);
在成功保存案例文件后,两个函数都返回true,而以其他任何方式返回false。
我的团队开发了此插件。
答案 1 :(得分:3)
不幸的是,我不认为扑动目前会暴露这种功能。
您最好的选择可能是编写插件或使用Platform Channels
来执行此操作。您可以像this example中一样使用临时目录,然后将路径传递给android,在那里您将读取文件并将其插入到图库中:
MediaStore.Images.Media.insertImage(
getContentResolver(),
yourBitmap,
yourTitle ,
yourDescription
);`
如果您在其中一个flutter存储库中创建功能请求,并且有人决定通过为您编写插件来帮助您,那么您可能会很幸运。
答案 2 :(得分:3)
您收到的错误是因为您试图将照片保存到/data/user/0/com.example.mycameraapp/app_flutter
,它是目录,而不是文件。
您可以使用flutter_photokit包将照片/视频保存到iOS上用户的相机胶卷/自定义相册。您需要将照片捕获到设备的临时目录或应用程序目录,然后从那里将文件传输到用户的相机胶卷。示例的相关部分如下所示:
// At the top
import 'package:flutter_photokit/flutter_photokit.dart';
// Function in _CameraAppState
void _captureAndSaveToCameraRoll() async {
String outputFilePath = '$_appDirectoryPath/test.jpg';
// Capture the photo to the app directory
await controller.capture(outputFilePath);
// Save the photo to the user's camera roll
FlutterPhotokit.saveToCameraRoll(filePath: outputFilePath);
}
...
// In your build function
floatingActionButton: new FloatingActionButton(
tooltip: 'Increment',
child: new Icon(Icons.camera),
onPressed: _captureAndSaveToCameraRoll,
)
免责声明:我是该插件的作者。