Unable to retrieve data from Firebase Realtime Database in Flutter Application [duplicate] - firebase

I am trying to create a simple app that adds posts to a firebase realtime database and shows them on a listview in flutter, but when I "post" it to the database, on the firebase console, the data value constantly appears as null. does anyone know what is wrong?
Here is a bit of my code -
post.dart
class Post {
Image coverImg;
File audioFile;
String body;
String author;
Set usersLiked = {};
DatabaseReference _id;
Post(this.body, this.author);
void likePost(User user) {
if (this.usersLiked.contains(user.uid)) {
this.usersLiked.remove(user.uid);
} else {
this.usersLiked.add(user.uid);
}
}
void update() {
updatePost(this, this._id);
}
void setId(DatabaseReference id) {
this._id = id;
}
Map<String, dynamic> toJson() {
return {
'body': this.body,
'author': this.author,
'usersLiked': this.usersLiked.toList()
};
}
}
Post createPost(record) {
Map<String, dynamic> attributes = {
'author': '',
'usersLiked': [],
'body': ''
};
record.forEach((key, value) => {attributes[key] = value});
Post post = new Post(attributes['body'], attributes['author']);
post.usersLiked = new Set.from(attributes['usersLiked']);
return post;
}
class PostList extends StatefulWidget {
final List<Post> listItems;
final User user;
PostList(this.listItems, this.user);
#override
_PostListState createState() => _PostListState();
}
class _PostListState extends State<PostList> {
void like(Function callBack) {
this.setState(() {
callBack();
});
}
#override
void initState() {
super.initState();
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: this.widget.listItems.length,
itemBuilder: (context, index) {
var post = this.widget.listItems[index];
return Card(
elevation: 7.0,
color: Colors.white,
child: Column(
children: [
Row(
children: [
IconButton(
icon: Icon(
Icons.play_circle_outline,
color: Colors.black,
size: 30,
),
onPressed: () {},
),
Expanded(
child: ListTile(
title: Text(post.body,
style: TextStyle(
fontWeight: FontWeight.w600,
color: Colors.black)),
subtitle: Text(post.author,
style: TextStyle(color: Colors.black)),
),
),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(post.usersLiked.length.toString(),
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w600)),
IconButton(
icon: Icon(
Icons.thumb_up,
color: post.usersLiked.contains(widget.user.uid)
? Colors.blue
: Colors.black,
),
onPressed: () =>
this.like(() => post.likePost(widget.user)),
)
],
))
],
)
],
));
},
);
}
}
database.dart
final databaseReference = FirebaseDatabase.instance.reference();
DatabaseReference savePost(Post post) {
var id = databaseReference.child('posts/').push();
id.set(post.toJson());
return id;
}
void updatePost(Post post, DatabaseReference id) {
id.update(post.toJson());
}
Future<List<Post>> getAllPosts() async {
DataSnapshot dataSnapshot = await databaseReference.child('posts/').once();
List<Post> posts = [];
if (dataSnapshot.value != null) {
dataSnapshot.value.forEach((key, value) {
Post post = createPost(value);
post.setId(databaseReference.child('posts/' + key));
posts.add(post);
});
}
return posts;
}
home.dart
class UserInfoScreen extends StatefulWidget {
const UserInfoScreen({Key key, User user})
: _user = user,
super(key: key);
final User _user;
#override
_UserInfoScreenState createState() => _UserInfoScreenState();
}
class _UserInfoScreenState extends State<UserInfoScreen> {
User _user;
bool _isSigningOut = false;
List<Post> posts = [];
void newPost(String text) {
var post = new Post(text, widget._user.displayName);
post.setId(savePost(post));
this.setState(() {
posts.add(post);
});
}
void updatePosts() {
getAllPosts().then((posts) => {
this.setState(() {
this.posts = posts;
})
});
}
Route _routeToSignInScreen() {
return PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) => SignInScreen(),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
var begin = Offset(-1.0, 0.0);
var end = Offset.zero;
var curve = Curves.ease;
var tween =
Tween(begin: begin, end: end).chain(CurveTween(curve: curve));
return SlideTransition(
position: animation.drive(tween),
child: child,
);
},
);
}
#override
void initState() {
_user = widget._user;
// HOME PAGE
pageList.add(Scaffold(
backgroundColor: Colors.white,
body: Column(children: [
Expanded(
child: PostList(this.posts, _user),
),
]),
));
pageList.add(Test1());
pageList.add(Scaffold(
backgroundColor: Colors.white,
body: Column(
children: [
TextInputWidget(this.newPost, "Title:"),
],
),
));
pageList.add(Test3());
// ACCOUNT PAGE
pageList.add(
Scaffold(
backgroundColor: Colors.white,
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(),
_user.photoURL != null
? ClipOval(
child: Material(
color: Colors.grey.withOpacity(0.3),
child: Image.network(
_user.photoURL,
fit: BoxFit.fitHeight,
),
),
)
: ClipOval(
child: Material(
color: Colors.grey.withOpacity(0.3),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Icon(
Icons.person,
size: 60,
color: Colors.black,
),
),
),
),
SizedBox(height: 16.0),
Text(
'${_user.displayName}',
style: TextStyle(
color: Colors.black,
fontSize: 26,
fontWeight: FontWeight.w700),
),
SizedBox(height: 8.0),
Text(
' ${_user.email} ',
style: TextStyle(
color: Colors.black,
fontSize: 20,
letterSpacing: 0.5,
),
),
SizedBox(height: 60.0),
_isSigningOut
? CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
)
: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(
Colors.redAccent,
),
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
),
onPressed: () async {
setState(() {
_isSigningOut = true;
});
await Authentication.signOut(context: context);
setState(() {
_isSigningOut = false;
});
Navigator.of(context)
.pushReplacement(_routeToSignInScreen());
},
child: Padding(
padding: EdgeInsets.only(top: 8.0, bottom: 8.0),
child: Text(
'Logout',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
),
),
],
),
),
);
super.initState();
updatePosts();
}
#override
List<Widget> pageList = List<Widget>();
int _currentIndex = 0;
void onTabTapped(int index) {
setState(() {
_currentIndex = index;
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0.0,
backgroundColor: Colors.white,
title: Text(
'SoundFX',
style: TextStyle(color: Colors.black),
),
centerTitle: true,
),
body: IndexedStack(
index: _currentIndex,
children: pageList,
),
bottomNavigationBar: BottomNavigationBar(
unselectedItemColor: Colors.grey,
selectedItemColor: Colors.blue,
backgroundColor: Colors.white,
elevation: 19.0,
onTap: onTabTapped,
currentIndex: _currentIndex,
type: BottomNavigationBarType.fixed,
items: [
BottomNavigationBarItem(
icon: new Icon(Icons.home),
title: Container(
height: 1.0,
)),
BottomNavigationBarItem(
icon: new Icon(Icons.search),
title: Container(
height: 1.0,
)),
BottomNavigationBarItem(
icon: new Icon(
Icons.add_circle,
size: 40,
),
title: Container(
height: 1.0,
)),
BottomNavigationBarItem(
icon: new Icon(Icons.videocam),
title: Container(
height: 1.0,
)),
BottomNavigationBarItem(
icon: Icon(Icons.account_circle),
title: Container(
height: 1.0,
)),
],
),
);
}
}
class Test1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.green,
);
}
}
class Test2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.blue,
);
}
}
class Test3 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.yellow,
);
}
}
text-input.dart
class TextInputWidget extends StatefulWidget {
final Function(String) callback;
String label;
TextInputWidget(this.callback, this.label);
#override
_TextInputWidgetState createState() => _TextInputWidgetState();
}
class _TextInputWidgetState extends State<TextInputWidget> {
final controller = TextEditingController();
#override
void dispose() {
super.dispose();
controller.dispose();
}
void click() {
widget.callback(controller.text);
FocusScope.of(context).unfocus();
controller.clear();
}
void pickFiles() async {
FilePickerResult result =
await FilePicker.platform.pickFiles(type: FileType.any);
File file = File(result.files.first.path);
print(file);
}
#override
Widget build(BuildContext context) {
return Container(
height: 400,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
child: Container(
padding: EdgeInsets.all(20.0),
child: TextField(
controller: this.controller,
decoration: InputDecoration(
labelText: this.widget.label,
))),
),
Container(
child: ElevatedButton(onPressed: this.click, child: Text('Post')),
),
Container(
child:
ElevatedButton(onPressed: this.pickFiles, child: Text('test')),
)
],
),
);
}
}
PS: Also, note that some of the functions and classes are unused or basically useless, and some of the names are very stupid, but please do not comment on those if they are not related to the question, as those are just for some tests for features for me to add into the application.
Also, note that i followed this tutorial - https://www.youtube.com/playlist?list=PLzMcBGfZo4-knQWGK2IC49Q_5AnQrFpzv

