file_picker - onPressed does not delete a card neither refresh the view - flutter

I am using File_Picker.dart
I am having an issue with one of the function I have written. When I press on the icon delete, the record is not deleted, and the screen is not refreshed. What I mean is that the card is still displayed.
Also, what I am trying to do it to be able to add a file one by one, without removing the file previously selected. But each time I am clicking on the button 'Open File picker' which is calling '_openFileExplorer()', the file selected previously is removed from the screen. I have not find how to stop this to happen.
If you can help me to solve this it would be appreciated. Many thanks.
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_storage/firebase_storage.dart';
class FilePickerDemo extends StatefulWidget {
#override
_FilePickerDemoState createState() => _FilePickerDemoState();
}
class _FilePickerDemoState extends State<FilePickerDemo> {
//FirebaseStorage storage = FirebaseStorage.instance;
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
late String _fileName;
List<PlatformFile>? _paths;
bool _loadingPath = false;
bool _multiPick = true;
FileType _fileType = FileType.media;
/*
#override
void initState() {
super.initState();
Firebase.initializeApp();
}
*/
void _openPictureFileExplorer() async {
setState(() => _loadingPath = true);
/*
try{
var files = (await FilePicker.platform.pickFiles(
type: _fileType,
allowMultiple: _multiPick,
))
?.files;
_paths = _paths!..addAll(files!.map((e) => e));
_loadingPath = false;
} on PlatformException catch (e) {
print("Unsupported operation" + e.toString());
} catch (ex) {
print('$ex');
}
*/
try {
_paths = (await FilePicker.platform.pickFiles(
type: _fileType,
allowMultiple: _multiPick,
))
?.files;
} on PlatformException catch (e) {
print("Unsupported operation" + e.toString());
} catch (ex) {
print('$ex');
}
if (!mounted) return;
setState(() {
_loadingPath = false;
print(_paths!.last.name);
_fileName = _paths != null ?
_paths!.map((e) => e.name).toString() : '...';
});
}
void _openDocumentFileExplorer() async {
setState(() => _loadingPath = true);
try{
var files = (await FilePicker.platform.pickFiles(
type: _fileType,
allowMultiple: _multiPick,
))
?.files;
_paths = _paths!..addAll(files!.map((e) => e));
_loadingPath = false;
} on PlatformException catch (e) {
print("Unsupported operation" + e.toString());
} catch (ex) {
print('$ex');
}
/*
try {
_paths = (await FilePicker.platform.pickFiles(
type: FileType.custom,
allowMultiple: _multiPick,
allowedExtensions: ['pdf','docx'],
))
?.files;
} on PlatformException catch (e) {
print("Unsupported operation" + e.toString());
} catch (ex) {
print('$ex');
}
if (!mounted) return;
setState(() {
_loadingPath = false;
print(_paths!.last.name);
_fileName = _paths != null ?
_paths!.map((e) => e.name).toString() : '...';
});
*/
}
void _clearCachedFiles() {
FilePicker.platform.clearTemporaryFiles().then((result) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
backgroundColor: result! ? Colors.green : Colors.red,
content: Text((result
? 'Temporary files removed with success.'
: 'Failed to clean temporary files')),
),
);
});
}
// Select and image from the gallery or take a picture with the camera
// Then upload to Firebase Storage
/*
Future<void> _upload() async {
try {
final String fileName = _fileName;
File imageFile = File(_paths.toString());
try {
// Uploading the selected image with some custom meta data
await storage.ref(fileName).putFile(
imageFile,
);
// Refresh the UI
setState(() {});
} on FirebaseException catch (error) {
print(error);
}
} catch (err) {
print(err);
}
}
*/
// Delete the selected image
// This function is called when a trash icon is pressed
void _delete(int index) {
if(_paths!=null || _paths!.length> 1) {
_paths!.removeAt(index);
setState(() {});
print ('2:' +_paths!.length.toString());
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: const Text('File Picker example app'),
),
body: Center(
child: Padding(
padding: const EdgeInsets.only(left: 10.0, right: 10.0),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 20.0),
child:Card(
child:
Container(
// color: Colors.red,
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children:[
//Attachement
FlatButton(
onPressed: () { },
child:
InkWell(
child: Container(
// color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.attach_file),
Text('Attachement'),
],
)
),
onTap: () {
},
),
),
//Photo
FlatButton(
onPressed: () { },
child:
InkWell(
child: Container(
// color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.add_a_photo_rounded),
Text('Photo'),
],
)
),
onTap: () {_openPictureFileExplorer(); },
),
),
],
),
)),
),
Builder(
builder: (BuildContext context) => _loadingPath ?
Padding(
padding: const EdgeInsets.only(bottom: 10.0),
child:const CircularProgressIndicator(),
)
: _paths != null && _paths!.isNotEmpty
? Container(
padding: const EdgeInsets.only(bottom: 30.0),
height:
MediaQuery.of(context).size.height * 0.50,
child: Scrollbar(
child: ListView.separated(
itemCount:
_paths != null && _paths!.isNotEmpty
? _paths!.length
: 1,
itemBuilder:
(BuildContext context, int index) {
final bool isMultiPath =
_paths != null && _paths!.isNotEmpty;
final String name =
(isMultiPath
? _paths!
.map((e) => e.name)
.toList()[index]
: _fileName ?? '...');
final path = _paths!
.map((e) => e.path)
.toList()[index]
.toString();
return Container(
height: 114,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
elevation: 10,
child: ClipPath(
clipper: ShapeBorderClipper(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15))),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: 113,width: 113,
child: Image.file(File(path),
fit: BoxFit.fill,
width: double.infinity,),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text(name,
style: TextStyle(fontWeight: FontWeight.bold),),
),
),
Padding(
padding: const EdgeInsets.only(right:25.0),
child: IconButton(onPressed: (){
//delete a record and the card displaying this record
_delete(index);
},
icon:Icon (Icons.delete, color: Colors.red,),),
)
],
),
),
//subtitle: Text(path),
),
);
},
separatorBuilder:
(BuildContext context, int index) =>
const SizedBox(),)),)
:const SizedBox(child:Text('No documents')),
),
],
),
),
)),
),
);
}
}

