How to decode Base64 String to Image file with flutter - image

I am actually trying to convert an Image file to Base64 and decode Base64 String to Image file in Dart/Flutter. Indeed, my application takes pictures with the camera plugin and then, saves it in a database as a Base64 String (because I don't know any other way but may be there is more relevant ways to store several images?).
I encode with this code :
final path = join(
(await getTemporaryDirectory()).path,
'${DateTime.now()}.png',
);
await _controller.takePicture(path);
final bytes = File(path).readAsBytesSync();
String img64 = base64Encode(bytes);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DisplayPictureScreen(imageAnalysed: img64),
),
);
And decode with this one :
class DisplayPictureScreen extends StatelessWidget {
final String imageAnalysed;
const DisplayPictureScreen({Key key, this.imageAnalysed}) : super(key: key);
#override
Widget build(BuildContext context) {
final decodedBytes = base64Decode(imageAnalysed);
var fileImg= File("testImage.png");
fileImg..writeAsBytesSync(decodedBytes);
return Scaffold(
appBar: AppBar(title: Text('Display the Picture')),
body: Image.file(fileImg),
);
}
}
But there is this error :
The following FileSystemException was thrown building DisplayPictureScreen(dirty):
Cannot open file, path = 'testImage.png' (OS Error: Read-only file system, errno = 30)
How can I solve my problem and get an image from the Base64 String ?
Thank you for your help !

You can copy paste run full code below
You can use path_provider to get getApplicationDocumentsDirectory and use bool isLoading to control show image when write file finish
code snippet
void writeFile() async {
final decodedBytes = base64Decode(widget.imageAnalysed);
final directory = await getApplicationDocumentsDirectory();
fileImg = File('${directory.path}/testImage.png');
print(fileImg.path);
fileImg.writeAsBytesSync(List.from(decodedBytes));
setState(() {
isLoading = false;
});
}
#override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_){
writeFile();
});
...
#override
Widget build(BuildContext context) {
return isLoading ? CircularProgressIndicator() : Image.file(fileImg);
}
working demo
full code
import 'dart:convert';
import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:flutter/material.dart';
class DisplayPictureScreen extends StatefulWidget {
final String imageAnalysed;
const DisplayPictureScreen({Key key, this.imageAnalysed}) : super(key: key);
#override
_DisplayPictureScreenState createState() => _DisplayPictureScreenState();
}
class _DisplayPictureScreenState extends State<DisplayPictureScreen> {
File fileImg;
bool isLoading = true;
void writeFile() async {
final decodedBytes = base64Decode(widget.imageAnalysed);
final directory = await getApplicationDocumentsDirectory();
fileImg = File('${directory.path}/testImage.png');
print(fileImg.path);
fileImg.writeAsBytesSync(List.from(decodedBytes));
setState(() {
isLoading = false;
});
}
#override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_){
writeFile();
});
super.initState();
}
#override
Widget build(BuildContext context) {
return isLoading ? CircularProgressIndicator() : Image.file(fileImg);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
String base64String =
'''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''';
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
DisplayPictureScreen(imageAnalysed: base64String),
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}

Related

Flutter RawKeyboardListener and 2D hardware scanner returns random result in Windows app

I generate QR code with free text (53a7a000-958c-11ec-0a80-085a0034aec2) and scanning it in a Flutter Windows app with hardware 2d scanner. But it constantly returns wrong text. It can be less or wrong characters. But at the same time I'm running the same code in android app and it works perfect.
Here is code i'm using
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'RawKeyboardListener';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: const MyStatefulWidget(),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
final FocusNode _focusNode = FocusNode();
String _controller = '';
String? _message;
#override
void dispose() {
_focusNode.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
FocusScope.of(context).requestFocus(_focusNode);
final TextTheme textTheme = Theme.of(context).textTheme;
return Container(
color: Colors.white,
alignment: Alignment.center,
child: DefaultTextStyle(
style: textTheme.bodyText1!,
child: RawKeyboardListener(
focusNode: _focusNode,
onKey: (RawKeyEvent event) {
if (event is RawKeyDownEvent) {
if (event.physicalKey == PhysicalKeyboardKey.enter) {
print('ENTER');
setState(() {
_message = _controller;
_controller = '';
});
} else {
print(
'_handleKeyEvent Event data keyLabel ${event.data.keyLabel}');
_controller += event.data.keyLabel;
}
print('controller: $_controller');
}
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
_message ?? 'Press a key',
),
Text(
'${_message?.length}',
),
],
),
),
),
);
}
}

Flutter: Unable to load asset and path_provider until hot reload

I'm downloading an picture from the internet and saving it in the platform's directory.I get the platform's directory from path_provider and (await getApplicationDocumentsDirectory()).path.
On iOS it works very well but on android I always get Unable to load asset: <path_to_my_directory>.
EDIT: I get this error on first start, after a hot restart, it works very well...
Here's a code sample to test:
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool dataLoaded = false;
String pathToSave;
#override
void initState() {
downloadImage();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: dataLoaded ? getImageBody() : CircularProgressIndicator()
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
getImageBody() {
return Image.asset(pathToSave);
}
void downloadImage() async {
String url = 'https://github.githubassets.com/images/modules/open_graph/github-mark.png';
pathToSave = '${(await getApplicationDocumentsDirectory()).path}/github-mark.png';
await Dio().download(url, pathToSave);
print(pathToSave);
setState(() {
dataLoaded = true;
});
}
}
dependencies:
path_provider: ^1.6.11
dio: ^3.0.9
For all, who run in similar issues:
Image.asset(path) loads an asset, thats in the path BEFORE app start.
Image.file(path) loads an asset/file and only needs an reference to an file e.g. File(path). That means, that assets can be dynamically added or static added before app start.

