Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I'm trying to capture an image from camera and save it in cache(i.e., Directory.systemTemp available from dart.io package). It is working fine in debug mode. But when I build the release apk and install, it is not working. This is the code:
import 'dart:async';
import 'dart:io';
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
class CameraExampleHome extends StatefulWidget {
@override
_CameraExampleHomeState createState() {
return new _CameraExampleHomeState();
/// Returns a suitable camera icon for [direction].
IconData getCameraLensIcon(CameraLensDirection direction) {
switch (direction) {
case CameraLensDirection.back:
return Icons.camera_rear;
case CameraLensDirection.front:
return Icons.camera_front;
case CameraLensDirection.external:
return Icons.camera;
throw new ArgumentError('Unknown lens direction');
void logError(String code, String message) =>
print('Error: $code\nError Message: $message');
class _CameraExampleHomeState extends State<CameraExampleHome> {
CameraController controller;
String imagePath;
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
Future<List<CameraDescription>> getCameras() async {
return await availableCameras();
@override
Widget build(BuildContext context) {
return new Scaffold(
key: _scaffoldKey,
appBar: new AppBar(
title: const Text('Camera example'),
body: FutureBuilder(
future: getCameras(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return new Text('loading...');
default:
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
else {
if (snapshot.hasData)
return createCameraView(context, snapshot);
return new Text('Null');
/// Display the preview from the camera (or a message if the preview is not available).
Widget _cameraPreviewWidget() {
if (controller == null || !controller.value.isInitialized) {
return const Text(
'Tap a camera',
style: const TextStyle(
color: Colors.white,
fontSize: 24.0,
fontWeight: FontWeight.w900,
} else {
return new AspectRatio(
aspectRatio: controller.value.aspectRatio,
child: new CameraPreview(controller),
/// Display the thumbnail of the captured image or video
/// Display the control bar with buttons to take pictures and record videos.
Widget _captureControlRowWidget() {
return new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
new IconButton(
icon: const Icon(Icons.camera_alt),
color: Colors.blue,
onPressed: controller != null &&
controller.value.isInitialized &&
!controller.value.isRecordingVideo
? onTakePictureButtonPressed
: null,
/// Display a row of toggle to select the camera (or a message if no camera is available).
Widget _cameraTogglesRowWidget(var cameras) {
final List<Widget> toggles = <Widget>[];
if (cameras.isEmpty) {
return const Text('No camera found');
} else {
for (CameraDescription cameraDescription in cameras) {
toggles.add(
new SizedBox(
width: 90.0,
child: new RadioListTile<CameraDescription>(
title:
new Icon(getCameraLensIcon(cameraDescription.lensDirection)),
groupValue: controller?.description,
value: cameraDescription,
onChanged: controller != null && controller.value.isRecordingVideo
? null
: onNewCameraSelected,
return new Row(children: toggles);
String timestamp() => new DateTime.now().millisecondsSinceEpoch.toString();
void showInSnackBar(String message) {
_scaffoldKey.currentState
.showSnackBar(new SnackBar(content: new Text(message)));
void onNewCameraSelected(CameraDescription cameraDescription) async {
if (controller != null) {
await controller.dispose();
controller = new CameraController(cameraDescription, ResolutionPreset.high);
// If the controller is updated then update the UI.
controller.addListener(() {
if (mounted) setState(() {});
if (controller.value.hasError) {
showInSnackBar('Camera error ${controller.value.errorDescription}');
try {
await controller.initialize();
} on CameraException catch (e) {
_showCameraException(e);
if (mounted) {
setState(() {});
void onTakePictureButtonPressed() {
takePicture().then((String filePath) {
if (mounted) {
setState(() {
imagePath = filePath;
// videoController?.dispose();
// videoController = null;
if (filePath != null) showInSnackBar('Picture saved to $filePath');
Future<String> takePicture() async {
if (!controller.value.isInitialized) {
showInSnackBar('Error: select a camera first.');
return null;
//final Directory extDir = await getApplicationDocumentsDirectory();
final Directory extDir = Directory.systemTemp;
final String dirPath = '${extDir.path}/Pictures/flutter_test';
await new Directory(dirPath).create(recursive: true);
final String filePath = '$dirPath/${timestamp()}.jpg';
if (controller.value.isTakingPicture) {
// A capture is already pending, do nothing.
return null;
try {
await controller.takePicture(filePath);
} on CameraException catch (e) {
_showCameraException(e);
return null;
return filePath;
void _showCameraException(CameraException e) {
logError(e.code, e.description);
showInSnackBar('Error: ${e.code}\n${e.description}');
Widget createCameraView(BuildContext context, AsyncSnapshot snapshot) {
return new Column(
children: <Widget>[
new Expanded(
child: new Container(
width: MediaQuery.of(context).size.width,
child: _cameraPreviewWidget(),
_captureControlRowWidget(),
new Padding(
padding: const EdgeInsets.all(5.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
_cameraTogglesRowWidget(snapshot.data),
//_thumbnailWidget(),
class CameraApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new CameraExampleHome(),
List<CameraDescription> cameras;
void main() {
// Fetch the available cameras before initializing the app.
runApp(new CameraApp());
I've tried setting the directory to await getApplicationDocumentsDirectory() like this:
final Directory extDir = await getApplicationDocumentsDirectory();
//final Directory extDir = Directory.systemTemp;
final String dirPath = '${extDir.path}/Pictures/flutter_test';
await new Directory(dirPath).create(recursive: true);
final String filePath = '$dirPath/${timestamp()}.jpg';
Then the pictures are being saved both in debug mode and the release apk. But the pictures are lost once I relaunch the app. I want them to accessible even after the app is relaunched(that is the main reason why I want to use cache).
So what's going wrong when I try to save to cache in release build of the app?
use the path_provider
package instead to get the temp path https://pub.dartlang.org/packages/path_provider
Directory tempDir = await getTemporaryDirectory();
String tempPath = tempDir.path;
Directory.systemTemp
is only supposed to be used on the server/console.
–
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.