firebaser here
Most likely the Firebase SDK is unable to read the URL of the database from its config file, because your database is hosted outside of the default (US) region.
If that is indeed the cause, you should specify the database URL in your code. By specifying it in your code, the SDK should able to connect to the database instance no matter what region it is hosted in.
This mean you should get your database with
FirebaseDatabase("your database URL").reference()
// Or
FirebaseDatabase(databaseURL: "your database URL").reference()
instead of
FirebaseDatabase.instance.reference()
This is documented here:
To get a reference to a database other than a us-central1 default dstabase, you must pass the database URL to getInstance() (or Kotlin+KTX database()) . For a us-central1 default database, you can call getInstance() (or database) without arguments.
So while this is documented, it is incredibly easy to overlook. I'm checking with our team if there's something we can do to make this configuration problem more obvious.

Related

Flutter and Firebase Authentication problem

Flutter fellow today I have a problem with the Firebase Authentication service.
Well then let me explain the situation. I have a page that let you select a type of user, if you select "Guest" you will push through the app's dashboard page Nav() without sign-in but if select "Sign-in" app will push you to the login page Login().
class SelectUser extends StatelessWidget {
const SelectUser({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFF20348F),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
padding: const EdgeInsets.all(15.0),
margin: const EdgeInsets.all(15.0),
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.amber,
borderRadius: BorderRadius.circular(45),
),
child: TextButton(
child: const Text('Guest'),
onPressed: () {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) => const Nav(),
),
(route) => false,
);
},
style: TextButton.styleFrom(
primary: const Color(0xFF20348F),
textStyle: const TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
)),
),
),
Container(
padding: const EdgeInsets.all(15.0),
margin: const EdgeInsets.all(15.0),
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.amber,
borderRadius: BorderRadius.circular(45),
),
child: TextButton(
child: const Text('Sign-In'),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (contex) {
return const Login();
}));
},
style: TextButton.styleFrom(
primary: const Color(0xFF20348F),
textStyle: const TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
)),
),
),
],
),
),
);
}
}
In Nav() I use BottomNavigationBarItem and have a several widget included Proflie()
inside.
I already test the sign-up, sign-out and registration function everything is perfectly fine but when I try to be tricky in Proflie() and I face...let's said the weird problem. First let's me show you the code in the Proflie().
class Profile extends StatefulWidget {
const Profile({Key? key}) : super(key: key);
#override
_ProfileState createState() => _ProfileState();
}
class _ProfileState extends State<Profile> {
String? _email;
DateTime? _creationTime;
DateTime? _lastSignIn;
bool? _status;
#override
Widget build(BuildContext context) {
userStatus();
return userForm();
}
userStatus() {
FirebaseAuth.instance.authStateChanges().listen((event) {
if (event == null) {
_status = false;
} else {
_status = true;
_email = FirebaseAuth.instance.currentUser!.email;
_creationTime =
FirebaseAuth.instance.currentUser!.metadata.creationTime;
_lastSignIn =
FirebaseAuth.instance.currentUser!.metadata.lastSignInTime;
}
});
}
Widget userForm() {
if (_status == true) {
return Scaffold(
appBar: defaultAppBar('Profile'),
body: Center(
child: ListView(
padding: const EdgeInsets.all(20),
children: [
Container(
margin: const EdgeInsets.all(30),
child: Text(
'Email: $_email',
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
),
),
Container(
margin: const EdgeInsets.all(30),
child: Text(
'Creation Time: $_creationTime',
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
),
),
Container(
margin: const EdgeInsets.all(30),
child: Text(
'Last Sign-In: $_lastSignIn',
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
),
),
const SizedBox(height: 45),
button('Change password', 1),
const SizedBox(height: 18),
button('Change email', 2),
const SizedBox(height: 18),
button('Sign-out', 0),
],
),
),
);
} else {
return Center(
child: ListView(
padding: const EdgeInsets.all(14),
children: <Widget>[
const SizedBox(height: 100),
Container(
margin: const EdgeInsets.all(30),
child: const Center(
child: Text(
'Please sign-in to use this Feature',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
),
),
const SizedBox(height: 50),
button('Login', 3),
const SizedBox(height: 18),
button('Register', 4),
],
),
);
}
}
Widget button(String txt, int _nav) {
Color? _color = const Color(0xFF20348F);
if (_nav == 0) {
_color = Colors.red;
}
return TextButton(
style: TextButton.styleFrom(
primary: _color,
textStyle: const TextStyle(
fontSize: 20,
),
),
child: Text(txt),
onPressed: () {
if (_nav == 0) {
FirebaseAuth.instance.signOut();
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) => const SelectUser(),
),
(route) => false,
);
} else {
Navigator.push(context, MaterialPageRoute(builder: (contex) {
if (_nav == 1) {
return const EditPass();
} else if (_nav == 2) {
return const EditEmail();
} else if (_nav == 3) {
return const Login();
} else {
return const Register();
}
}));
}
},
);
}
}
As you can see I'm trying to use userStatus() to identify the "User" and "Guest" and that function I use FirebaseAuth.instance.authStateChanges().listen((event) to check user state in Firebase Authentication(Not really sure am I doing the right way if not please teach me how to check user state) if event == null that mean no user sign-in right now. I'm just going to set _status = false so the "Guest" should found the else case in userForm(). Otherwise _status = true this mean user is signed-in and userForm() should go to if (_status == true) case.
Now the problem is when I success to sign-in on the Login(). In Profile() I ended up got the else case of userForm() instead but that not all! When I hot reloaded the IDE it turn out now I'm in the if (_status == true) case. Yeah like said it a weird problem the first time that app loaded the page it go to false case but when hot reloaded it turn to true case. I'm not so sure the error is from Profile() or Login(). I'm just going leave the Login() then.
class Login extends StatefulWidget {
const Login({Key? key}) : super(key: key);
#override
_LoginState createState() => _LoginState();
}
class _LoginState extends State<Login> {
final _formKey = GlobalKey<FormState>();
var _email = "";
var _password = "";
final emailController = TextEditingController();
final passwordController = TextEditingController();
bool _passwordVisible = true;
#override
void dispose() {
emailController.dispose();
passwordController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return formLogin();
}
Widget formLogin() {
return Scaffold(
appBar: defaultAppBar('Sign-In'),
body: Center(
child: Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.all(32),
child: ListView(
children: [
buildEmail(),
const SizedBox(height: 24),
buildPassword('Password', 'Your password...'),
const SizedBox(height: 50),
button('Sign-in', 0),
const SizedBox(height: 24),
button('Sign-up', 1),
],
),
),
),
),
);
}
userLogin() async {
try {
await FirebaseAuth.instance
.signInWithEmailAndPassword(email: _email, password: _password);
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) => const Nav(),
),
(route) => false,
);
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
backgroundColor: Colors.amber,
content: Text(
"Email not found",
style: TextStyle(fontSize: 16.0, color: Colors.black),
),
),
);
} else if (e.code == 'wrong-password') {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
backgroundColor: Colors.amber,
content: Text(
"Password incorrect",
style: TextStyle(fontSize: 16.0, color: Colors.black),
),
),
);
}
}
}
TextButton button(String txt, int nav) {
return TextButton(
style: TextButton.styleFrom(
primary: const Color(0xFF20348F),
textStyle: const TextStyle(
fontSize: 20,
),
),
child: Text(txt),
onPressed: () {
if (nav == 0) {
if (_formKey.currentState!.validate()) {
setState(() {
_email = emailController.text;
_password = passwordController.text;
});
userLogin();
}
} else {
_formKey.currentState!.reset();
Navigator.push(context, MaterialPageRoute(builder: (contex) {
return const Register();
}));
}
},
);
}
Widget buildEmail() {
return TextFormField(
decoration: const InputDecoration(
labelText: 'Email',
hintText: 'name#example.com',
prefixIcon: Icon(Icons.mail_outline),
border: OutlineInputBorder(),
errorStyle: TextStyle(color: Colors.redAccent, fontSize: 15),
),
controller: emailController,
validator: MultiValidator([
RequiredValidator(errorText: "Email is required"),
EmailValidator(errorText: "The format of email is incorrect")
]),
keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.done,
);
}
Widget buildPassword(String _txt1, String _txt2) {
return TextFormField(
obscureText: _passwordVisible,
decoration: InputDecoration(
labelText: _txt1,
hintText: _txt2,
suffixIcon: GestureDetector(
onTap: () {
setState(() {
_passwordVisible = !_passwordVisible;
});
},
child: Icon(
_passwordVisible ? Icons.visibility : Icons.visibility_off,
),
),
prefixIcon: const Icon(Icons.vpn_key_outlined),
border: const OutlineInputBorder(),
errorStyle: const TextStyle(color: Colors.redAccent, fontSize: 15),
),
controller: passwordController,
validator: RequiredValidator(errorText: "Password is required"),
textInputAction: TextInputAction.done,
);
}
}
If you guy could help me I'd gladly appreciated.
If you can create a .gist i would be of help to u, also in your profile page i can see issue's that u r listening to the user changes in the build, its very unpractical to add it in the build because flutter will call the build method multiple times , build should be clean, also potential memory leaks are there since u r not disposing the streams.