onDonePress() for intro_slides implementation?

I am trying to edit the void onDonePress() function (the "demo" example from https://flutterappdev.com/2019/01/24/simple-and-configurable-app-introduction-slider-for-flutter/), however, my app is not doing what I am expecting it to do.
I wanted the "Done" button to redirect the user to a login page which I made in another dart file called Login.dart
This is my onDonePress implementation:
class _MyHomePageState extends State<MyHomePage> {
List<Slide> slides = new List();
#override
void initState() {
super.initState();
slides.add(
new Slide(
backgroundImage: "images/1.png",
backgroundImageFit: BoxFit.cover,
backgroundOpacity: 0,
backgroundOpacityColor: Colors.white,
),
);
slides.add(
new Slide(
backgroundImage: "images/2.png",
backgroundImageFit: BoxFit.cover,
backgroundOpacity: 0,
backgroundOpacityColor: Colors.white,
),
);
slides.add(
new Slide(
backgroundImage: "images/2.png",
backgroundImageFit: BoxFit.cover,
backgroundOpacity: 0,
backgroundOpacityColor: Colors.white,
),
);
}
void onSkipPress() {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => HomePage()),
);
}
void onDonePress() {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => HomePage()),
);
}
#override
Widget build(BuildContext context) {
return new IntroSlider(
slides: this.slides,
onDonePress: this.onDonePress,
onSkipPress: this.onSkipPress,
);
}
}
This is part of my next.dart file
import 'package:flutter/material.dart';
void main() => runApp(Login());
class Login extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: CompanyColors.pink[100],
),
home: HomePage(title: 'Welcome!'),
);
}
}
class HomePage extends StatefulWidget {
HomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
TextStyle style = TextStyle(fontFamily: 'Montserrat', fontSize: 20.0);
#override
Widget build(BuildContext context) {
//TextField: allows you to enter text with keyboard or onscreen keyboard
final email = TextField(
Any ideas on why it is not going to the login page? When I press "Done" the screen stays the same. I also have included import 'Login.dart' to my intro slides dart file. Thank you!

How to show local string in StatefulWidget?

I've learned How to use i18n via StatelessWidget for my flutter practice,
but still not work via StatefulWidget.
I can simply replace the following code
title: new Text(S.of(context).title)
with a const String, for example:
title: const Text("A Test Title");
So I think every thing else should be okay. The only problem is i18n not work.
Could some body help me, "How to use i18n via StatefulWidget on flutter ?"
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'generated/i18n.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatefulWidget {
MyApp({Key key, this.title}) : super(key: key);
final String title;
#override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
BuildContext c;
#override
void initState() {
super.initState();
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
var tiles = new List<Widget>();
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: new Text(S.of(context).title), // Here is the problem
),
body: new Stack(
children: <Widget>[
new Container(),
new ListView(
children: tiles,
)
],
),
),
localizationsDelegates: [S.delegate],
supportedLocales: S.delegate.supportedLocales,
localeResolutionCallback: S.delegate.resolution(
fallback: new Locale("en", "")
),
);
}
}
The context you're using doesn't have a MaterialApp as a parent. Instead, it has a MaterialApp as a child.
The problem is, S instance you're trying to fetch using S.of(context) is stored inside MaterialApp. Hence the error.
What you can instead do is use a different context where that context has MaterialApp in its parents.
The easiest way to achieves this is by wrapping a part of your app into a Builder.
Something like :
return MaterialApp(
home: Builder(
builder: (context) {
const title = S.of(context).title; // works now because the context used has a MaterialApp inside its parents
return Scaffold(...);
}
)
)

Flutter - Routing between different Views

So, I have this file:
import 'package:flutter/material.dart';
import "calculateDerivations.dart";
import "calculateRoots.dart";
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Ableitungen berechnen'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text(config.title)),
body: new Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
new InputWidget(),
]
),
);
}
}
class InputWidget extends StatefulWidget {
#override
InputWidgetState createState() => new InputWidgetState();
}
class InputWidgetState extends State<InputWidget> {
InputValue val = new InputValue(text: "");
String ersteAbleitung = "";
String zweiteAbleitung = "";
String dritteAbleitung = "";
String roots = "";
String function = "";
void _submitted(){
setState((){
/*
* Redirect here
*/
});
}
#override
Widget build(BuildContext context) {
return new Column(
children: [
new Input(
value: val,
labelText: 'Funktion hier eingeben',
onChanged: (InputValue newInputValue) {
setState(() {
val = newInputValue;
});
}),
new IconButton(
icon: new Icon(Icons.check),
onPressed: _submitted,
)
]
);
}
}
As soon as the user now clicks the IconButton (which calls _submitted), I want him to be redirected to a new View (Widget). How would I solve this routing problem in Flutter?
Thanks in advance
Normal route navigation might look like this:
new IconButton(
icon: new Icon(Icons.check),
onPressed: () {
Navigator.push(context, new MaterialPageRoute(
builder: (_) => new MyCustomView(),
);
)
)
You can also use named routes by passing a map of WidgetBuilders as the routes constructor argument for your MaterialApp, or by passing an onGenerateRoute handler. There's an example of named routes in the Flutter gallery.
If you don't want there to be an animation, see my answer to this question.

Resources