How to save File Selected from filepicker_windows in Disk (Flutter Desktop) - flutter

Please I need assistance.
I have written below code to saved file selected from filepicker_windows to C: drive.
filepicker_windows worked well and it get my C: drive successfully But not saving the file.
It gives me ERROR "Exception has occurred.
NoSuchMethodError (NoSuchMethodError: Class 'String' has no instance getter 'bodyBytes'.
Receiver: "C:\Users\norak\OneDrive\Pictures\afdb\Capture.PNG"
Tried calling: bodyBytes)"
Below is my code, please help correct it.
pubspec.yaml File
name: file_manager
description: A new Flutter project.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1
environment:
sdk: ">=2.12.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
filepicker_windows: ^2.0.0
path_provider: ^2.0.1
provider: ^5.0.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
MAIN PAGE
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:filepicker_windows/filepicker_windows.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Future<String> getPicturesPath() async {
Directory docDir = await getApplicationDocumentsDirectory();
var pathList = docDir.path.split('\\');
pathList[pathList.length - 1] = 'Pictures';
var picturePath = pathList.join('\\');
print(picturePath);
return picturePath;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("File Management"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'Testing',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
final file = OpenFilePicker()
..filterSpecification = {'All Files': '*.*'}
..defaultFilterIndex = 0
..defaultExtension = 'doc'
..title = 'Select a document';
final result = file.getFile();
if (result != null) {
print(result.path);
saveImage(result.path, 'ik.jpg');
print("Saved");
}
},
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
void saveImage(imageData, String imageName) async {
var picturesPath = await getPicturesPath();
var thetaImage = await File(join(picturesPath, 'theta_images', imageName))
.create(recursive: true);
await thetaImage.writeAsBytes(imageData.bodyBytes);
}
}
await thetaImage.writeAsBytes(imageData.bodyBytes); //This is the line that is given error
Please advice

Why don't you debug your code? It's a string. That's why you got the error.
Change the code to:
await thetaImage.writeAsBytes(File(imageData).readAsBytesSync());

> final directory = await getApplicationDocumentsDirectory();
final path = directory.path;
final file = File(path);

Related

How to test a saved file in flutter