firebase firestore chat timestamp order not working corectly

below is my code, i have a chat made in flutter and it should be sorted by timestamp however it is still seemingly random, on firebase it is recording the correct time stamp in json and i thought i had it coded correctly with the firestore.collection order by call. image attached shows the messages they should be ordered 1-6
import 'package:flutter/material.dart';
import 'package:bardsf/constants.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
late String messageText;
class BodyBuildingChat extends StatefulWidget {
static const String id = 'body_building_chat';
#override
_BodyBuildingChatState createState() => _BodyBuildingChatState();
}
class _BodyBuildingChatState extends State<BodyBuildingChat> {
final messageTextController = TextEditingController();
final _firestore = FirebaseFirestore.instance;
final _auth = FirebaseAuth.instance;
late User loggedInUser;
#override
void initState() {
super.initState();
getCurrentUser();
}
void getCurrentUser() async {
try {
final user = await _auth.currentUser;
if (user != null) {
loggedInUser = user;
print(loggedInUser.email);
}
} catch (e) {
print (e);
}
}
// void getMessages() async{
// final messages = await _firestore.collection('messages').get();
// for (var message in messages.docs) {
// print(message.data().cast());
// }
// }
void messagesStream() async {
await for( var snapshot in _firestore.collection('bodybuilding').orderBy('timestamp').snapshots()) {
for (var message in snapshot.docs) {
print(message.data().cast());
}
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: null,
actions: <Widget>[
IconButton(
icon: Icon(Icons.close),
onPressed: () {
messagesStream();
_auth.signOut();
Navigator.pop(context);
}),
],
title: Text('🏔Body Building'),
backgroundColor: Colors.lightBlueAccent,
),
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
StreamBuilder<QuerySnapshot>(
stream: _firestore.collection('bodybuilding').snapshots(),
builder: (context, snapshot){
List<MessageBubble> messageBubbles = [];
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.lightBlueAccent,
),
);
}
final messages = snapshot.data!.docs.reversed;
for (var message in messages) {
final messageText = message['text'];
final messageSender = message['sender'];
final currentUser = loggedInUser.email;
final messageBubble = MessageBubble(
sender: messageSender,
text: messageText,
isMe: currentUser == messageSender,
);
messageBubbles.add(messageBubble);
}
return Expanded(
child: ListView(
reverse: true,
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 10),
children: messageBubbles,
),
);
},
),
Container(
decoration: kMessageContainerDecoration,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
controller: messageTextController,
onChanged: (value) {
messageText = value;
},
decoration: kMessageTextFieldDecoration,
),
),
TextButton(
onPressed: () {
messageTextController.clear();
_firestore.collection('bodybuilding').add({
'text': messageText,
'sender': loggedInUser.email,
'timestamp': FieldValue.serverTimestamp(),
});
},
child: Text(
'Send',
style: kSendButtonTextStyle,
),
),
],
),
),
],
),
),
);
}
}
class MessageBubble extends StatelessWidget {
MessageBubble({required this.sender,required this.text,required this.isMe});
final String sender;
final String text;
final bool isMe;
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: isMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: <Widget>[
Text(sender,
style: TextStyle(
fontSize: 12.0,
),
),
Material(
borderRadius: isMe ? BorderRadius.only(topLeft: Radius.circular(30.0),
bottomLeft: Radius.circular(30.0),
bottomRight: Radius.circular(30.0),
) : BorderRadius.only(topRight: Radius.circular(30.0),
bottomLeft: Radius.circular(30.0),
bottomRight: Radius.circular(30.0),
),
elevation: 5.0,
color: isMe ? Colors.lightBlueAccent : Colors.white,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 8.0, horizontal: 8.0),
child: Text('$text',
style: TextStyle( fontSize: 15.0,
color: isMe ? Colors.white : Colors.black,),
),
),
),
],
),
);
}
}
You did not use the appropriate stream.
Change this line
stream: _firestore.collection('bodybuilding').snapshots(),
into this line
stream: _firestore.collection('bodybuilding').orderBy('timestamp').snapshots(),
You will notice that you used the correct stream in the messagesStream but not in the StremBuilder.
Let me know if this does not help.