The problem here is that the paths variable is made up of a list of PlatformFile and you are trying to remove a string value which doesn't exist in that list.
You can see this if you print the value of paths in your _delete() method. It should show [Instance of 'PlatformFile', Instance of 'PlatformFile'].
In a nutshell what you're trying to do could be visualized as such
[PlatformFile(), PlatformFile()].remove("some/path/string/value")
There can be a simple fix for this assuming the list isn't sorted, you can just send the index as the reference from the onTap .
It would look like this
void _delete(int ref) {
// remove the element at the passed index
_paths!.removeAt(ref);
setState(() {});
}
... some code...
itemBuilder: (BuildContext context, int index) {
... some code...
IconButton(
onPressed: () {
_delete(index);
setState(() {});
},
icon: Icon(
Icons.delete,
color: Colors.red,
),
... some code...
);
}
Alternatively if you can't be sure of the positions of the elements in the path list, this would be the best approach.
void _delete(String ref) {
var _platformFileObject = _paths!.where((element) => element.path == ref).first;
_paths!.remove(_platformFileObject);
setState(() {});
}
Edit to answer the second question;
In your _openFileExplorer() method, you are reassigning the new file objects rather than adding them to the _paths list. The solution would be to add the new file objects to the list.
FilePickerResult? filePickerResult = await
FilePicker.platform.pickFiles(
type: _fileType,
allowMultiple: _multiPick,
);
_paths?.addAll(filePickerResult!.files.map((e) => e));
Edited to answer the third question
The error you stated occurs because of this [lines 150-153]
itemCount:
_paths != null && _paths!.isNotEmpty
? _paths!.length
: 1
So when it goes to the builder it is trying build a list item but there's nothing to get since the list is actually empty. You should change 1 to 0.
In order to show a text when the _paths list is empty, you should try something like this.
Scrollbar(
child: !_paths!.isEmpty
? ListView.separated(
itemCount: _paths!.length,
itemBuilder: (BuildContext context, int index) {
return Container();
},
separatorBuilder: (BuildContext context, int index) {
return Container();
},
)
: Text("Text to display when _paths is empty"),
);
Additionally, I would recommend that you refactor your code for better readability.

Related

How to call a function only once while the page is active in flutter