This flutter web page reading-writing-files
provides an example of saving a file, in this case containing a counter. I have pasted this into an example app. How can I unit test the file saving part of it?
My failed test attempt is below the app code.
There are 2 issues:
How to write the test itself - what is the testable return from the
t = storage.writeCounter(counter);
how can I shut the app down and prove that the file persists and is later readable
main.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
void main() {
runApp(
MaterialApp(
title: 'Reading and Writing Files',
home: FlutterDemo(storage: CounterStorage()),
),
);
}
class CounterStorage {
Future<String> get _localPath async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
Future<File> get _localFile async {
final path = await _localPath;
return File('$path/counter.txt');
}
Future<int> readCounter() async {
try {
final file = await _localFile;
// Read the file
final contents = await file.readAsString();
return int.parse(contents);
} catch (e) {
// If encountering an error, return 0
return 0;
}
}
Future<File> writeCounter(int counter) async {
final file = await _localFile;
// Write the file
return file.writeAsString('$counter');
}
}
class FlutterDemo extends StatefulWidget {
const FlutterDemo({Key? key, required this.storage}) : super(key: key);
final CounterStorage storage;
#override
_FlutterDemoState createState() => _FlutterDemoState();
}
class _FlutterDemoState extends State<FlutterDemo> {
int _counter = 0;
#override
void initState() {
super.initState();
widget.storage.readCounter().then((int value) {
setState(() {
_counter = value;
});
});
}
Future<File> _incrementCounter() {
setState(() {
_counter++;
});
// Write the variable as a string to the file.
return widget.storage.writeCounter(_counter);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Reading and Writing Files'),
),
body: Center(
child: Text(
'Button tapped $_counter time${_counter == 1 ? '' : 's'}.',
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
counter_test.dart
import 'package:write_file_test/main.dart';
void main() {
test('Check file save works', () async {
final CounterStorage storage;
var counter = 6;
var t = storage.writeCounter(counter);
expect(find.text('1'), findsOneWidget);
});
}
pubspec.yaml
name: write_file_test
description: Flutter test file saving
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1
environment:
sdk: ">=2.12.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
path_provider: ^2.0.5
cupertino_icons: ^1.0.2
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^1.0.0
flutter:
uses-material-design: true

Unable to select image using Image Picker on Flutter Web (MissingPluginException)

Below I'm sharing my flutter code that simply selects an Image and displays it on screen after taking the required permissions. The code, however, runs fine on Android but gives a MissingPluginException(No implementation found for method requestPermissions on channel flutter.baseflow.com/permissions/methods) exception when I try to upload image on web.
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:permission_handler/permission_handler.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Project2',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
File _file = File("zz");
uploadImage() async {
final ImagePicker _picker = ImagePicker();
final XFile? image;
var permissionStatus = requestPermissions();
if (await permissionStatus.isGranted) {
image = await _picker.pickImage(source: ImageSource.gallery);
var selected = File(image!.path);
setState(() {
_file = selected;
});
} else {
showToast("Permission not granted");
}
}
Future<PermissionStatus> requestPermissions() async {
await Permission.photos.request();
return Permission.photos.status;
}
void showToast(String message) {
Fluttertoast.showToast(
msg: message,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0,
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Upload Image"),
),
body: Column(
children: [
(_file.path != "zz")
? Image.file(_file)
: Image.asset("assets/img/images.jpeg"),
SizedBox(
height: 20,
width: double.infinity,
),
ElevatedButton(
onPressed: () => uploadImage(),
child: Text("Upload"),
)
],
),
);
}
}
Following is the generated stacktrace on pressing upload button:
Error: MissingPluginException(No implementation found for method requestPermissions on channel flutter.baseflow.com/permissions/methods)
at Object.throw_ [as throw] (http://localhost:64931/dart_sdk.js:5041:11)
at MethodChannel._invokeMethod (http://localhost:64931/packages/flutter/src/services/system_channels.dart.lib.js:943:21)
at _invokeMethod.next (<anonymous>)
at http://localhost:64931/dart_sdk.js:37403:33
at _RootZone.runUnary (http://localhost:64931/dart_sdk.js:37274:59)
at _FutureListener.thenAwait.handleValue (http://localhost:64931/dart_sdk.js:32530:29)
at handleValueCallback (http://localhost:64931/dart_sdk.js:33057:49)
at Function._propagateToListeners (http://localhost:64931/dart_sdk.js:33095:17)
at _Future.new.[_completeWithValue] (http://localhost:64931/dart_sdk.js:32943:23)
at async._AsyncCallbackEntry.new.callback (http://localhost:64931/dart_sdk.js:32964:35)
at Object._microtaskLoop (http://localhost:64931/dart_sdk.js:37526:13)
at _startMicrotaskLoop (http://localhost:64931/dart_sdk.js:37532:13)
at http://localhost:64931/dart_sdk.js:33303:9
pubspec.yaml file:
environment:
sdk: ">=2.12.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
image_picker: ^0.8.3+3
permission_handler: ^8.1.4+2
fluttertoast: ^8.0.8
cupertino_icons: ^1.0.2
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
assets:
- assets/img/images.jpeg
PS: flutter clean and flutter run isn't working for Web version.
The problem is with the permissions handler package in Web. Permissions Handler package is built only for Android and IOS, and no permission is required to upload image on Web Platform, so using it on Web gives MissingPluginException.
The problem was resolved by adding conditional statements and separate implementations for Web And Mobile Platforms.
To check if the platform is web, you first need to add:
import 'package:flutter/foundation.dart' show kIsWeb;
Change the uploadImage() method as:
uploadImage() async {
var permissionStatus = requestPermissions();
// MOBILE
if (!kIsWeb && await permissionStatus.isGranted) {
final ImagePicker _picker = ImagePicker();
XFile? image = await _picker.pickImage(source: ImageSource.gallery);
if (image != null) {
var selected = File(image.path);
setState(() {
_file = selected;
});
} else {
showToast("No file selected");
}
}
// WEB
else if (kIsWeb) {
final ImagePicker _picker = ImagePicker();
XFile? image = await _picker.pickImage(source: ImageSource.gallery);
if (image != null) {
var f = await image.readAsBytes();
setState(() {
_file = File("a");
webImage = f;
});
} else {
showToast("No file selected");
}
} else {
showToast("Permission not granted");
}
}
And then finally add seperate implementations for Web and Android Image in build() method:
File _file = File("zz");
Uint8List webImage = Uint8List(10);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Upload Image"),
),
body: Column(
children: [
(_file.path == "zz")
? Image.asset("assets/img/images.jpeg")
: (kIsWeb)
? Image.memory(webImage)
: Image.file(_file),
SizedBox(
height: 20,
width: double.infinity,
),
ElevatedButton(
onPressed: () => uploadImage(),
child: Text("Upload"),
)
],
),
);
}

Flutter 1.22.6 - url_launcher - Sending HTML email

I have two problems with the url_launcher: ^5.7.10
First Problem:
When I try to send an email with html tag, on a real device, if I use Gmail application the body of my email is not well formated. I see the HTML tags. I tried with or without HTML5 doctype
Second Problem:
When I try to send an email with an Href tag the email body is cut at the equal sign.
My code is
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'URL Launcher',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'URL Launcher'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Future<void> _sendMailHtml(String url) async {
if (await canLaunch(url)) {
await launch(
url
);
} else {
throw 'Could not launch $url';
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: ListView(
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
onPressed: () => setState(() {
_launched = _sendMailHtml('mailto:smith#example.org?subject=News&body=<h1>Header 1</h1><p>Paragraph</p>');
}),
child: const Text('Send Mail HTML'),
),
RaisedButton(
onPressed: () => setState(() {
_launched = _sendMailHtml('mailto:smith#example.org?subject=News&body=<h1>Header 1</h1><p>Paragraph</p>Link<p>End of mail</p>');
}),
child: const Text('Send Mail HTML With HREF'),
),
],
),
],
),
);
}
}
My pubspec.yaml is
name: flutter_app
description: A new Flutter application.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1
environment:
sdk: ">=2.7.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
url_launcher: ^5.7.10
cupertino_icons: ^1.0.0
dev_dependencies:
flutter_test:
sdk: flutter
# The following section is specific to Flutter.
flutter:
uses-material-design: true
I did not try with flutter 2 because my app is in production and I have some dependencies errors.
For the first problem if I try with another email app, I can see the good formatting.
On Android 10...
screenshots :
first problem on Gmail app
on other email app
Second problem with Gmail and anchor tag
The mailto body parameter only supports plaintext messages. See this question.
If you want you can check out the mailer package which has an interface for sending HTML emails, as shown in the linked page.

Error: The getter 'length' was called on null

Error says:
NoSuchMethodError: The getter 'length' was called on null
It is a basic flutter music player App.
main.dart
import 'package:flute_music_player/flute_music_player.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<Song> _songs;
#override
void initState() {
// TODO: implement initState
super.initState();
initPlayer();
}
void initPlayer() async{
var songs = await MusicFinder.allSongs();
songs=new List.from(songs);
setState(() {
_songs = songs;
});
}
#override
Widget build(BuildContext context) {
Widget home(){
new Scaffold(
appBar: new AppBar(title: new Text("Music App"),
),
body: new ListView.builder(
itemCount: _songs.length,
itemBuilder: (context,int index){
return new ListTile(
leading: new CircleAvatar(
child: new Text(_songs[index].title[0]),
),
title: new Text(_songs[index].title),
);
}),
);
}
return new MaterialApp(
home: home(),
);
}
}
pubspec.yaml
name: music_player
description: A new Flutter application.
version: 1.0.0+1
environment:
sdk: ">=2.1.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
flute_music_player:
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
It should show the list of musics as result but gives an unexpected error.I am running on android.Plz help me out.
It should show the list of musics as result but gives an unexpected error.I am running on android.Plz help me out.
Change itemCount: _songs.length to itemCount: _songs?.length ?? 0 - it helps to avoid exception
Since you're performing an async operation, that would take certain amount of time so when your app first builds, the songs array is null. Try to start with an empty array instead of a null array: List<Song> _songs = []; then, when the async operation is completed the setState will make the widget to rebuild and show the array with data.

More than one file was found with OS independent path 'META-INF/androidx.exifinterface_exifinterface.version'

I'm using Google mlkit: ^0.9.0 for scanning bar-code in my Flutter project and when I run it this error occrues:
Note: C:\flutter\.pub-cache\hosted\pub.dartlang.org\mlkit-0.9.0\android\src\main\java\com\azihsoyn\flutter\mlkit\MlkitPlugin.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:transformResourcesWithMergeJavaResForDebug'.
> More than one file was found with OS independent path 'META-INF/androidx.exifinterface_exifinterface.version'
I don't know what the reason.
This is my pubsec.yaml file:
name: flutter_test_barcode
description: A new Flutter application for test ocr
version: 1.0.0+1
environment:
sdk: ">=2.0.0-dev.68.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
path_provider: 0.4.1
mlkit: ^0.9.0
image_picker: 0.4.12+1
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
And this is my Main.dart file:
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:mlkit/mlkit.dart';
void main() => runApp(new MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
File _file;
List<VisionText> _currentLabels = <VisionText>[];
FirebaseVisionTextDetector detector = FirebaseVisionTextDetector.instance;
#override
initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: new Text('Plugin example app'),
),
body: _buildBody(),
floatingActionButton: new FloatingActionButton(
onPressed: () async {
try {
//var file = await ImagePicker.pickImage(source: ImageSource.camera);
var file =
await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
_file = file;
});
try {
var currentLabels = await detector.detectFromPath(_file?.path);
setState(() {
_currentLabels = currentLabels;
});
} catch (e) {
print(e.toString());
}
} catch (e) {
print(e.toString());
}
},
child: new Icon(Icons.camera),
),
),
);
}
Widget _buildImage() {
return SizedBox(
height: 500.0,
child: new Center(
child: _file == null
? Text('No Image')
: new FutureBuilder<Size>(
future: _getImageSize(Image.file(_file, fit: BoxFit.fitWidth)),
builder: (BuildContext context, AsyncSnapshot<Size> snapshot) {
if (snapshot.hasData) {
return Container(
foregroundDecoration:
TextDetectDecoration(_currentLabels, snapshot.data),
child: Image.file(_file, fit: BoxFit.fitWidth));
} else {
return new Text('Detecting...');
}
},
),
),
);
}
Future<Size> _getImageSize(Image image) {
Completer<Size> completer = new Completer<Size>();
image.image.resolve(new ImageConfiguration()).addListener(
(ImageInfo info, bool _) => completer.complete(
Size(info.image.width.toDouble(), info.image.height.toDouble())));
return completer.future;
}
Widget _buildBody() {
return Container(
child: Column(
children: <Widget>[
_buildImage(),
_buildList(_currentLabels),
],
),
);
}
Widget _buildList(List<VisionText> texts) {
if (texts.length == 0) {
return Text('Empty');
}
return Expanded(
child: Container(
child: ListView.builder(
padding: const EdgeInsets.all(1.0),
itemCount: texts.length,
itemBuilder: (context, i) {
return _buildRow(texts[i].text);
}),
),
);
}
Widget _buildRow(String text) {
return ListTile(
title: Text(
"Text: ${text}",
),
dense: true,
);
}
}
class TextDetectDecoration extends Decoration {
final Size _originalImageSize;
final List<VisionText> _texts;
TextDetectDecoration(List<VisionText> texts, Size originalImageSize)
: _texts = texts,
_originalImageSize = originalImageSize;
#override
BoxPainter createBoxPainter([VoidCallback onChanged]) {
return new _TextDetectPainter(_texts, _originalImageSize);
}
}
class _TextDetectPainter extends BoxPainter {
final List<VisionText> _texts;
final Size _originalImageSize;
_TextDetectPainter(texts, originalImageSize)
: _texts = texts,
_originalImageSize = originalImageSize;
#override
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
final paint = new Paint()
..strokeWidth = 2.0
..color = Colors.red
..style = PaintingStyle.stroke;
print("original Image Size : ${_originalImageSize}");
final _heightRatio = _originalImageSize.height / configuration.size.height;
final _widthRatio = _originalImageSize.width / configuration.size.width;
for (var text in _texts) {
print("text : ${text.text}, rect : ${text.rect}");
final _rect = Rect.fromLTRB(
offset.dx + text.rect.left / _widthRatio,
offset.dy + text.rect.top / _heightRatio,
offset.dx + text.rect.right / _widthRatio,
offset.dy + text.rect.bottom / _heightRatio);
//final _rect = Rect.fromLTRB(24.0, 115.0, 75.0, 131.2);
print("_rect : ${_rect}");
canvas.drawRect(_rect, paint);
}
print("offset : ${offset}");
print("configuration : ${configuration}");
final rect = offset & configuration.size;
print("rect container : ${rect}");
//canvas.drawRect(rect, paint);
canvas.restore();
}
}
I changed libraries version according to Google Android X Compatibility documentation but the error still exists! Please help me
The problem was solved finally by changing version library of mlkit and some other libraries in pubspec.yaml file that I guessed they may have conflict with this. The key note is that '^' sign before version number should be removed to make sure which version number is exactly used, not the latest available version.