Why is the Firebase Realtime Database's data appearing as null in the console?

I am trying to create a simple app that adds posts to a firebase realtime database and shows them on a listview in flutter, but when I "post" it to the database, on the firebase console, the data value constantly appears as null. does anyone know what is wrong?
Here is a bit of my code -
post.dart
class Post {
Image coverImg;
File audioFile;
String body;
String author;
Set usersLiked = {};
DatabaseReference _id;
Post(this.body, this.author);
void likePost(User user) {
if (this.usersLiked.contains(user.uid)) {
this.usersLiked.remove(user.uid);
} else {
this.usersLiked.add(user.uid);
}
}
void update() {
updatePost(this, this._id);
}
void setId(DatabaseReference id) {
this._id = id;
}
Map<String, dynamic> toJson() {
return {
'body': this.body,
'author': this.author,
'usersLiked': this.usersLiked.toList()
};
}
}
Post createPost(record) {
Map<String, dynamic> attributes = {
'author': '',
'usersLiked': [],
'body': ''
};
record.forEach((key, value) => {attributes[key] = value});
Post post = new Post(attributes['body'], attributes['author']);
post.usersLiked = new Set.from(attributes['usersLiked']);
return post;
}
class PostList extends StatefulWidget {
final List<Post> listItems;
final User user;
PostList(this.listItems, this.user);
#override
_PostListState createState() => _PostListState();
}
class _PostListState extends State<PostList> {
void like(Function callBack) {
this.setState(() {
callBack();
});
}
#override
void initState() {
super.initState();
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: this.widget.listItems.length,
itemBuilder: (context, index) {
var post = this.widget.listItems[index];
return Card(
elevation: 7.0,
color: Colors.white,
child: Column(
children: [
Row(
children: [
IconButton(
icon: Icon(
Icons.play_circle_outline,
color: Colors.black,
size: 30,
),
onPressed: () {},
),
Expanded(
child: ListTile(
title: Text(post.body,
style: TextStyle(
fontWeight: FontWeight.w600,
color: Colors.black)),
subtitle: Text(post.author,
style: TextStyle(color: Colors.black)),
),
),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(post.usersLiked.length.toString(),
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w600)),
IconButton(
icon: Icon(
Icons.thumb_up,
color: post.usersLiked.contains(widget.user.uid)
? Colors.blue
: Colors.black,
),
onPressed: () =>
this.like(() => post.likePost(widget.user)),
)
],
))
],
)
],
));
},
);
}
}
database.dart
final databaseReference = FirebaseDatabase.instance.reference();
DatabaseReference savePost(Post post) {
var id = databaseReference.child('posts/').push();
id.set(post.toJson());
return id;
}
void updatePost(Post post, DatabaseReference id) {
id.update(post.toJson());
}
Future<List<Post>> getAllPosts() async {
DataSnapshot dataSnapshot = await databaseReference.child('posts/').once();
List<Post> posts = [];
if (dataSnapshot.value != null) {
dataSnapshot.value.forEach((key, value) {
Post post = createPost(value);
post.setId(databaseReference.child('posts/' + key));
posts.add(post);
});
}
return posts;
}
home.dart
class UserInfoScreen extends StatefulWidget {
const UserInfoScreen({Key key, User user})
: _user = user,
super(key: key);
final User _user;
#override
_UserInfoScreenState createState() => _UserInfoScreenState();
}
class _UserInfoScreenState extends State<UserInfoScreen> {
User _user;
bool _isSigningOut = false;
List<Post> posts = [];
void newPost(String text) {
var post = new Post(text, widget._user.displayName);
post.setId(savePost(post));
this.setState(() {
posts.add(post);
});
}
void updatePosts() {
getAllPosts().then((posts) => {
this.setState(() {
this.posts = posts;
})
});
}
Route _routeToSignInScreen() {
return PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) => SignInScreen(),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
var begin = Offset(-1.0, 0.0);
var end = Offset.zero;
var curve = Curves.ease;
var tween =
Tween(begin: begin, end: end).chain(CurveTween(curve: curve));
return SlideTransition(
position: animation.drive(tween),
child: child,
);
},
);
}
#override
void initState() {
_user = widget._user;
// HOME PAGE
pageList.add(Scaffold(
backgroundColor: Colors.white,
body: Column(children: [
Expanded(
child: PostList(this.posts, _user),
),
]),
));
pageList.add(Test1());
pageList.add(Scaffold(
backgroundColor: Colors.white,
body: Column(
children: [
TextInputWidget(this.newPost, "Title:"),
],
),
));
pageList.add(Test3());
// ACCOUNT PAGE
pageList.add(
Scaffold(
backgroundColor: Colors.white,
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(),
_user.photoURL != null
? ClipOval(
child: Material(
color: Colors.grey.withOpacity(0.3),
child: Image.network(
_user.photoURL,
fit: BoxFit.fitHeight,
),
),
)
: ClipOval(
child: Material(
color: Colors.grey.withOpacity(0.3),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Icon(
Icons.person,
size: 60,
color: Colors.black,
),
),
),
),
SizedBox(height: 16.0),
Text(
'${_user.displayName}',
style: TextStyle(
color: Colors.black,
fontSize: 26,
fontWeight: FontWeight.w700),
),
SizedBox(height: 8.0),
Text(
' ${_user.email} ',
style: TextStyle(
color: Colors.black,
fontSize: 20,
letterSpacing: 0.5,
),
),
SizedBox(height: 60.0),
_isSigningOut
? CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
)
: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(
Colors.redAccent,
),
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
),
onPressed: () async {
setState(() {
_isSigningOut = true;
});
await Authentication.signOut(context: context);
setState(() {
_isSigningOut = false;
});
Navigator.of(context)
.pushReplacement(_routeToSignInScreen());
},
child: Padding(
padding: EdgeInsets.only(top: 8.0, bottom: 8.0),
child: Text(
'Logout',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
),
),
],
),
),
);
super.initState();
updatePosts();
}
#override
List<Widget> pageList = List<Widget>();
int _currentIndex = 0;
void onTabTapped(int index) {
setState(() {
_currentIndex = index;
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0.0,
backgroundColor: Colors.white,
title: Text(
'SoundFX',
style: TextStyle(color: Colors.black),
),
centerTitle: true,
),
body: IndexedStack(
index: _currentIndex,
children: pageList,
),
bottomNavigationBar: BottomNavigationBar(
unselectedItemColor: Colors.grey,
selectedItemColor: Colors.blue,
backgroundColor: Colors.white,
elevation: 19.0,
onTap: onTabTapped,
currentIndex: _currentIndex,
type: BottomNavigationBarType.fixed,
items: [
BottomNavigationBarItem(
icon: new Icon(Icons.home),
title: Container(
height: 1.0,
)),
BottomNavigationBarItem(
icon: new Icon(Icons.search),
title: Container(
height: 1.0,
)),
BottomNavigationBarItem(
icon: new Icon(
Icons.add_circle,
size: 40,
),
title: Container(
height: 1.0,
)),
BottomNavigationBarItem(
icon: new Icon(Icons.videocam),
title: Container(
height: 1.0,
)),
BottomNavigationBarItem(
icon: Icon(Icons.account_circle),
title: Container(
height: 1.0,
)),
],
),
);
}
}
class Test1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.green,
);
}
}
class Test2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.blue,
);
}
}
class Test3 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.yellow,
);
}
}
text-input.dart
class TextInputWidget extends StatefulWidget {
final Function(String) callback;
String label;
TextInputWidget(this.callback, this.label);
#override
_TextInputWidgetState createState() => _TextInputWidgetState();
}
class _TextInputWidgetState extends State<TextInputWidget> {
final controller = TextEditingController();
#override
void dispose() {
super.dispose();
controller.dispose();
}
void click() {
widget.callback(controller.text);
FocusScope.of(context).unfocus();
controller.clear();
}
void pickFiles() async {
FilePickerResult result =
await FilePicker.platform.pickFiles(type: FileType.any);
File file = File(result.files.first.path);
print(file);
}
#override
Widget build(BuildContext context) {
return Container(
height: 400,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
child: Container(
padding: EdgeInsets.all(20.0),
child: TextField(
controller: this.controller,
decoration: InputDecoration(
labelText: this.widget.label,
))),
),
Container(
child: ElevatedButton(onPressed: this.click, child: Text('Post')),
),
Container(
child:
ElevatedButton(onPressed: this.pickFiles, child: Text('test')),
)
],
),
);
}
}
PS: Also, note that some of the functions and classes are unused or basically useless, and some of the names are very stupid, but please do not comment on those if they are not related to the question, as those are just for some tests for features for me to add into the application.
Also, note that i followed this tutorial - https://www.youtube.com/playlist?list=PLzMcBGfZo4-knQWGK2IC49Q_5AnQrFpzv
firebaser here
Most likely the Firebase SDK is unable to read the URL of the database from its config file, because your database is hosted outside of the default (US) region.
If that is indeed the cause, you should specify the database URL in your code. By specifying it in your code, the SDK should able to connect to the database instance no matter what region it is hosted in.
This mean you should get your database with
FirebaseDatabase("your database URL").reference()
// Or
FirebaseDatabase(databaseURL: "your database URL").reference()
instead of
FirebaseDatabase.instance.reference()
This is documented here:
To get a reference to a database other than a us-central1 default dstabase, you must pass the database URL to getInstance() (or Kotlin+KTX database()) . For a us-central1 default database, you can call getInstance() (or database) without arguments.
So while this is documented, it is incredibly easy to overlook. I'm checking with our team if there's something we can do to make this configuration problem more obvious.

