I want to download a zip file and it should be extracted to the assigned directory through the flutter app but my app cant download the file so please help me
here is the code which doesn't download the file
if anyone knows how to resolve it please help me
problem is: the app can not download files and can't unzip it to assigned directory
`import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
class Tbutton extends StatefulWidget {
final String url;
final String fileName;
Tbutton({required this.url, required this.fileName});
#override
_TbuttonState createState() => _TbuttonState();
}
class _TbuttonState extends State<Tbutton> {
bool downloading = false;
var progressString = "";
#override
Widget build(BuildContext context) {
return Card(
color: Colors.green,
elevation: 6,
child: Container(
decoration: BoxDecoration(
color: Colors.green, borderRadius: BorderRadius.circular(10)),
height: 50,
width: double.infinity,
child: TextButton(
onPressed: downloading ? null : _startDownload,
child: Text(
downloading ? progressString : "Download",
style: TextStyle(
color: Colors.white, fontSize: 25, fontWeight: FontWeight.bold),
),
),
),
);
}
void _startDownload() async {
setState(() {
downloading = true;
progressString = "Downloading...";
});
var directory = await getExternalStorageDirectory();
var filePath = "${directory!.path}Android/emulated/${widget.fileName}";
// var androidDataDirectory = Directory("${directory.path}../../");
var uri = Uri.parse(widget.url);
var request = await HttpClient().getUrl(uri);
var response = await request.close();
var bytes = await consolidateHttpClientResponseBytes(response);
File file = File(filePath);
await file.writeAsBytes(bytes);
setState(() {
downloading = false;
progressString = "Download Complete";
});
}
}
`
Related
Hello friend i am new in flutter i need help i have project where almost different zip file hosted on sever every zip file have different audio with categories now i want if user want to download that zip file and extract audio then able to play in application it not visible in phone memory ?here example of code but this is for images and one zip file i take code from this url
https://www.coderzheaven.com/2019/06/07/download-zip-extract-it-and-show-the-images-file-in-list-in-ui/
here my code
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:archive/archive.dart';
import 'package:http/http.dart' as http;
import 'package:path_provider/path_provider.dart';
class DownloadAssetsDemo extends StatefulWidget {
DownloadAssetsDemo() : super();
final String title = "Download & Extract ZIP Demo";
#override
DownloadAssetsDemoState createState() => DownloadAssetsDemoState();
}
class DownloadAssetsDemoState extends State<DownloadAssetsDemo> {
//
bool _downloading;
String _dir;
List<String> _images, _tempImages;
String _zipPath = 'https://coderzheaven.com/youtube_flutter/images.zip';
String _localZipFileName = 'images.zip';
#override
void initState() {
super.initState();
_images = List();
_tempImages = List();
_downloading = false;
_initDir();
}
_initDir() async {
if (null == _dir) {
_dir = (await getApplicationDocumentsDirectory()).path;
}
}
Future<File> _downloadFile(String url, String fileName) async {
var req = await http.Client().get(Uri.parse(url));
var file = File('$_dir/$fileName');
return file.writeAsBytes(req.bodyBytes);
}
Future<void> _downloadZip() async {
setState(() {
_downloading = true;
});
_images.clear();
_tempImages.clear();
var zippedFile = await _downloadFile(_zipPath, _localZipFileName);
await unarchiveAndSave(zippedFile);
setState(() {
_images.addAll(_tempImages);
_downloading = false;
});
}
unarchiveAndSave(var zippedFile) async {
var bytes = zippedFile.readAsBytesSync();
var archive = ZipDecoder().decodeBytes(bytes);
for (var file in archive) {
var fileName = '$_dir/${file.name}';
if (file.isFile) {
var outFile = File(fileName);
//print('File:: ' + outFile.path);
_tempImages.add(outFile.path);
outFile = await outFile.create(recursive: true);
await outFile.writeAsBytes(file.content);
}
}
}
buildList() {
return Expanded(
child: ListView.builder(
itemCount: _images.length,
itemBuilder: (BuildContext context, int index) {
return Image.file(
File(_images[index]),
fit: BoxFit.fitWidth,
);
},
),
);
}
progress() {
return Container(
width: 25,
height: 25,
padding: EdgeInsets.fromLTRB(0.0, 20.0, 10.0, 20.0),
child: CircularProgressIndicator(
strokeWidth: 3.0,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: <Widget>[
_downloading ? progress() : Container(),
IconButton(
icon: Icon(Icons.file_download),
onPressed: () {
_downloadZip();
},
),
],
),
body: Container(
child: Column(
children: <Widget>[
buildList(),
],
),
),
);
}
}
_initDir() async {
if (null == _dir) {
_dir = (await getApplicationDocumentsDirectory()).path;
print("current dir--$_dir")
}
}
use like this
I am facing an issue with the state of my Flutter application.
A user can pick an image from their gallery using the Image Picker package from pub.dev. That goes smoothly, but I am then trying to save the picked image to local storage, with the help of the Path Provider package.
As demonstrated in this quick gif, you can see that picking an image indeed replaces the old one. However, when leaving the page and navigating back to it, the UI displays the old image instead of the new one.
Issue in this gif
Here is the code for the profile picture stateful widget:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'custom_profile_picture.dart';
import 'default_profile_picture.dart';
class ProfilePicture extends StatefulWidget {
const ProfilePicture({
Key? key,
}) : super(key: key);
#override
State<ProfilePicture> createState() => _ProfilePictureState();
}
class _ProfilePictureState extends State<ProfilePicture> {
final ImagePicker _picker = ImagePicker();
XFile? pickedFile;
File? localImage;
#override
void initState() {
super.initState();
loadImage();
}
#override
Widget build(BuildContext context) {
return Column(
children: [
pickedFile != null
? CustomProfilePicture(image: File(pickedFile!.path))
: const DefaultProfilePicture(),
TextButton(
onPressed: pickImage,
child: const Text(
'Change picture',
style: TextStyle(fontSize: 12),
),
),
],
);
}
void pickImage() async {
final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
if (image != null) {
print('New image picked');
setState(() {
pickedFile = image;
});
saveImage(image);
}
}
void saveImage(XFile img) async {
String path = (await getApplicationDocumentsDirectory()).path;
File convertedImg = File(img.path);
String fileName = "profilepicture";
File? localImage = await convertedImg.copy("$path/$fileName");
print("Image was saved under: $path/$fileName");
}
void loadImage() async {
String fileName = "profilepicture";
String path = (await getApplicationDocumentsDirectory()).path;
if (await File("$path/$fileName").exists()) {
print('The image exists. Loading image from:');
print('$path/$fileName');
setState(() {
pickedFile = XFile("$path/$fileName");
});
}
}
}
Here is the code for the Profile page, in which is located the profile picture component:
import 'package:flutter/material.dart';
import 'widgets/profile_picture.dart';
import 'widgets/custom_table.dart';
import 'widgets/about_me_content.dart';
import 'widgets/service_info_content.dart';
class ProfileView extends StatelessWidget {
const ProfileView({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFe3e3e3),
appBar: AppBar(
foregroundColor: Colors.blue,
title: const Text(
'Profile view',
style: TextStyle(fontWeight: FontWeight.bold),
),
centerTitle: true,
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
),
body: SingleChildScrollView(
clipBehavior: Clip.none,
physics: const AlwaysScrollableScrollPhysics(),
child: Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
child: Align(
alignment: Alignment.center,
child: Column(
children: [
const ProfilePicture(),
const Text(
'William Dupont',
style: TextStyle(fontSize: 26, fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
const SizedBox(height: 20),
CustomTable(tableTitle: 'About me', content: AboutMeContent(),),
const SizedBox(height: 20),
CustomTable(tableTitle: 'My service info', content: ServiceInfoContent(),),
],
),
),
),
),
);
}
}
Any question, let me know.
I have found a fix to this issue.
I evict the image at the current path using the evict method.
Code:
void loadImage() async {
String fileName = "profilepicture";
String path = (await getApplicationDocumentsDirectory()).path;
if (await File("$path/$fileName").exists()) {
print('The image exists. Loading image from:');
print('$path/$fileName');
await FileImage(File('$path/$fileName)).evict();
setState(() {
pickedFile = XFile("$path/$fileName");
});
}
}
I want to be able to make progress bar where the value changes based on a function. My problem is I am working with 3 different files. The first file main_page_test.dart where the code for calling the function is held. enigma_test.dart where the code for the function is held. Finally, loading_alert_dialog.dart where I keep the code for the AlertDialog containing the ProgressBar
To clarify, I want the application to display the AlertDialog when the function is called in main_page_test.dart. While the function is running I want it to update the ProgressBar and pass the filename of the file it is working on encrypting.
If there is anything else I can clarify on please let me know.
Here is the relevant code for main_page_test.dart:
import 'dart:io';
import 'package:fluent_ui/fluent_ui.dart';
import 'package:file_picker/file_picker.dart';
import '../functions/enigma_test.dart';
class MainPageTest extends StatefulWidget {
const MainPageTest({Key? key}) : super(key: key);
#override
State<MainPageTest> createState() => _MainPageTestState();
}
class _MainPageTestState extends State<MainPageTest> {
final double _buttonTextSize = 20.0;
final double _widgetWidth = 200.0;
List<File>? _files;
late final TextEditingController _textController;
late final FlyoutController _flyoutController;
#override
void initState() {
super.initState();
_textController = TextEditingController();
_flyoutController = FlyoutController();
}
#override
void dispose() {
_textController.dispose();
_flyoutController.dispose();
super.dispose();
}
void pickFiles() async {
FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ['txt'],
allowMultiple: true,
);
if (result != null) {
setState(() {
_files = result.paths.map((path) => File(path!)).toList();
});
} else {
setState(() {
_files = null;
});
}
}
#override
Widget build(BuildContext context) {
return Center(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: SizedBox(
width: _widgetWidth,
child: Button(
onPressed: () {
pickFiles();
},
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 12.0),
child: Text(
'Choose Files',
style: TextStyle(
fontSize: _buttonTextSize,
),
),
),
),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: SizedBox(
width: _widgetWidth,
child: Button(
onPressed: () async {
await EnigmaTest().encrypt(_files!);
},
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 12.0),
child: Text(
'Encrypt',
style: TextStyle(
fontSize: _buttonTextSize,
),
),
),
),
),
),
],
),
);
}
}
Here is the relevant code for enigma_test.dart:
import 'dart:developer';
import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as p;
import 'package:encrypt/encrypt.dart';
class EnigmaTest {
Future<void> encrypt(List<File> files) async {
const String keyAsString = '123';
final String encryptedPath = p.join(await _localPath, 'encrypted');
final Key key = Key.fromUtf8(keyAsString.padRight(32, ' '));
try {
for (File file in files) {
final contents = await file.readAsLines();
// getting the name of the file without the extension
final filename = p.basename(file.path);
File encrypedFile =
await File(p.join(encryptedPath, filename)).create(recursive: true);
var sink = encrypedFile.openWrite();
for (String line in contents) {
if (line == '') {
sink.writeln();
} else {
var encryptedLine = _aesEncryption(line, key);
sink.writeln(encryptedLine);
}
}
await sink.flush();
await sink.close();
}
} catch (e) {
//somethibng
inspect(e);
}
}
String _aesEncryption(String line, Key key) {
final iv = IV.fromLength(16);
final encrypter = Encrypter(AES(key));
final encrypted = encrypter.encrypt(line, iv: iv);
return encrypted.base16;
}
Future<String> get _localPath async {
final documentsDirectory = await getApplicationDocumentsDirectory();
final encyptedFilesDirectory =
p.join(documentsDirectory.path, "Dead Man's Enigma Output");
return encyptedFilesDirectory;
}
}
Here is the code for loading_alert_dialog.dart:
import 'package:fluent_ui/fluent_ui.dart';
class MyLoadingAlertDialog {
static showLoadingAlert(
BuildContext context, String filename, double progress) {
showDialog(
context: context,
builder: (context) {
return ContentDialog(
title: const Text('Progress'),
content: Column(
children: [
SizedBox(
width: double.infinity,
child: ProgressBar(value: progress, strokeWidth: 8),
),
Padding(
padding: const EdgeInsets.all(4.0),
child: Text(
'currently encrypting $filename...',
style: const TextStyle(
fontSize: 10.0, fontStyle: FontStyle.italic),
),
),
],
),
);
},
);
}
}
Well, that looks like a job for a simple state management solution; the simplest one you could go would be Provider and using something as simple as a ValueNotifier and a ValueListenableBuilder, that way you can have the main class trigger notifications to another class (in your case, the dialog) via the ValueNotifier.
I did a simple example of how this would play out in a Gist. Run it through DartPad and see how it works.
Pretty much is creating a provided service FileProcessingService that serves as the inter-widget communication. The MainPageTest class picks the files, launches the encryption logic (EnigmaTest) as well as the dialog MyLoadingAlertDialog; the EnigmaTest, as it processes each file, sends notifications via a ValueNotifier of type String representing the current file being processed, while the MyLoadingAlertDialog has a ValueListenableBuilder widget listening on that ValueNotifier and updating accordingly, all via the FileProcessingService provided service.
Check out the bottom animation of when you run the Gist on DartPad and how the communication goes. Hope this works for your purposes.
I'm trying to save a QR image and add sharing optionality for that, but while doing so I'm facing with this "findRenderObject was called on null" object.
How can I solve this error? This is the code below
GenerateQr.dart
import 'package:attendee/services/database.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'dart:ui';
import 'package:flutter/rendering.dart';
import 'package:intl/intl.dart';
import 'package:attendee/constants.dart';
import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
class GeneratePage extends StatefulWidget {
#override
State<StatefulWidget> createState() => GeneratePageState();
}
class GeneratePageState extends State<GeneratePage> {
String qrData =
"https://github.com/neon97"; // already generated qr code when the page opens
FirebaseAuth auth = FirebaseAuth.instance;
String subject;
GlobalKey globalKey = new GlobalKey();
final CollectionReference student_details =
FirebaseFirestore.instance.collection('students');
final CollectionReference tutor_details =
FirebaseFirestore.instance.collection("tutors");
String timeString;
bool _validate = false;
// String formattedDate = DateFormat('kk:mm:ss \n EEE d MMM').format(now);
static const double _topSectionTopPadding = 50.0;
static const double _topSectionBottomPadding = 20.0;
static const double _topSectionHeight = 50.0;
void _getTime() {
final String formattedDateTime =
DateFormat('yyyy-MM-dd \n kk:mm:ss').format(DateTime.now()).toString();
//DateFormat('yyyy-MM-dd').toString();
setState(() {
timeString = formattedDateTime;
});
}
#override
void initState() {
super.initState();
Timer.periodic(Duration(seconds: 1), (Timer t) => _getTime());
}
#override
Widget build(BuildContext context) {
var numberOfClasses;
return Scaffold(
appBar: AppBar(
title: Text('QR Code Generator'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.share),
onPressed: _captureAndSharePng,
)
],
),
body: SingleChildScrollView(
child: Container(
padding: EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
QrImage(
//plce where the QR Image will be shown
data: qrData,
),
SizedBox(
height: 40.0,
),
Text(
"New QR Link Generator",
style: TextStyle(fontSize: 20.0),
),
TextField(
controller: qrdataFeed,
decoration: InputDecoration(
hintText: "SUBJECT-anything",
errorText:
_validate ? "Please enter in Sub-Date format!" : null,
),
),
Padding(
padding: EdgeInsets.fromLTRB(40, 20, 40, 0),
child: MaterialButton(
minWidth: double.infinity,
height: 60,
onPressed: () async {
qrdataFeed.text
.contains(RegExp(r'^[a-zA-Z]*\-[a-zA-Z]*$'))
? _validate = false
: _validate = true;
if (qrdataFeed.text.isEmpty) {
//a little validation for the textfield
if (!mounted) return;
setState(() {
qrData = "";
});
} else {
int index = qrdataFeed.text.indexOf('-');
subject = qrdataFeed.text.substring(0, index);
print("Subject name is $subject");
String user = isTutor ? "tutors" : "students";
String uid = FirebaseAuth.instance.currentUser.uid;
numberOfClasses = await FirebaseFirestore.instance
.collection(user)
.doc(uid)
.get()
.then((value) {
return value.data()['numberOfClasses'];
});
String rollno = await FirebaseFirestore.instance
.collection(user)
.doc(uid)
.get()
.then((value) {
return value.data()['rollno'];
});
print('$numberOfClasses is printed pehle');
await DatabaseService().attendance(rollno);
setState(() {
qrData = qrdataFeed.text;
scanned = true;
print('done');
numberOfClasses += 1; //idhar se dekhke
print('$numberOfClasses is printed');
});
await tutor_details.doc(uid).set(
{'numberOfClasses': numberOfClasses},
SetOptions(merge: true));
}
},
shape: RoundedRectangleBorder(
side: BorderSide(
color: Colors.black,
),
borderRadius: BorderRadius.circular(50)),
child: Text(
"Generate QR",
style:
TextStyle(fontWeight: FontWeight.w600, fontSize: 18),
),
)),
],
),
),
),
);
}
final qrdataFeed = TextEditingController();
Future<void> _captureAndSharePng() async {
try {
RenderRepaintBoundary boundary =
globalKey.currentContext.findRenderObject();
print(boundary);
var image = await boundary.toImage();
ByteData byteData = await image.toByteData(format: ImageByteFormat.png);
Uint8List pngBytes = byteData.buffer.asUint8List();
final tempDir = await getTemporaryDirectory();
final file = await new File('${tempDir.path}/image.png').create();
await file.writeAsBytes(pngBytes);
final channel = const MethodChannel('channel:me.attendee.share/share');
channel.invokeMethod('shareFile', 'image.png');
} catch (e) {
print(e.toString());
}
}
}
The error is here:
RenderRepaintBoundary boundary = globalKey.currentContext.findRenderObject();
Try changing globalKey.currentContext with context and see if the error is solved
Bye :D
I have tried to export qr Code to an png Image, but it is not working because Flutter is telling me : type "RenderPadding" is not a subtype of type "RenderRepaintBoundary". does anyone has an idea how i can convert those type together ? or how i can make the code work ?
this ist the used function
#override
Future<void> _captureAndSharePng() async {
try {
RenderRepaintBoundary boundary =
globalKey.currentContext.findRenderObject();
var image = await boundary.toImage();
ByteData byteData = await image.toByteData(format: ImageByteFormat.png);
Uint8List pngBytes = byteData.buffer.asUint8List();
final tempDir = await getTemporaryDirectory();
final file = await new File('${tempDir.path}/image.png').create();
await file.writeAsBytes(pngBytes);
final channel = const MethodChannel('channel:me.simo.share/share');
channel.invokeMethod('shareFile', 'assets.png');
} catch (e) {
print(e.toString());
}
}
and here is all the Code:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:parse_server_sdk_flutter/parse_server_sdk.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'dart:ui';
import 'dart:async';
import 'dart:typed_data';
import 'package:flutter/rendering.dart';
import 'package:path_provider/path_provider.dart';
import 'package:team3/Common/navigate.dart';
import 'package:team3/qrCode/detail.dart';
class Generate extends StatefulWidget {
#override
_GenerateState createState() => _GenerateState();
}
class _GenerateState extends State<Generate> {
String qrData = "SHS HTW App";
GlobalKey globalKey = new GlobalKey();
final TextEditingController qrText = TextEditingController();
#override
Future<void> _captureAndSharePng() async {
try {
RenderRepaintBoundary boundary =
globalKey.currentContext.findRenderObject();
var image = await boundary.toImage();
ByteData byteData = await image.toByteData(format: ImageByteFormat.png);
Uint8List pngBytes = byteData.buffer.asUint8List();
final tempDir = await getTemporaryDirectory();
final file = await new File('${tempDir.path}/image.png').create();
await file.writeAsBytes(pngBytes);
final channel = const MethodChannel('channel:me.simo.share/share');
channel.invokeMethod('shareFile', 'assets.png');
} catch (e) {
print(e.toString());
}
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('QrCode Generate'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.share),
onPressed: () {
_captureAndSharePng();
},
),
],
),
body: Container(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
child: Expanded(
child: Padding(
padding: const EdgeInsets.fromLTRB(50, 10, 10, 180),
key: globalKey,
child: QrImage(
//place where the qr image will be shown
data: qrData,
size: 250,
),
),
),
),
SizedBox(
height: 40.0,
),
Text("get your data/ linked to the QR Code"),
TextField(
//place where we enter the text od data
controller: qrText,
decoration: InputDecoration(
hintText: "Enter the data/Link",
),
),
Padding(
padding: const EdgeInsets.fromLTRB(40, 20, 40, 20),
child: FlatButton(
padding: EdgeInsets.all(15.0),
child: Text("generate qr code"),
//what should ahppen when we press the button
onPressed: () {
if (qrText.text.isEmpty) {
setState(() {
qrData = "";
});
} else {
qrData = qrText.text;
}
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
side: BorderSide(color: Colors.green, width: 3.0)),
),
),
],
),
),
),
);
}
}
Wrap your QRImage widget in RepaintBoundary and try.
RepaintBoundary(
key: qrKey,
child: QrImage(
data: generateQRContrller.qrData.value,
backgroundColor: CupertinoColors.white,
)
)
Future<void> _captureAndSharePng(content) async {
try {
RenderRepaintBoundary boundary = qrKey.currentContext.findRenderObject();
var image = await boundary.toImage();
ByteData byteData = await image.toByteData(format: ImageByteFormat.png);
Uint8List pngBytes = byteData.buffer.asUint8List();
final tempDir = await getExternalStorageDirectory();
final file = await new File('${tempDir.path}/shareqr.png').create();
await file.writeAsBytes(pngBytes);
await Share.shareFiles([file.path], text: content);
} catch (e) {
print(e.toString());
}
}
https://github.com/theyakka/qr.flutter/issues/79
try changing this line
RenderRepaintBoundary boundary =
globalKey.currentContext.findRenderObject();
to
RenderRepaintBoundary boundary =
globalKey.currentContext!.findRenderObject() as RenderRepaintBoundary;