I have a dart page voterhome(like dashboard),at first when I arrive at voterhome it will call the getuserdetails() function and get the adhar of user to pass it to other pages so I can navigate to other pages (like vote,voteregister ..etc)
when I return back to voterhome from other pages it will call the getuserdetails()function again because the function is inside initstate() I don't want this to happen how can I do that
my code :
voterhome.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:election/services/IntoLogin.dart';
import 'package:election/pages/Voter/Vote.dart';
import 'package:election/pages/Voter/VoteRegister.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:web3dart/web3dart.dart';
import '../../services/Auth.dart';
import '../../utils/Constants.dart';
import '../../services/Electioninfo.dart';
import '../../services/VerifyEmail.dart';
class VoterHome extends StatefulWidget {
//getting required parameters to pass on to vote and authorize
final Web3Client ethClient;
final String electionName;
final String electionaddress;
const VoterHome({Key? key, required this.ethClient, required this.electionName, required this.electionaddress}) : super(key: key);
#override
State<VoterHome> createState() => _VoterHomeState();
}
class _VoterHomeState extends State<VoterHome> {
//creating clients
late Client? httpClient;//http client
late Web3Client? ethclient;// eth client
//sign out user
final User? user = Auth().currentuser;
Future<void>signOut()async{
await Auth().signOut();
if(!mounted)return;
Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (context)=>IntroLogin()), (route) => false);
}
// voters info
var email;
var adhar;
var name;
var phone;
//checking if voter authorized or voted // dont have to do this because we does this on the respected pages
late bool isAuth = false;//if he is authorized
late bool isVoted = false;//if he is voted
Future<void>getUserDetail() async {
try {
final DocumentSnapshot voters = await FirebaseFirestore.instance
.collection('voters')
.doc(user?.email)
.get();
if (voters.data() != null) {
email = voters.get('email');
name = voters.get('name');
phone = voters.get('phone');
adhar = voters.get('adharnum');
print('adhar is $adhar');
}else{
print('cannot find details');
}
showSnackBar(succesdetailsnackSnack);
} catch (e) {
if (kDebugMode) {
print('get check user ::::: $e');
showSnackBar(errordetailsnackSnack);
}
}
}//function to check ends
#override
void initState() {
httpClient = Client();
ethclient = Web3Client(infura_url, httpClient!);
WidgetsBinding.instance.addPostFrameCallback((_) async {
await getUserDetail();
setState(() { });
});
super.initState();
}
#override
Widget build(BuildContext context) {
Map<String,dynamic> voterdata = {'name':name,'adharnum':adhar.toString(),'email':email,};
if(user!.emailVerified){
return Scaffold(
appBar: AppBar(
leading: IconButton(onPressed: () { signOut(); }, icon: const Icon(Icons.logout),),
actions: [IconButton(onPressed:(){setState(() {});}, icon: const Icon(Icons.refresh))],
title: const Text('Voter DASHBOARD'),backgroundColor: Colors.cyan,),
body: SingleChildScrollView(
child: Column(
children: [
Container(
padding: const EdgeInsets.all(24),
margin: const EdgeInsets.only(bottom: 16),
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => VoteRegister(electionName:widget.electionName,
ethClient: widget.ethClient, electionaddress:widget.electionaddress,adhar:adhar,)));
},
child: Card(borderOnForeground: true,elevation: 4,
child: Column(
children: [
Container(height: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
image: const DecorationImage(
image: AssetImage('assets/undraw/electionday.png')))),
Container(decoration: const BoxDecoration(color: Colors.cyan),width: double.infinity,
child: const Center(
child: Text('Register to Vote',style: TextStyle(
fontWeight: FontWeight.bold,fontSize:16,color: Colors.white),),
),
)
],
),
),
),
),
Container(
padding: const EdgeInsets.all(24),
margin: const EdgeInsets.only(bottom: 16),
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => VoterVote(ethClient:ethclient!,electionName:widget.electionName,
electionaddress:widget.electionaddress ,votermap:voterdata,)));
},
child: Card(borderOnForeground: true,elevation: 4,
child: Column(
children: [
Container(height: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
image: const DecorationImage(
image: AssetImage('assets/undraw/upvote.png')))),
Container(decoration: const BoxDecoration(color: Colors.cyan),width: double.infinity,
child: const Center(
child: Text('Vote',style: TextStyle(fontWeight: FontWeight.bold,fontSize:16,color: Colors.white),),
),
)
],
),
),
),
),
Container(
padding: const EdgeInsets.all(24),
margin: const EdgeInsets.only(bottom: 16),
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ElectionInfo(ethClient:ethclient!,electionName:widget.electionName,
electionAddress:widget.electionaddress,)));
},
child: Card(borderOnForeground: true,elevation: 4,
child: Column(
children: [
Container(height: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
image: const DecorationImage(
image: AssetImage('assets/undraw/electionday.png')))),
Container(decoration: const BoxDecoration(color: Colors.cyan),width: double.infinity,
child: const Center(
child: Text('Election details',style: TextStyle(
fontWeight: FontWeight.bold,fontSize:16,color: Colors.white),),
),
)
],
),
),
),
),
],
),
)
);
}else{
return Scaffold(
appBar:AppBar( ///app bar
backgroundColor: Colors.cyan,
leading: IconButton(
onPressed: () {
signOut();
},
icon: const Icon(Icons.logout_sharp),
),
title: const Text('Verify Voter email'),
actions: [
IconButton(
onPressed: () {
refresh();
},
icon: const Icon(Icons.refresh))
],
),
body: Container(margin: const EdgeInsets.only(top: 56),
child: Center(
child: Column(
children: [
Text('Your Email ${user?.email} is not verified'),
const SizedBox(height: 24,),
ElevatedButton(
onPressed: () {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => const VerifyEmail()),
(route) => false);
},
child: const Text('Verify Email'))
],
),
),
),
);
}
}
//function to refresh using setstate
void refresh() {
setState(() {});
}
//snackbar
SnackBar errordetailsnackSnack = const SnackBar(content: Text('You are not logged in if you are please check your internet connection'));
SnackBar succesdetailsnackSnack = const SnackBar(content: Text('successfull'));
SnackBar votedSnack = const SnackBar(content: Text('You have already voted'));
SnackBar RegisterSnack = const SnackBar(content: Text('You have already registered'));
// SnackBar errorSnack = const SnackBar(content: Text('Fill all the details'));
// SnackBar datanullSnack = const SnackBar(content: Text('No users registerd yet'));
//function to show snackbar
ScaffoldFeatureController<SnackBar, SnackBarClosedReason> showSnackBar(SnackBar snackBar) {
return ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
}
vote.dart //when i go to voterhome() from this it again calls the function
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:election/pages/Voter/VoterHome.dart';
import 'package:election/utils/Constants.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:web3dart/web3dart.dart';
import '../../services/Auth.dart';
import '../../services/functions.dart';
import '../../services/IntoLogin.dart';
class VoterVote extends StatefulWidget {
final Web3Client ethClient;
final String electionName;
final String electionaddress;
final votermap;
const VoterVote({Key? key, required this.ethClient, required this.electionName, required this.electionaddress, this.votermap,}) : super(key: key);
#override
State<VoterVote> createState() => _VoterVoteState();
}
class _VoterVoteState extends State<VoterVote> {
final User? user = Auth().currentuser;//fi// rebase auth current user initialization
//sign out user function
Future<void> signOut() async {
if (!mounted) return;
await Auth().signOut();
if (!mounted) return;
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => IntroLogin()),
(route) => false);
}
//checking if the voter is already voted
late bool isAuth = false;
late bool isVoted = false;
Future<void>getUserDetail() async {
var voterdetails = widget.votermap;
try {
final DocumentSnapshot voters = await FirebaseFirestore.instance
.collection('Election')
.doc(widget.electionName).collection('voterAuth').doc(voterdetails['adharnum'])
.get();
if (voters.data() != null) {
isAuth = voters.get('isAuth');
isVoted = voters.get('isVoted');
}else{
isAuth = false;
isVoted= false;
print('cannot find details');
}
} catch (e) {
if (kDebugMode) {
print('get check user ::::: $e');
}
}
}//function to check ends
TextEditingController privatekeyController = TextEditingController();
#override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) async {
await getUserDetail();
setState(() { });
});
super.initState();
}
#override
Widget build(BuildContext context) {
if(isVoted== true && isAuth == true){
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.cyan,
leading: IconButton(onPressed: (){signOut();},icon: const Icon(Icons.logout_sharp),),
title:const Text('Vote'),
actions: [
IconButton(onPressed:(){
refresh();
}, icon: const Icon(Icons.refresh))
],
),
body: const Center(child: Text('you have already voted sir'),),
);
}else if(isVoted == false&&isAuth == true){
return Scaffold(
appBar:AppBar(
backgroundColor: Colors.cyan,
leading: IconButton(onPressed: (){signOut();},icon: const Icon(Icons.logout_sharp),),
title:const Text('Vote'),
actions: [
IconButton(onPressed:(){
refresh();
}, icon: const Icon(Icons.refresh))
],
),
body: Container(margin:const EdgeInsets.only(bottom: 56,top: 24),alignment: Alignment.topCenter,
child:SingleChildScrollView(
child: Column(
children: [
Center(
child: SelectableText("$voter_private_key && $voter_key2 && $voter_key3")
),
const SizedBox(height: 24,),
Container(padding: const EdgeInsets.all(16),
child: TextField(
controller: privatekeyController,
decoration:
const InputDecoration(hintText: 'Private key for voting',border: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(8))))),
),
const SizedBox(height: 24,),
SingleChildScrollView(
child: StreamBuilder<List>(stream:getCandidatesNum(widget.ethClient,widget.electionaddress).asStream(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
} else {
return Column(
children: [
for (int i = 0; i < snapshot.data![0].toInt(); i++)
FutureBuilder<List>(
future: candidateInfo(i, widget.ethClient,widget.electionaddress),
builder: (context, candidatesnapshot) {
if (candidatesnapshot.connectionState ==
ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
} else {
return Card( //card to represent the candidate
color: Colors.cyan,
child: SizedBox(height: 100,
child: Center(
child: ListTile(
title: Text('Name: ${candidatesnapshot.data![0][0]}'),
subtitle: Text('Votes: ${candidatesnapshot.data![0][1]}'),
leading: ConstrainedBox(
constraints: const BoxConstraints(
minHeight: 90,
minWidth: 90,
maxHeight: 100,
maxWidth: 100,
),
child:const Image(image: AssetImage('assets/undraw/electionday.png')),
),
trailing: ElevatedButton(
onPressed: ()async {
try{
await vote(i,widget.ethClient,privatekeyController.text,widget.electionaddress);
await registerAuth();
gotoDashboard();
showSnackBar(succesdetailsnackSnack);
}catch(e){
if (kDebugMode) {
print(e);
}
showSnackBar(errordetailsnackSnack);
gotoDashboard();
}
}, child: const Text('Vote'),),
),
),
),
);
}
})
],
);
}
},
),
),
],
),
),
),
);
}else{
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.cyan,
leading: IconButton(onPressed: (){signOut();},icon: const Icon(Icons.logout_sharp),),
title:const Text('Vote'),
actions: [
IconButton(onPressed:(){
refresh();
}, icon: const Icon(Icons.refresh))
],
),
body: const Center(child: Text('you are not authorized please authorize first'),),
);
}
}
//snackbar
SnackBar errordetailsnackSnack = const SnackBar(content: Text(' already voted or please check your internet connection'));
SnackBar succesdetailsnackSnack = const SnackBar(content: Text('successfull'));
SnackBar voterSnack = const SnackBar(content: Text('you are a voter logout from voter account'));
SnackBar adminSnack = const SnackBar(content: Text('you are an admin logout from Admin account'));
// SnackBar errorSnack = const SnackBar(content: Text('Fill all the details'));
// SnackBar datanullSnack = const SnackBar(content: Text('No users registerd yet'));
//function to show snackbar
ScaffoldFeatureController<SnackBar, SnackBarClosedReason> showSnackBar(SnackBar snackBar) {
return ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
void refresh() {
setState(() {});
}
Future<void> registerAuth() async {
var voterdetails = widget.votermap;
try {
await FirebaseFirestore.instance.collection('Election').doc(widget.electionName).collection('voterAuth').doc(voterdetails['adharnum']).update({'isVoted':true});
print('updated data aaaaaaaaaaaaaaa');
} catch (e) {
if (kDebugMode) {
print('failed to register on firebase $e');
}
}
}
void gotoDashboard(){
Navigator.pushAndRemoveUntil(context,MaterialPageRoute(builder:(context)=>VoterHome(ethClient: widget.ethClient,
electionName: widget.electionName, electionaddress: widget.electionaddress)), (route) => false);
}
}
One way to achieve what you want is by making your page retain its state.
Try this code
You have to add with AutomaticKeepAliveClientMixin to the screen like in the snippet below.
Override this #override bool get wantKeepAlive => true;.
Inside build method, add this super.build(context);.
class _TestScreen extends State<TestScreen> with AutomaticKeepAliveClientMixin<TestScreen> {
#override
bool get wantKeepAlive => true;
Widget build(BuildContext context) {
super.build(context);
return Scaffold();
}
}
After doing this, your page will not call initState() everytime that page is loaded.
When you navigate from VoteHome page to VoteRegister page, you use the push method. The push method returns a Future object. You can use the then method of Future to execute your code after VoteRegister was popped from the navigation stack or in other words the user pressed back button in appbar.
Navigator.of(context)
.push(MaterialPageRoute(
builder: (context) => VoteRegister(electionName:widget.electionName,ethClient: widget.ethClient, electionaddress:widget.electionaddress,adhar:adhar,)))
.then((value) {
// you can do what you need here
// setState etc.
// also reload your data here
});