sucessfully authenticated but can't write in firebase database using flutter [duplicate]

I am trying to create a simple app that adds posts to a firebase realtime database and shows them on a listview in flutter, but when I "post" it to the database, on the firebase console, the data value constantly appears as null. does anyone know what is wrong?
Here is a bit of my code -
post.dart
class Post {
Image coverImg;
File audioFile;
String body;
String author;
Set usersLiked = {};
DatabaseReference _id;
Post(this.body, this.author);
void likePost(User user) {
if (this.usersLiked.contains(user.uid)) {
this.usersLiked.remove(user.uid);
} else {
this.usersLiked.add(user.uid);
}
}
void update() {
updatePost(this, this._id);
}
void setId(DatabaseReference id) {
this._id = id;
}
Map<String, dynamic> toJson() {
return {
'body': this.body,
'author': this.author,
'usersLiked': this.usersLiked.toList()
};
}
}
Post createPost(record) {
Map<String, dynamic> attributes = {
'author': '',
'usersLiked': [],
'body': ''
};
record.forEach((key, value) => {attributes[key] = value});
Post post = new Post(attributes['body'], attributes['author']);
post.usersLiked = new Set.from(attributes['usersLiked']);
return post;
}
class PostList extends StatefulWidget {
final List<Post> listItems;
final User user;
PostList(this.listItems, this.user);
#override
_PostListState createState() => _PostListState();
}
class _PostListState extends State<PostList> {
void like(Function callBack) {
this.setState(() {
callBack();
});
}
#override
void initState() {
super.initState();
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: this.widget.listItems.length,
itemBuilder: (context, index) {
var post = this.widget.listItems[index];
return Card(
elevation: 7.0,
color: Colors.white,
child: Column(
children: [
Row(
children: [
IconButton(
icon: Icon(
Icons.play_circle_outline,
color: Colors.black,
size: 30,
),
onPressed: () {},
),
Expanded(
child: ListTile(
title: Text(post.body,
style: TextStyle(
fontWeight: FontWeight.w600,
color: Colors.black)),
subtitle: Text(post.author,
style: TextStyle(color: Colors.black)),
),
),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(post.usersLiked.length.toString(),
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w600)),
IconButton(
icon: Icon(
Icons.thumb_up,
color: post.usersLiked.contains(widget.user.uid)
? Colors.blue
: Colors.black,
),
onPressed: () =>
this.like(() => post.likePost(widget.user)),
)
],
))
],
)
],
));
},
);
}
}
database.dart
final databaseReference = FirebaseDatabase.instance.reference();
DatabaseReference savePost(Post post) {
var id = databaseReference.child('posts/').push();
id.set(post.toJson());
return id;
}
void updatePost(Post post, DatabaseReference id) {
id.update(post.toJson());
}
Future<List<Post>> getAllPosts() async {
DataSnapshot dataSnapshot = await databaseReference.child('posts/').once();
List<Post> posts = [];
if (dataSnapshot.value != null) {
dataSnapshot.value.forEach((key, value) {
Post post = createPost(value);
post.setId(databaseReference.child('posts/' + key));
posts.add(post);
});
}
return posts;
}
home.dart
class UserInfoScreen extends StatefulWidget {
const UserInfoScreen({Key key, User user})
: _user = user,
super(key: key);
final User _user;
#override
_UserInfoScreenState createState() => _UserInfoScreenState();
}
class _UserInfoScreenState extends State<UserInfoScreen> {
User _user;
bool _isSigningOut = false;
List<Post> posts = [];
void newPost(String text) {
var post = new Post(text, widget._user.displayName);
post.setId(savePost(post));
this.setState(() {
posts.add(post);
});
}
void updatePosts() {
getAllPosts().then((posts) => {
this.setState(() {
this.posts = posts;
})
});
}
Route _routeToSignInScreen() {
return PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) => SignInScreen(),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
var begin = Offset(-1.0, 0.0);
var end = Offset.zero;
var curve = Curves.ease;
var tween =
Tween(begin: begin, end: end).chain(CurveTween(curve: curve));
return SlideTransition(
position: animation.drive(tween),
child: child,
);
},
);
}
#override
void initState() {
_user = widget._user;
// HOME PAGE
pageList.add(Scaffold(
backgroundColor: Colors.white,
body: Column(children: [
Expanded(
child: PostList(this.posts, _user),
),
]),
));
pageList.add(Test1());
pageList.add(Scaffold(
backgroundColor: Colors.white,
body: Column(
children: [
TextInputWidget(this.newPost, "Title:"),
],
),
));
pageList.add(Test3());
// ACCOUNT PAGE
pageList.add(
Scaffold(
backgroundColor: Colors.white,
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(),
_user.photoURL != null
? ClipOval(
child: Material(
color: Colors.grey.withOpacity(0.3),
child: Image.network(
_user.photoURL,
fit: BoxFit.fitHeight,
),
),
)
: ClipOval(
child: Material(
color: Colors.grey.withOpacity(0.3),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Icon(
Icons.person,
size: 60,
color: Colors.black,
),
),
),
),
SizedBox(height: 16.0),
Text(
'${_user.displayName}',
style: TextStyle(
color: Colors.black,
fontSize: 26,
fontWeight: FontWeight.w700),
),
SizedBox(height: 8.0),
Text(
' ${_user.email} ',
style: TextStyle(
color: Colors.black,
fontSize: 20,
letterSpacing: 0.5,
),
),
SizedBox(height: 60.0),
_isSigningOut
? CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
)
: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(
Colors.redAccent,
),
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
),
onPressed: () async {
setState(() {
_isSigningOut = true;
});
await Authentication.signOut(context: context);
setState(() {
_isSigningOut = false;
});
Navigator.of(context)
.pushReplacement(_routeToSignInScreen());
},
child: Padding(
padding: EdgeInsets.only(top: 8.0, bottom: 8.0),
child: Text(
'Logout',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
color: Colors.white,
),
),
),
),
],
),
),
);
super.initState();
updatePosts();
}
#override
List<Widget> pageList = List<Widget>();
int _currentIndex = 0;
void onTabTapped(int index) {
setState(() {
_currentIndex = index;
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0.0,
backgroundColor: Colors.white,
title: Text(
'SoundFX',
style: TextStyle(color: Colors.black),
),
centerTitle: true,
),
body: IndexedStack(
index: _currentIndex,
children: pageList,
),
bottomNavigationBar: BottomNavigationBar(
unselectedItemColor: Colors.grey,
selectedItemColor: Colors.blue,
backgroundColor: Colors.white,
elevation: 19.0,
onTap: onTabTapped,
currentIndex: _currentIndex,
type: BottomNavigationBarType.fixed,
items: [
BottomNavigationBarItem(
icon: new Icon(Icons.home),
title: Container(
height: 1.0,
)),
BottomNavigationBarItem(
icon: new Icon(Icons.search),
title: Container(
height: 1.0,
)),
BottomNavigationBarItem(
icon: new Icon(
Icons.add_circle,
size: 40,
),
title: Container(
height: 1.0,
)),
BottomNavigationBarItem(
icon: new Icon(Icons.videocam),
title: Container(
height: 1.0,
)),
BottomNavigationBarItem(
icon: Icon(Icons.account_circle),
title: Container(
height: 1.0,
)),
],
),
);
}
}
class Test1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.green,
);
}
}
class Test2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.blue,
);
}
}
class Test3 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.yellow,
);
}
}
text-input.dart
class TextInputWidget extends StatefulWidget {
final Function(String) callback;
String label;
TextInputWidget(this.callback, this.label);
#override
_TextInputWidgetState createState() => _TextInputWidgetState();
}
class _TextInputWidgetState extends State<TextInputWidget> {
final controller = TextEditingController();
#override
void dispose() {
super.dispose();
controller.dispose();
}
void click() {
widget.callback(controller.text);
FocusScope.of(context).unfocus();
controller.clear();
}
void pickFiles() async {
FilePickerResult result =
await FilePicker.platform.pickFiles(type: FileType.any);
File file = File(result.files.first.path);
print(file);
}
#override
Widget build(BuildContext context) {
return Container(
height: 400,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
child: Container(
padding: EdgeInsets.all(20.0),
child: TextField(
controller: this.controller,
decoration: InputDecoration(
labelText: this.widget.label,
))),
),
Container(
child: ElevatedButton(onPressed: this.click, child: Text('Post')),
),
Container(
child:
ElevatedButton(onPressed: this.pickFiles, child: Text('test')),
)
],
),
);
}
}
PS: Also, note that some of the functions and classes are unused or basically useless, and some of the names are very stupid, but please do not comment on those if they are not related to the question, as those are just for some tests for features for me to add into the application.
Also, note that i followed this tutorial - https://www.youtube.com/playlist?list=PLzMcBGfZo4-knQWGK2IC49Q_5AnQrFpzv
firebaser here
Most likely the Firebase SDK is unable to read the URL of the database from its config file, because your database is hosted outside of the default (US) region.
If that is indeed the cause, you should specify the database URL in your code. By specifying it in your code, the SDK should able to connect to the database instance no matter what region it is hosted in.
This mean you should get your database with
FirebaseDatabase("your database URL").reference()
// Or
FirebaseDatabase(databaseURL: "your database URL").reference()
instead of
FirebaseDatabase.instance.reference()
This is documented here:
To get a reference to a database other than a us-central1 default dstabase, you must pass the database URL to getInstance() (or Kotlin+KTX database()) . For a us-central1 default database, you can call getInstance() (or database) without arguments.
So while this is documented, it is incredibly easy to overlook. I'm checking with our team if there's something we can do to make this configuration problem more obvious.

how to get videos from Gallery and upload it firebase firestore using Image Picker and Video Player in Flutter?

I am trying to get video from gallery and want to display them in grid view and inside container and then on save button want to upload it to firebase firestore. Firstly, I am not able get the videos from gallery and display it in UI. I have seen many examples and followed them but it is not working for me as I am new into all this and not able to put to it together, where it needs to be..Pls help me out. Thanks in advance.Though the complete code may or may not be related to my query but it may help somebody who is trying to achieve something same. This is the complete code which have play button, video length with indicator.
I think I am missing few things here:-
#override
void initState() {
super.initState();
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
This is where I want display the video:-
Container(
height: MediaQuery.of(context).size.height,
padding: EdgeInsets.all(20),
child:GridView.builder(
itemCount: _video.length,
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 150,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
),
itemBuilder: (context,index){
return Container(
child: _controller.value.isInitialized ?
Stack(
children: [
VideoPlayer(_controller),
_ControlsOverlay(_controller),
],
)
:Container(),
);
}
),
),
This is where I open gallery and pick video;-
chooseVideo() async {
final pickedVideo = await picker.getVideo(
source: ImageSource.gallery,
maxDuration: const Duration(seconds: 60)
);
setState(() {
_video.add(File(pickedVideo?.path));
_controller = VideoPlayerController.file(File(_video.toString()));
});
if (pickedVideo.path == null) retrieveLostData();
}
Future<void> retrieveLostData() async {
final LostData response = await picker.getLostData();
if (response.isEmpty) {
return;
}
if (response.file != null) {
setState(() {
_video.add(File(response.file.path));
});
} else {
print(response.file);
}
}
This is complete code:-
class AddVideo extends StatefulWidget {
#override
_AddVideo createState() => _AddVideo();
}
class _AddVideo extends State<AddVideo> {
bool uploading = false;
double val = 0;
CollectionReference imgRef;
firebase_storage.Reference ref;
List<File> _video = [];
File videoFile;
List<String> urls = [];
final picker = ImagePicker();
final auth = FirebaseAuth.instance;
final _stoarge = FirebaseStorage.instance;
VideoPlayerController _controller;
#override
void initState() {
super.initState();
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.transparent,
actions: [
ElevatedButton(
child: Text("SAVE", style: TextStyle(fontSize: 15)),
onPressed: () {
setState(() {
uploading = true;
});
_uploadVideo().whenComplete(() => Navigator.of(context).pop());
},
style: ElevatedButton.styleFrom(
padding: EdgeInsets.fromLTRB(25.0, 15.0, 25.0, 10.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0))),
),
],
),
body: Container(
child: SafeArea(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
// padding: EdgeInsets.all(20),
child: ElevatedButton(
child: Text("Open Gallery", style: TextStyle(fontSize: 20)),
onPressed: () => !uploading ? chooseVideo() : null,
style: ElevatedButton.styleFrom(
padding: EdgeInsets.fromLTRB(25.0, 15.0, 25.0, 10.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0))),
),
),
Container(
height: MediaQuery.of(context).size.height,
padding: EdgeInsets.all(20),
child:GridView.builder(
itemCount: _video.length,
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 150,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
),
itemBuilder: (context,index){
return Container(
child: _controller.value.isInitialized ?
Stack(
children: [
VideoPlayer(_controller),
_ControlsOverlay(_controller),
],
)
:Container(),
);
}
),
),
uploading ?
Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
child: Text(
'uploading...',
style: TextStyle(fontSize: 20),
),
),
SizedBox(
height: 10,
),
CircularProgressIndicator(
value: val,
valueColor: AlwaysStoppedAnimation<Color>(Colors.green),
)
],
)
)
: Container(),
],
),
),
),
),
);
}
chooseVideo() async {
final pickedVideo = await picker.getVideo(
source: ImageSource.gallery,
maxDuration: const Duration(seconds: 60)
);
setState(() {
_video.add(File(pickedVideo?.path));
_controller = VideoPlayerController.file(File(_video.toString()));
});
if (pickedVideo.path == null) retrieveLostData();
}
Future<void> retrieveLostData() async {
final LostData response = await picker.getLostData();
if (response.isEmpty) {
return;
}
if (response.file != null) {
setState(() {
_video.add(File(response.file.path));
});
} else {
print(response.file);
}
}
_uploadVideo() async {
for (var video in _video) {
var _ref = _stoarge.ref().child("videos/" + Path.basename(video.path));
await _ref.putFile(video);
String url = await _ref.getDownloadURL();
print(url);
urls.add(url);
print(url);
}
print("uploading:" + urls.asMap().toString());
await FirebaseFirestore.instance
.collection("users")
.doc(auth.currentUser.uid)
.update({"images": urls});
// .doc(auth.currentUser.uid).update({"images": FieldValue.arrayUnion(urls) });
}
}
class _ControlsOverlay extends StatelessWidget {
String getPosition() {
final duration = Duration(
milliseconds: controller.value.position.inMilliseconds.round());
return [duration.inMinutes, duration.inSeconds]
.map((seg) => seg.remainder(60).toString().padLeft(2, '0'))
.join(':');
}
const _ControlsOverlay(this.controller);
final VideoPlayerController controller;
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
AnimatedSwitcher(
duration: Duration(milliseconds: 50),
reverseDuration: Duration(milliseconds: 200),
child: controller.value.isPlaying
? SizedBox.shrink()
: Container(
color: Colors.black26,
child: Center(
child: Icon(
Icons.play_arrow,
color: Colors.white,
size: 100.0,
),
),
),
),
GestureDetector(
onTap: () {
controller.value.isPlaying ? controller.pause() : controller.play();
},
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Row(
children: [
const SizedBox(width: 8),
Expanded(child: Text(getPosition()),),
const SizedBox(width: 8),
Expanded(child: buildIndicator()),
const SizedBox(width: 8),
],
)
),
],
);
}
Widget buildIndicator() => Container(
margin: EdgeInsets.all(8).copyWith(right: 0),
height: 10,
child: VideoProgressIndicator(
controller, allowScrubbing: true,
),
);
}

Resources