Why does Flutter Camera Plugin return video content type as Application/octet-stream

hello guys!
i am using flutter story view package to implement story functionality in my app and i am using camera plugin to record video and upload, however the content type of the uploaded video is application/octet-stream when i receive it on my server and only when it is sent from ios. for android everything is fine and i get the content type as video/mp4.
can you guys please help me.
i have not done anything fancy i have just used the basic functionality of start recording and stop recording of the camra plugin.
// ignore_for_file: use_build_context_synchronously
List<CameraDescription>? cameras;
class CameraScreen extends StatefulWidget {
const CameraScreen({Key? key}) : super(key: key);
#override
State<CameraScreen> createState() => _CameraScreenState();
}
class _CameraScreenState extends State<CameraScreen> {
CameraController? _cameraController;
Future<void>? cameraValue;
bool flash = false;
bool iscamerafront = true;
static const _maxSeconds = 30;
ValueNotifier<bool> visible = ValueNotifier(false);
ValueNotifier<bool> isRecoring = ValueNotifier(false);
TimerProvider? _timerProvider;
#override
void initState() {
super.initState();
_timerProvider = Provider.of(context, listen: false);
_cameraController = CameraController(cameras![0], ResolutionPreset.veryHigh,
imageFormatGroup: ImageFormatGroup.bgra8888);
cameraValue = _cameraController?.initialize();
_cameraController?.prepareForVideoRecording();
lockCamera();
}
lockCamera() async {
await _cameraController!.lockCaptureOrientation();
}
#override
void dispose() {
super.dispose();
visible.dispose();
isRecoring.dispose();
_cameraController?.dispose();
}
#override
Widget build(BuildContext context) {
print("camera_screen");
final size = MediaQuery.of(context).size;
return Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
centerTitle: true,
title: ValueListenableBuilder<bool>(
valueListenable: visible,
builder: (context, value, child) {
return Visibility(
visible: value,
child: Container(
padding: const EdgeInsets.all(10),
width: 50,
height: 50,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.black.withOpacity(0.5)),
child: Center(
child: Consumer<TimerProvider>(
builder: (context, value, child) {
if (value.seconds == 0) {
if (_cameraController!.value.isRecordingVideo) {
stopRecording();
}
}
return Text(
value.seconds.toString(),
style: CustomStyles.fixAppBarTextStyle
.copyWith(color: Colors.white),
);
}),
),
));
}),
backgroundColor: Colors.transparent,
leadingWidth: 100,
leading: InkWell(
onTap: () {
Navigator.pop(context);
},
child: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Cancel",
style: CustomStyles.fixMediumBodyTextStyle
.copyWith(color: Colors.white),
),
)),
),
),
body: SafeArea(
top: false,
child: Stack(
children: [
FutureBuilder(
future: cameraValue,
builder: (context, snapshot) {
_cameraController?.lockCaptureOrientation();
if (snapshot.connectionState == ConnectionState.done) {
return Transform.scale(
scale: size.aspectRatio *
_cameraController!.value.aspectRatio <
1
? 1 /
(size.aspectRatio *
_cameraController!.value.aspectRatio)
: size.aspectRatio *
_cameraController!.value.aspectRatio,
child: Center(child: CameraPreview(_cameraController!)),
);
} else {
return const Center(
child: CircularProgressIndicator.adaptive(),
);
}
}),
Positioned(
bottom: 0.0,
child: Container(
padding: const EdgeInsets.only(top: 5, bottom: 5),
width: Dimensions.screenWidth,
child: Column(
children: [
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
padding: const EdgeInsets.all(4),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.black.withOpacity(0.5)),
child: Center(
child: IconButton(
icon: Icon(
flash ? Icons.flash_on : Icons.flash_off,
color: Colors.white,
size: 28,
),
onPressed: () {
setState(() {
flash = !flash;
});
flash
? _cameraController!
.setFlashMode(FlashMode.torch)
: _cameraController!
.setFlashMode(FlashMode.off);
}),
),
),
ValueListenableBuilder<bool>(
valueListenable: isRecoring,
builder: (context, value, child) {
return GestureDetector(
onLongPress: () {
startRecording();
},
onLongPressUp: () {
stopRecording();
},
onTap: () {
if (value == false) {
takePhoto(context);
}
},
child: value == true
? const CircleAvatar(
radius: 50,
backgroundColor: Colors.white30,
child: CircleAvatar(
radius: 35,
backgroundColor: Colors.red,
),
)
: const CircleAvatar(
radius: 35,
backgroundColor: Colors.white30,
child: CircleAvatar(
radius: 25,
backgroundColor: Colors.white,
),
));
}),
Container(
padding: const EdgeInsets.all(4),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.black.withOpacity(0.5)),
child: IconButton(
icon: const Icon(
Icons.flip_camera_ios,
color: Colors.white,
size: 28,
),
onPressed: () async {
setState(() {
iscamerafront = !iscamerafront;
});
int cameraPos = iscamerafront ? 0 : 1;
_cameraController = CameraController(
cameras![cameraPos], ResolutionPreset.high);
cameraValue = _cameraController?.initialize();
}),
),
],
),
addVerticalSpace(6),
const Text(
"Hold for Video, tap for photo",
style: TextStyle(
color: Colors.white,
),
textAlign: TextAlign.center,
),
addVerticalSpace(5),
],
),
),
),
],
),
),
);
}
void startRecording() async {
visible.value = true;
_timerProvider?.startCountDown(_maxSeconds);
isRecoring.value = true;
await _cameraController?.startVideoRecording();
}
void stopRecording() async {
XFile videopath = await _cameraController!.stopVideoRecording();
_timerProvider?.stopTimer();
isRecoring.value = false;
Navigator.push(
context,
MaterialPageRoute(
builder: (builder) => CameraResult(
image: File(videopath.path),
isImage: false,
))).then((value) {
visible.value = false;
});
}
void takePhoto(BuildContext context) async {
XFile file = await _cameraController!.takePicture();
SystemSound.play(SystemSoundType.click);
final img.Image? capturedImage =
img.decodeImage(await File(file.path).readAsBytes());
final img.Image orientedImage = img.flipHorizontal(capturedImage!);
File finalImage =
await File(file.path).writeAsBytes(img.encodeJpg(orientedImage));
Navigator.push(
context,
CupertinoPageRoute(
builder: (builder) => CameraResult(
image: finalImage,
isImage: true,
))).then((value) {
visible.value = false;
});
}
}
the upload function is as bellow
{File? shouts,
File? thumbnail,
int? duration,
bool? isImage,
required String userId,
required OnUploadProgressCallback onUploadProgress}) async {
assert(shouts != null);
try {
var url = Constants.POSTSHOUTURL;
final httpClient = FileService.getHttpClient();
final request = await httpClient.postUrl(Uri.parse(url));
int byteCount = 0;
var multipart;
if (isImage == false) {
multipart = await http.MultipartFile.fromPath(
'story-media', shouts!.path,
contentType: MediaType("video", "mp4"));
} else {
multipart = await http.MultipartFile.fromPath(
'story-media',
shouts!.path,
);
}
var multipart2 =
await http.MultipartFile.fromPath('thumbnail', thumbnail!.path);
var requestMultipart = http.MultipartRequest('POST', Uri.parse(url));
requestMultipart.fields["userid"] = userId.toString();
requestMultipart.fields["duration"] = duration.toString();
requestMultipart.headers['Content-type'] = 'multipart/form-data';
requestMultipart.files.add(multipart);
requestMultipart.files.add(multipart2);
var msStream = requestMultipart.finalize();
var totalByteLength = requestMultipart.contentLength;
request.contentLength = totalByteLength;
request.headers.add(HttpHeaders.authorizationHeader,
"Bearer ${Hive.box<UserData>(Constants.userDb).get(Hive.box<UserData>(Constants.userDb).keyAt(0))!.token}");
request.headers.set(HttpHeaders.contentTypeHeader,
requestMultipart.headers[HttpHeaders.contentTypeHeader]!);
Stream<List<int>> streamUpload = msStream.transform(
StreamTransformer.fromHandlers(
handleData: (data, sink) {
sink.add(data);
byteCount += data.length;
if (onUploadProgress != null) {
onUploadProgress(byteCount, totalByteLength);
// CALL STATUS CALLBACK;
}
},
handleError: (error, stack, sink) {
throw error;
},
handleDone: (sink) {
sink.close();
// UPLOAD DONE;
},
),
);
await request.addStream(streamUpload);
final httpResponse = await request.close();
var statusCode = httpResponse.statusCode;
if (statusCode ~/ 100 == 2) {
onUploadProgress(0, 0);
return await FileService.readResponseAsString(httpResponse);
}
return "";
} on SocketException {
throw FetchDataException("No internet to upload Shout!");
}
}```
i have used necessary info.plist setting also

RenderFlex children have non-zero flex but incoming height constraints are unbounded in flatter

I have a page code written in an android studio. On this page, I display a list of objects, as well as a widget to search for these objects. When I clicked on the search widget, I had the following problem: "The following statement was thrown during layout:
RenderFlex is overcrowded 31 pixels below.
The corresponding widget that caused the errors was: "But then I found the answer to this question and added" SingleChildScrollView ".
But then I had this problem: "RenderFlex have non-zero flexibility, but the input height limits are unlimited." . And I can't solve it in any way. I will be grateful for your help. Here is my code:
import 'package:flutter/material.dart';
import 'package:flutter_app_seals/model/post/form_unseals.dart';
import 'package:flutter_app_seals/model/post/form_seals.dart';
import 'package:flutter_app_seals/model/setting/globalvar.dart' as global;
import 'dart:async';
import 'dart:io';
import 'dart:convert';
void main() => runApp(JsonParseObjectSts_UN());
class JsonParseObjectSts_UN extends StatefulWidget {
JsonParseObjectSts_UN() : super();
#override
_JsonParseObjectsState createState() => _JsonParseObjectsState();
}
class _JsonParseObjectsState extends State <StatefulWidget> {
List<UserDetails> _searchResult = [];
List<UserDetails> _userDetails = [];
TextEditingController controller = new TextEditingController();
final String url = global.urlVar ;
// Get json result and convert it to model. Then add
Future<Null> getUserDetails() async {
HttpClient client = new HttpClient();
client.badCertificateCallback = ((X509Certificate cert, String host, int port) => true);
final request = await client
.getUrl(Uri.parse(url))
.timeout(Duration(seconds: 5));
HttpClientResponse response = await request.close();
var responseBody = await response.transform(utf8.decoder).join();
final responseJson = json.decode(responseBody);
setState(() {
for (Map user in responseJson) {
_userDetails.add(UserDetails.fromJson(user));
}
});
}
#override
void initState() {
super.initState();
getUserDetails();
}
Widget _buildUsersList() {
return new ListView.builder(
itemCount: _userDetails.length,
itemBuilder: (context, index) {
return new Card(
color: (_userDetails[index].sealed == "Так") ? Colors.redAccent : Colors.greenAccent,
margin: EdgeInsets.symmetric(vertical: 7),
child: ListTile(
title: Text(
_userDetails[index].name,
style: TextStyle(fontSize: 25),
),
subtitle: Text("Запломбований:${_userDetails[index].sealed}"),
leading: Icon(
Icons.home_outlined,
size: 30,
color: Colors.black87,
),
onTap: () =>
{
if ('Так' == _userDetails[index].sealed) {
global.nameObj = _userDetails[index].name,
global.sealsNumb = _userDetails[index].seal_number,
global.typesOp = 'Так',
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Unseals()),
)
}
else{
{
global.nameObj = _userDetails[index].name,
global.typesOp = 'Ні',
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Form_seals()),
)
}
}
}
),
);
},
);
}
Widget _buildSearchResults() {
return new ListView.builder(
itemCount: _searchResult.length,
itemBuilder: (context, i) {
return new Card(
color: (_searchResult[i].sealed == "Так") ? Colors.redAccent : Colors.greenAccent,
margin: EdgeInsets.symmetric(vertical: 7),
child: ListTile(
title: Text(
_searchResult[i].name,
style: TextStyle(fontSize: 25),
),
subtitle: Text("Запломбований:${_searchResult[i].sealed}"),
leading: Icon(
Icons.home_outlined,
size: 30,
color: Colors.black87,
),
onTap: () =>
{
if ('Так' == _searchResult[i].sealed) {
global.nameObj = _searchResult[i].name,
global.sealsNumb = _searchResult[i].seal_number,
global.typesOp = 'Так',
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Unseals()),
)
}
else{
{
global.nameObj = _searchResult[i].name,
global.typesOp = 'Ні',
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Form_seals()),
)
}
}
}
),
);
},
);
}
Widget _buildSearchBox() {
return new Padding(
padding: const EdgeInsets.all(8.0),
child: new Card(
child: new ListTile(
leading: new Icon(Icons.search),
title: new TextField(
controller: controller,
decoration: new InputDecoration(
hintText: 'Пошук', border: InputBorder.none),
onChanged: onSearchTextChanged,
),
trailing: new IconButton(
icon: new Icon(Icons.cancel),
onPressed: () {
controller.clear();
onSearchTextChanged('');
},
),
),
),
);
}
Widget _buildBody() {
return new Scaffold(
body:Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.blue, Colors.white],
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
),
child: SingleChildScrollView(
child:Column(
children: <Widget>[
new Container(
color: Theme.of(context).primaryColor, child: _buildSearchBox()),
new Expanded(
child: _searchResult.length != 0 || controller.text.isNotEmpty
? _buildSearchResults()
: _buildUsersList()),
],
),
),
),
);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
body: _buildBody()
);
}
onSearchTextChanged(String text) async {
_searchResult.clear();
if (text.isEmpty) {
setState(() {});
return;
}
_userDetails.forEach((userDetail) {
if (userDetail.name.contains(text) ) _searchResult.add(userDetail);
});
setState(() {});
}
}
class UserDetails {
final String name, seal_number,sealed;
UserDetails({this.name, this.sealed, this.seal_number});
factory UserDetails.fromJson(Map<String, dynamic> json) {
return new UserDetails(
sealed: json['sealed'],
name: json['name'],
seal_number: json['seal_number'],
);
}
}
My scrin:
My scrin when I want to use search:

how to increase the size of the window with the search result in flutter?

I have a page code written in an android studio. On this page, I display a list of objects, as well as a widget to search for these objects. When I clicked on the search widget,my list of objects is shrinking, and it is almost invisible (it is at the top). Can this be fixed somehow so that it can be seen on the whole page ??
import 'package:flutter/material.dart';
import 'package:flutter_app_seals/model/post/form_unseals.dart';
import 'package:flutter_app_seals/model/post/form_seals.dart';
import 'package:flutter_app_seals/model/setting/globalvar.dart' as global;
import 'dart:async';
import 'dart:io';
import 'dart:convert';
void main() => runApp(JsonParseObjectSts_UN());
class JsonParseObjectSts_UN extends StatefulWidget {
JsonParseObjectSts_UN() : super();
#override
_JsonParseObjectsState createState() => _JsonParseObjectsState();
}
class _JsonParseObjectsState extends State <StatefulWidget> {
List<UserDetails> _searchResult = [];
List<UserDetails> _userDetails = [];
TextEditingController controller = new TextEditingController();
final String url = global.urlVar ;
// Get json result and convert it to model. Then add
Future<Null> getUserDetails() async {
HttpClient client = new HttpClient();
client.badCertificateCallback = ((X509Certificate cert, String host, int port) => true);
final request = await client
.getUrl(Uri.parse(url))
.timeout(Duration(seconds: 5));
HttpClientResponse response = await request.close();
var responseBody = await response.transform(utf8.decoder).join();
final responseJson = json.decode(responseBody);
setState(() {
for (Map user in responseJson) {
_userDetails.add(UserDetails.fromJson(user));
}
});
}
#override
void initState() {
super.initState();
getUserDetails();
}
Widget _buildUsersList() {
return new ListView.builder(
itemCount: _userDetails.length,
itemBuilder: (context, index) {
return new Card(
color: (_userDetails[index].sealed == "Так") ? Colors.redAccent : Colors.greenAccent,
margin: EdgeInsets.symmetric(vertical: 7),
child: ListTile(
title: Text(
_userDetails[index].name,
style: TextStyle(fontSize: 25),
),
subtitle: Text("Запломбований:${_userDetails[index].sealed}"),
leading: Icon(
Icons.home_outlined,
size: 30,
color: Colors.black87,
),
onTap: () =>
{
if ('Так' == _userDetails[index].sealed) {
global.nameObj = _userDetails[index].name,
global.sealsNumb = _userDetails[index].seal_number,
global.typesOp = 'Так',
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Unseals()),
)
}
else{
{
global.nameObj = _userDetails[index].name,
global.typesOp = 'Ні',
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Form_seals()),
)
}
}
}
),
);
},
);
}
Widget _buildSearchResults() {
return new ListView.builder(
itemCount: _searchResult.length,
itemBuilder: (context, i) {
return new Card(
color: (_searchResult[i].sealed == "Так") ? Colors.redAccent : Colors.greenAccent,
margin: EdgeInsets.symmetric(vertical: 7),
child: ListTile(
title: Text(
_searchResult[i].name,
style: TextStyle(fontSize: 25),
),
subtitle: Text("Запломбований:${_searchResult[i].sealed}"),
leading: Icon(
Icons.home_outlined,
size: 30,
color: Colors.black87,
),
onTap: () =>
{
if ('Так' == _searchResult[i].sealed) {
global.nameObj = _searchResult[i].name,
global.sealsNumb = _searchResult[i].seal_number,
global.typesOp = 'Так',
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Unseals()),
)
}
else{
{
global.nameObj = _searchResult[i].name,
global.typesOp = 'Ні',
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Form_seals()),
)
}
}
}
),
);
},
);
}
Widget _buildSearchBox() {
return new Padding(
padding: EdgeInsets.all(7.0),
child: new Card(
child: new ListTile(
leading: new Icon(Icons.search),
title: new TextField(
controller: controller,
decoration: new InputDecoration(
hintText: 'Пошук', border: InputBorder.none),
onChanged: onSearchTextChanged,
),
trailing: new IconButton(
icon: new Icon(Icons.cancel),
onPressed: () {
controller.clear();
onSearchTextChanged('');
},
),
),
),
);
}
Widget _buildBody() {
return new Scaffold(
body:Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.blue, Colors.white],
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
),
child:Column(
children: <Widget>[
new Expanded( flex: 1, child: _buildSearchBox()),
new Expanded(flex:8,
child: _searchResult.length != 0 || controller.text.isNotEmpty
? _buildSearchResults()
: _buildUsersList()),
],
),
),
);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
body: _buildBody()
);
}
onSearchTextChanged(String text) async {
_searchResult.clear();
if (text.isEmpty) {
setState(() {});
return;
}
_userDetails.forEach((userDetail) {
if (userDetail.name.contains(text) ) _searchResult.add(userDetail);
});
setState(() {});
}
}
class UserDetails {
final String name, seal_number,sealed;
UserDetails({this.name, this.sealed, this.seal_number});
factory UserDetails.fromJson(Map<String, dynamic> json) {
return new UserDetails(
sealed: json['sealed'],
name: json['name'],
seal_number: json['seal_number'],
);
}
}
My page:
My page with search:
I have looked at your code several times, I just noticed a small error.
For the results of your searches, you try to display the "List" of searches in a ListView.builder, which is in a column in the parent container does not have a defined height.
Solution: Set a height for the main container and the problem will be solved

Flutter image_picker package returns null when trying to retrieve a video from the gallery

I am trying to build an app that lets users select videos and upload them, so for this, I am using the image_picker package. However, I am currently running tests and whenever I try to select a video from the gallery, instead of getting a file back I get null. I don't know if the problem is with how I am using the package or with permissions, although according to the package you don't need permissions for android.
Below the function in my code that is giving me trouble:
handleChooseFromGallery() async {
Navigator.pop(context);
File filePicked = await ImagePicker.pickVideo(
source: ImageSource.gallery,
maxDuration: Duration(seconds: 90),
);
//This line always returns false
print({'is file not null': filePicked != null});
setState(() {
if (filePicked != null) {
this.files.add(filePicked);
this.selected = true;
} else {
showError();
}
});
}
The complete code (minus completely irrelevant things):
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:golfapp/data/course_data.dart';
import 'package:golfapp/data/user_data.dart';
import 'package:provider/provider.dart';
import 'package:image_picker/image_picker.dart';
import 'package:uuid/uuid.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:golfapp/data/semana_data.dart';
import 'package:golfapp/widgets/chewie_item.dart';
final StorageReference storageRef = FirebaseStorage.instance.ref();
final postsRef = Firestore.instance.collection('posts');
final DateTime timestamp = DateTime.now();
class DetailScreen extends StatefulWidget {
final int index;
final String photoUrl;
final String videoUrl;
DetailScreen({this.index, this.photoUrl, this.videoUrl});
#override
_DetailScreenState createState() => _DetailScreenState();
}
class _DetailScreenState extends State<DetailScreen> {
bool isUploading = false;
bool selected = false;
List<File> files = [];
String postId = Uuid().v4();
TextEditingController captionController = TextEditingController();
showError() {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Row(
children: [
Padding(
padding: EdgeInsets.only(right: 10.0),
child: Text('Error'),
),
Icon(Icons.error_outline, size: 60.0),
],
),
content: SingleChildScrollView(
child: ListBody(
children: [
Text(
'Hubo un error con el video seleccionado.',
style: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.w600,
fontSize: 17.0,
),
),
],
),
),
);
},
);
}
clearImage() {
setState(() {
this.selected = false;
});
}
handleTakePhoto() async {
Navigator.pop(context);
File fileTaken = await ImagePicker.pickVideo(
source: ImageSource.camera,
maxDuration: Duration(seconds: 90),
);
setState(() {
if (fileTaken != null) {
this.files.add(fileTaken);
this.selected = true;
} else {
showError();
}
});
}
handleChooseFromGallery() async {
Navigator.pop(context);
File filePicked = await ImagePicker.pickVideo(
source: ImageSource.gallery,
maxDuration: Duration(seconds: 90),
);
print({'is file not null': filePicked != null});
setState(() {
if (filePicked != null) {
this.files.add(filePicked);
this.selected = true;
} else {
showError();
}
});
}
selectImage(parentContext) {
return showDialog(
context: parentContext,
builder: (context) {
return SimpleDialog(
title: Text("Seleccionar video"),
children: <Widget>[
SimpleDialogOption(
child: Text("Tomar video"),
onPressed: handleTakePhoto,
),
SimpleDialogOption(
child: Text("Video de la galería"),
onPressed: handleChooseFromGallery,
),
SimpleDialogOption(
child: Text("Cancelar"),
onPressed: () => Navigator.pop(context),
)
],
);
},
);
}
Future<String> uploadVideo(imageFile) async {
StorageUploadTask uploadTask = storageRef
.child(Provider.of<UserData>(context, listen: false).user.id)
.child(Provider.of<CourseData>(context, listen: false).course.uid)
.child(Provider.of<SemanaData>(context, listen: false).semana.uid)
.putFile(imageFile, StorageMetadata(contentType: 'video/mp4'));
StorageTaskSnapshot storageSnap = await uploadTask.onComplete;
String downloadUrl = await storageSnap.ref.getDownloadURL();
return downloadUrl;
}
createPostInFirestore({List<String> mediaUrl, String description}) {
postsRef
.document(Provider.of<UserData>(context, listen: false).user.id)
.collection("userPosts")
.document(Provider.of<CourseData>(context, listen: false).course.uid)
.setData({
"semana": Provider.of<SemanaData>(context, listen: false).semana.uid,
"postId": postId,
"ownerId": Provider.of<UserData>(context, listen: false).user.id,
"username": Provider.of<UserData>(context, listen: false).user.username,
"mediaUrl": mediaUrl,
"description": description,
"timestamp": timestamp,
"likes": {},
});
}
handleSubmit() async {
setState(() {
isUploading = true;
});
List<String> mediaUrlS = [];
for (File fileLoop in files) {
String mediaUrl = await uploadVideo(fileLoop);
mediaUrlS.add(mediaUrl);
}
createPostInFirestore(
mediaUrl: mediaUrlS,
description: captionController.text,
);
captionController.clear();
setState(() {
files = [];
isUploading = false;
postId = Uuid().v4();
selected = false;
});
}
Scaffold buildUploadForm() {
return Scaffold(
appBar: AppBar(
title: Text(
"Tu video",
style: TextStyle(color: Colors.black),
),
actions: [
FlatButton(
onPressed: files.length < 2 ? selectImage(context) : null,
child: Text(
'Seleccionar otro video',
),
),
FlatButton(
onPressed: isUploading ? null : () => handleSubmit(),
child: Text(
"Mandar",
),
),
],
),
body: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: files.length,
itemBuilder: (BuildContext context, int index) {
final File fileBuilder = files[index];
return Container(
height: 220.0,
width: MediaQuery.of(context).size.width * 0.8,
child: Center(
child: AspectRatio(
aspectRatio: 16 / 9,
child: Container(
child: ChewieListItem(
videoUrl: fileBuilder.path,
network: false,
file: fileBuilder,
),
),
),
),
);
}),
);
}
Widget buildNormalScreen () {
return Container(
child: GestureDetector(
onTap: () {
selectImage(context);
},
child: Container(
height: 50.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30.0),
color: Theme.of(context).accentColor,
),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Subir videos',
style: TextStyle(
fontFamily: 'Comfortaa',
fontSize: 17.0,
color: Colors.white,
),
),
],
),
),
),
),
);
}
#override
Widget build(BuildContext context) {
return !selected
? buildNormalScreen()
: buildUploadForm();
}
}
In the function at the top, I also tried doing something like ImagePicker.pickVideo().then((file){...}) but it didn't work.
I also added <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> to my "android/app/src/main/AndroidManifest.xml" file.
I also tried adding android:requestLegacyExternalStorage="true" inside the <application> tag in my "android/app/src/main/AndroidManifest.xml" file, but then I get an error:
I don't know what I should be changing either in my code or in one of the files in the android folder, any help is deeply appreciated.
Thank you very much in advance
Put the condition in the same function.
handleChooseFromGallery() async {
Navigator.pop(context);
File filePicked = await ImagePicker.pickVideo(
source: ImageSource.gallery,
maxDuration: Duration(seconds: 90),
//This line always returns false
print({'is file not null': filePicked != null});
setState(() {
if (filePicked != null) {
this.files.add(filePicked);
this.selected = true;
} else {
showError();
}
});
}
);