Related
I am building a flutter eCommerce app. if I log in as a new user, with google, or sign up, the home page doesn't load the products... in console, It shows cloud firestore permission denied. then after I close and reopen the app, the page loads with products.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth.uid != null;
}
}
}
the above rule is not working. but if I log in, the user logs in successfully, also the user details are added to the DB.
Login page
Error:
W/Firestore( 1298): (22.0.2) [Firestore]: Listen for
Query(target=Query(product order by
name);limitType=LIMIT_TO_FIRST) failed: Status{code=PERMISSION_DENIED, description=Missing or insufficient
permissions., cause=null}
HomePage
class _HomeoneState extends State<Homeone> {
final _key = GlobalKey<ScaffoldState>();
ProductServices _productServices = ProductServices();
List _gender = ['Current location', 'loc1', 'loc2'];
String _genderVal;
#override
Widget build(BuildContext context) {
final userProvider = Provider.of<UserProvider>(context);
final productProvider = Provider.of<ProductProvider>(context);
return Scaffold(
key: _key,
backgroundColor: white,
endDrawer: Drawer(
child: ListView(
children: <Widget>[
UserAccountsDrawerHeader(
decoration: BoxDecoration(color: red,
borderRadius: BorderRadius.only(bottomRight: Radius.circular(50),bottomLeft: Radius.circular(50)),
image: DecorationImage(
fit: BoxFit.fill,
image: NetworkImage(
'https://blogrope.com/wp-content/uploads/2013/03/happy_wallpaper_by_melaamory-d5n8m53.jpg')),
),
accountName: CustomText(
text: userProvider.userModel?.name ?? "username lading...",
color: black,
weight: FontWeight.bold,
size: 18,
),
accountEmail: CustomText(
text: userProvider.userModel?.email ?? "email loading...",
color: black,
),
),
ListTile(
onTap: () async{
await userProvider.getOrders();
changeScreen(context, OrdersScreen());
},
leading: Icon(Icons.bookmark_outlined,color: Colors.black,),
title: CustomText(text: "My orders"),
),
ListTile(
onTap: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => MyHomePage()));
},
leading: Icon(Icons.exit_to_app_outlined,color: Colors.black,),
title: CustomText(text: "Log out"),
),
ListTile(
onTap: () {
userProvider.signOut();
},
leading: Icon(Icons.exit_to_app_outlined,color: Colors.black,),
title: CustomText(text: "Log out"),
),
ListTile(
onTap: () {
AuthService().signOutGoogle();
Navigator.push(
context, MaterialPageRoute(builder: (context) => Login()));
},
leading: Icon(Icons.add),
title: CustomText(text: "Log out for google"),
),
],
),
),
body:
SafeArea(
child: ListView(
physics: AlwaysScrollableScrollPhysics(),
children: <Widget>[
// Custom App bar
Column(
children: <Widget>[
Container(
padding: const EdgeInsets.all(5.0),
child: Row(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text('Hi',style: TextStyle(color: Colors.black),)),
Padding(
padding: const EdgeInsets.all(4.0),
child: Text(
userProvider.userModel?.name ?? "wait...",
),
),
Container(
margin: EdgeInsets.all(14),
child: Padding(
padding: const EdgeInsets.fromLTRB(200.0,0,0,0),
child: Align(
alignment: Alignment.topRight,
child: GestureDetector(
onTap: (){
changeScreen(context, CartScreen());
},
child: Icon(Icons.shopping_cart))),
),
),
],
),
),
Container(
margin: EdgeInsets.fromLTRB(280, 0, 0, 0),
child: GestureDetector(
onTap: () {
_key.currentState.openEndDrawer();
},
child: Icon(Icons.menu)),
),
Padding(
padding: const EdgeInsets.all(5.0),
child: Align(
alignment: Alignment.topLeft,
child: Text(
'Delivering to',
style: TextStyle(
color: Colors.grey,
),
),
),
),
Container(
padding: EdgeInsets.all(8),
margin: EdgeInsets.all(4),
decoration: BoxDecoration(
border: Border.all(color: Colors.transparent),
borderRadius: BorderRadius.all(Radius.circular(20)),
color: Colors.white,
),
child: DropdownButton(
hint: Text('Current location'),
dropdownColor: Colors.white,
value: _genderVal,
isExpanded: true,
onChanged: (value) {
setState(() {
_genderVal = value;
});
},
items: _gender.map((value) {
return DropdownMenuItem(
value: value,
child: Text(value),
);
}).toList(),
),
),
],
),
// Search Text field
// Search(),
Container(
decoration: BoxDecoration(
color: white,
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(24),
bottomLeft: Radius.circular(24))),
child: Padding(
padding: const EdgeInsets.only(
top: 5, left: 14, right: 14, bottom: 14),
child: Container(
decoration: BoxDecoration(
color: grey.withOpacity(0.2),
borderRadius: BorderRadius.circular(15),
),
child: ListTile(
leading: Icon(
Icons.search,
color: black,
),
title: TextField(
textInputAction: TextInputAction.search,
onSubmitted: (pattern)async{
await productProvider.search(productName: pattern);
changeScreen(context, ProductSearchScreen());
},
decoration: InputDecoration(
hintText: "Search...",
border: InputBorder.none,
),
),
),
),
),
),
// featured products
ListTile(
title: Text('Menu of the Day',
style: TextStyle(color: Colors.black, fontSize: 18),),
trailing: Text('View all', style: TextStyle(color: Colors.red),
),
),
FeaturedProducts(),
ListTile(
title: Text('Highly rated foods',
style: TextStyle(color: Colors.black, fontSize: 18),),
trailing: Text('View all', style: TextStyle(color: Colors.red),
),
),
FeaturedProductsone(),
// recent products
Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(14.0),
child: Container(
alignment: Alignment.centerLeft,
child: new Text('Recent products')),
),
],
),
Column(
children: productProvider.products
.map((item) => GestureDetector(
child: ProductCard(
product: item,
),
))
.toList(),
),
],
),
),
);
}
}
Login
final userProvider = Provider.of<UserProvider>(context);
return Scaffold(
key: _key,
body:userProvider.status == Status.Authenticating ? Loading() : Form(
key: _formKey,
child: ListView(
children: <Widget>[
Container(
padding: EdgeInsets.all(20.0),
margin: EdgeInsets.all(30),
child: Center(
child: Text(
'Login',
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.w500,
),
),
),
),
Container(
child: Center(
child: Text(
'Add details to login',
style: TextStyle(
fontSize: 15,
),
),
),
),
Container(
padding: EdgeInsets.all(20),
child: TextFormField(
controller: _email,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
suffixIcon: Icon(Icons.email),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.transparent),
borderRadius: BorderRadius.all(Radius.circular(20)),
),
hintText: 'Your Email',
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blueAccent),
borderRadius: BorderRadius.all(Radius.circular(20)),
),
filled: true,
fillColor: Colors.grey[200],
),
validator: (value) {
if (value.isEmpty) {
Pattern pattern =
r'^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
RegExp regex = new RegExp(pattern);
if (!regex.hasMatch(value))
return 'Please make sure your email address is valid';
else
return null;
}
},
),
),
Container(
padding: EdgeInsets.all(20),
child: TextFormField(
controller: _password,
obscureText: true,
decoration: InputDecoration(
suffixIcon: Icon(Icons.vpn_key_sharp),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.transparent),
borderRadius: BorderRadius.all(Radius.circular(20)),
),
hintText: 'Password',
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blueAccent),
borderRadius: BorderRadius.all(Radius.circular(20)),
),
filled: true,
fillColor: Colors.grey[200],
),
validator: (value) {
if (value.isEmpty) {
return "The password field cannot be empty";
} else if (value.length < 6) {
return "the password has to be at least 6 characters long";
}
return null;
},
),
),
Container(
padding: EdgeInsets.all(40),
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(40.0),
),
color: Color(0xfffd44323),
child: Text('Login',
style: TextStyle(
fontSize: 20,
)),
textColor: Colors.white,
onPressed: () async {
// _loginUser(type: LoginType.email,email:_emailController.text, password:_passwordController.text,context: context);
if(_formKey.currentState.validate()){
if(!await userProvider.signIn(_email.text, _password.text))
_key.currentState.showSnackBar(SnackBar(content: Text("Failure")));
return;
}
changeScreenReplacement(context, HomePage());
},
),
),
InkWell(
child: Container(
child: Center(
child: Text(
'Forgot password',
style: TextStyle(
fontSize: 15,
),
),
),
),
onTap: (){
// Navigator.push(
// context, MaterialPageRoute(builder: (context) => Dashone()));
},
),
Container(
margin: EdgeInsets.all(35.0),
child: Center(
child: Text(
'or Login with ',
style: TextStyle(
fontSize: 15,
),
),
),
),
Container(
padding: EdgeInsets.all(5),
margin: EdgeInsets.all(20.0),
decoration: BoxDecoration(
border: Border.all(color: Colors.transparent),
borderRadius: BorderRadius.all(Radius.circular(34)),
color: Color(0xfff3680c1),
),
child: Center(
child: ListTile(
leading: SvgPicture.asset('assets/facebook.svg',
color: Colors.white),
title: Center(
child: Text(
'Login with facebook',
style: TextStyle(
color: Colors.white,
fontSize: 17,
),
)),
),
),
),
Container(
padding: EdgeInsets.all(5),
margin: EdgeInsets.all(20.0),
decoration: BoxDecoration(
border: Border.all(color: Colors.transparent),
borderRadius: BorderRadius.all(Radius.circular(34)),
color: Color(0xfffd44323),
),
child: Center(
child: InkWell(
child: ListTile(
leading: SvgPicture.asset(
'assets/google-plus.svg',
color: Colors.white,
height: 25.0,
width: 25.0,
),
title: Center(
child: InkWell(
child: Container(
child: Text(
'Login with Google',
style: TextStyle(
color: Colors.white,
fontSize: 17,
),
),
),
onTap: () async {
FirebaseAuth _auth = FirebaseAuth.instance;
User user = await AuthService().signInWithGoogle();
print(user);
if (user == null) {
_userServices.createUser({
"name": _auth.currentUser.displayName,
"photo": _auth.currentUser.photoURL,
"email": _auth.currentUser.email,
"uid": _auth.currentUser.uid,
"votes": votes,
"trips": trips,
"rating": rating,
});
// _userServices.createUser(
//
//
// );
// 5s over, navigate to a new page
Navigator.pushReplacement(
context, MaterialPageRoute(
builder: (context) => HomePage()));
}
},
),
)
),
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
child: Center(
child: Text(
'Don\'t have an Account?',
style: TextStyle(
fontSize: 15,
),
),
),
),
InkWell(
child: Container(
padding: EdgeInsets.all(10.0),
child: Center(
child: Text(
'Sign up',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Color(0xfffd44323),
),
),
),
),
onTap: () {
changeScreen(context, SignUp());
},
),
],
),
],
),
),
);
}
}
After restaring the app
import 'package:flutter/material.dart';
import 'package:flutter_myapp/AllWidgets/Divider.dart';
import 'package:flutter_myapp/AllWidgets/progressDialog.dart';
import 'package:flutter_myapp/Assistants/requestAssistant.dart';
import 'package:flutter_myapp/DataHandler/appData.dart';
import 'package:flutter_myapp/Models/address.dart';
import 'package:flutter_myapp/Models/placePredictions.dart';
import 'package:flutter_myapp/configMaps.dart';
import 'package:provider/provider.dart';
class SearchScreen extends StatefulWidget {
#override
_SearchScreenState createState() => _SearchScreenState();
}
class _SearchScreenState extends State<SearchScreen>
{
TextEditingController pickUpTextEditingController = TextEditingController();
TextEditingController dropOffTextEditingController = TextEditingController();
List<PlacePredictions> placePredictionList = [];
#override
Widget build(BuildContext context)
{
String placeAddress = Provider.of<AppData>(context).pickUpLocation.placeName ?? "";
pickUpTextEditingController.text = placeAddress;
return Scaffold(
body: Column(
children: [
Container(
height: 215.0,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black,
blurRadius: 6.0,
spreadRadius: 0.5,
offset: Offset(0.7, 0.7),
),
],
),
child: Padding(
padding: EdgeInsets.only(left: 25.0, top: 25.0, bottom: 20.0),
child: Column(
children: [
SizedBox(height: 5.0),
Stack(
children: [
GestureDetector(
onTap:()
{
Navigator.pop(context);
},
child: Icon(
Icons.arrow_back
),
),
Center(
child: Text("Set Drop Off", style: TextStyle(fontSize: 18.0, fontFamily: "Brand Bold"),),
)
],
),
SizedBox(height: 16.0),
Row(
children: [
Image.asset("images/pickicon.png", height: 16.0, width: 16.0,),
SizedBox(width: 18.0,),
Expanded(
child: Container(
decoration: BoxDecoration(
color: Colors.grey[400],
borderRadius: BorderRadius.circular(5.0),
),
child: Padding(
padding: EdgeInsets.all(3.0),
child: TextField(
controller: pickUpTextEditingController,
decoration: InputDecoration(
hintText: "PickUp Location",
fillColor: Colors.grey[400],
filled: true,
border: InputBorder.none,
isDense: true,
contentPadding: EdgeInsets.only(left: 11.0, top: 8.0, bottom: 8.0),
),
),
),
),
),
],
),
SizedBox(height: 10.0),
Row(
children: [
Image.asset("images/desticon.png", height: 16.0, width: 16.0,),
SizedBox(width: 18.0,),
Expanded(
child: Container(
decoration: BoxDecoration(
color: Colors.grey[400],
borderRadius: BorderRadius.circular(5.0),
),
child: Padding(
padding: EdgeInsets.all(3.0),
child: TextField(
onChanged: (val)
{
findPlace(val);
},
controller: dropOffTextEditingController,
decoration: InputDecoration(
hintText: "Where to? ",
fillColor: Colors.grey[400],
filled: true,
border: InputBorder.none,
isDense: true,
contentPadding: EdgeInsets.only(left: 11.0, top: 8.0, bottom: 8.0),
),
),
),
),
),
],
),
],
),
),
),
//tile for predictions
SizedBox(height: 10.0,),
(placePredictionList.length > 0)
?Padding(
padding: EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
child: ListView.separated(
padding: EdgeInsets.all(0.0),
itemBuilder: (context, index)
{
return PredictionTile(placePredictions: placePredictionList[index],);
},
separatorBuilder: (BuildContext context, int index) => DividerWidget(),
itemCount: placePredictionList.length,
shrinkWrap: true,
physics: ClampingScrollPhysics(),
),
)
:Container(),
],
),
);
}
void findPlace(String placeName) async
{
if(placeName.length > 1)
{
String autoCompleteUrl = "https://maps.googleapis.com/maps/api/place/autocomplete/json?input=$placeName&key=$mapKey&sessiontoken=1234567890&components=country:us";
var res = await RequestAssistant.getRequest(autoCompleteUrl);
if(res == "failed")
{
return;
}
//print("Places Predictions Response :: ");
//print(res);
if(res["status"] == "OK")
{
var predictions = res["predictions"];
var placeList = (predictions as List).map((e) => PlacePredictions.fromJson(e)).toList();
setState(() {
placePredictionList = placeList;
});
}
}
}
}
class PredictionTile extends StatelessWidget
{
final PlacePredictions placePredictions;
PredictionTile({Key key,this.placePredictions}) : super(key: key);
#override
Widget build(BuildContext context)
{
return FlatButton(
padding: EdgeInsets.all(0.0),
onPressed: ()
{
getPlaceAddressDetails(placePredictions.place_id, context);
},
child: Container(
child: Column(
children: [
SizedBox(width: 10.0,),
Row(
children: [
Icon(Icons.add_location),
SizedBox(width: 14.0,),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 8.0,),
Text(placePredictions.main_text, overflow: TextOverflow.ellipsis, style: TextStyle(fontSize: 16.0),),
SizedBox(height: 2.0,),
Text(placePredictions.secondary_text, overflow: TextOverflow.ellipsis, style: TextStyle(fontSize: 12.0, color: Colors.grey),),
SizedBox(height: 8.0,),
],
),
),
],
),
SizedBox(width: 10.0,),
],
),
),
);
}
void getPlaceAddressDetails(String placeId, context) async
{
showDialog(
context: context,
builder: (BuildContext context) => ProgressDialog(message: "Setting Drop off, Please wait....",),
);
String placeDetailsUrl = "https://maps.googleapis.com/maps/api/place/details/json?place_id=$placeId&key=$mapKey";
var res = await RequestAssistant.getRequest(placeDetailsUrl);
Navigator.pop(context);
if(res == "failed")
{
return;
}
if(res["status"] == "OK")
{
Address address = Address();
address.placeName = res["result"]["name"];
address.placeId = placeId;
address.latitude = res["result"]["geometry"]["location"]["lat"];
address.longitude = res["result"]["geometry"]["location"]["lng"];
Provider.of<AppData>(context, listen: false).updateDropOffLocationAddress(address);
print("This is Drop Off Location :: ");
print(address.placeName);
Navigator.pop(context, "obtainDirection");
}
}
}
Please help me, I can't understand what's wrong.
I keep getting this error.
Exception caught by widgets library:
The following assertion was thrown building PredictionTile(dirty): A
non-null String must be provided to a Text widget.
'package:flutter/src/widgets/text.dart': Failed assertion: line 380
pos 10: 'data != null'
The Text Widget cannot contain null data, the error relies in the following lines:
Text(placePredictions.main_text, overflow: TextOverflow.ellipsis, style: TextStyle(fontSize: 16.0),),
Text(placePredictions.secondary_text, overflow: TextOverflow.ellipsis, style: TextStyle(fontSize: 12.0, color: Colors.grey),),
To fix it, we could change them to:
Text(placePredictions.main_text ?? 'n/a', overflow: TextOverflow.ellipsis, style: TextStyle(fontSize: 16.0),),
Text(placePredictions.secondary_text ?? 'n/a', overflow: TextOverflow.ellipsis, style: TextStyle(fontSize: 12.0, color: Colors.grey),),
That replaces the null data with 'n/a'.
Error: Could not find the correct Provider above this SignUp Widget
To fix, please:
Ensure the Provider is an ancestor to this SignUp
Widget
Provide types to Provider
Provide types to Consumer
Provide types to Provider.of()
Ensure the correct context is being used.
class SignUp extends StatefulWidget {
#override
_SignUpState createState() => _SignUpState();
}
class _SignUpState extends State<SignUp> {
final _formKey = GlobalKey<FormState>();
final _key = GlobalKey<ScaffoldState>();
TextEditingController _email = TextEditingController();
TextEditingController _password = TextEditingController();
TextEditingController _name = TextEditingController();
bool hidePass = true;
#override
Widget build(BuildContext context) {
final user = Provider.of<UserProvider>(context);
return Scaffold(
key: _key,
body: user.status == Status.Authenticating ? Loading() : Stack(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left:20, right:20.0, top: 80),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.grey[350],
blurRadius:
20.0, // has the effect of softening the shadow
)
],
),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(16.0),
child: Container(
alignment: Alignment.topCenter,
child: Image.asset(
'images/cart.png',
width: 120.0,
// height: 240.0,
)),
),
Padding(
padding:
const EdgeInsets.fromLTRB(14.0, 8.0, 14.0, 8.0),
child: Material(
borderRadius: BorderRadius.circular(10.0),
color: Colors.grey.withOpacity(0.2),
elevation: 0.0,
child: Padding(
padding: const EdgeInsets.only(left: 12.0),
child: ListTile(
title: TextFormField(
controller: _name,
decoration: InputDecoration(
hintText: "Full name",
icon: Icon(Icons.person_outline),
border: InputBorder.none),
validator: (value) {
if (value.isEmpty) {
return "The name field cannot be empty";
}
return null;
},
),
),
),
),
),
Padding(
padding:
const EdgeInsets.fromLTRB(14.0, 8.0, 14.0, 8.0),
child: Material(
borderRadius: BorderRadius.circular(10.0),
color: Colors.grey.withOpacity(0.2),
elevation: 0.0,
child: Padding(
padding: const EdgeInsets.only(left: 12.0),
child: ListTile(
title: TextFormField(
controller: _email,
decoration: InputDecoration(
hintText: "Email",
icon: Icon(Icons.alternate_email),
border: InputBorder.none),
validator: (value) {
if (value.isEmpty) {
Pattern pattern =
r'^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
RegExp regex = new RegExp(pattern);
if (!regex.hasMatch(value))
return 'Please make sure your email address is valid';
else
return null;
}
return null;
},
),
),
),
),
),
Padding(
padding:
const EdgeInsets.fromLTRB(14.0, 8.0, 14.0, 8.0),
child: Material(
borderRadius: BorderRadius.circular(10.0),
color: Colors.grey.withOpacity(0.2),
elevation: 0.0,
child: Padding(
padding: const EdgeInsets.only(left: 12.0),
child: ListTile(
title: TextFormField(
controller: _password,
obscureText: hidePass,
decoration: InputDecoration(
hintText: "Password",
icon: Icon(Icons.lock_outline),
border: InputBorder.none),
validator: (value) {
if (value.isEmpty) {
return "The password field cannot be empty";
} else if (value.length < 6) {
return "the password has to be at least 6 characters long";
}
return null;
},
),
trailing: IconButton(
icon: Icon(Icons.remove_red_eye),
onPressed: () {
setState(() {
hidePass = false;
});
}),
),
),
),
),
Padding(
padding:
const EdgeInsets.fromLTRB(14.0, 8.0, 14.0, 8.0),
child: Material(
borderRadius: BorderRadius.circular(20.0),
color: deepOrange,
elevation: 0.0,
child: MaterialButton(
onPressed: () async{
if(_formKey.currentState.validate()){
if(!await user.signUp(_name.text ,_email.text, _password.text))
_key.currentState.showSnackBar(SnackBar(content: Text("Sign up failed")));
}
},
minWidth: MediaQuery.of(context).size.width,
child: Text(
"Sign up",
textAlign: TextAlign.center,
style: TextStyle(
color: white,
fontWeight: FontWeight.bold,
fontSize: 20.0),
),
)),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
onTap: () {
Navigator.pop(context);
},
child: Text(
"I already have an account",
textAlign: TextAlign.center,
style: TextStyle(color: deepOrange, fontSize: 16),
))),
Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Or sign up with", style: TextStyle(fontSize: 18,color: Colors.grey),),
),
Padding(
padding:
const EdgeInsets.fromLTRB(14.0, 8.0, 14.0, 8.0),
child: Material(
child: MaterialButton(
onPressed: () async{
if(!await user.signUpWithGoogle())
_key.currentState.showSnackBar(SnackBar(content: Text("Sign in failed")));
},
child: Image.asset("assets/google-48.png", width: 30,)
)),
),
],
),
),
],
)),
),
),
],
),
);
}
}
keep getting error what am I doing wrong
I want to upload the image to firebase storage in want to store the download URL in the firestore. I have the code that I have bellowed! but the problem is whenever I try to upload an image the image upload successfully but the URL did not save in the firestore. It's returns me Null.
How can I store the URL to firestore?
class NewFund extends StatefulWidget {
NewFund();
#override
_NewFundState createState() => _NewFundState();
}
class _NewFundState extends State<NewFund> {
final GlobalKey<FormState> _fundFormKey = GlobalKey<FormState>();
String userID, postName, postDetails, postImgUrl;
String filepath = '${DateTime.now()}.png';
File _imageFile;
StorageUploadTask _uploadTask;
final FirebaseStorage _storage =
FirebaseStorage(storageBucket: 'gs://i-donate-402dd.appspot.com');
getUserName(userId) {
this.userID = userID;
}
getPostName(postName) {
this.postName = postName;
}
getTaskDetails(postDetails) {
this.postDetails = postDetails;
}
getImageUrl(postImgUrl) {
this.postImgUrl = postImgUrl;
}
int _myPostType = 0;
String postVal;
void _handleTaskType(int value) {
setState(() {
_myPostType = value;
switch (_myPostType) {
case 1:
postVal = 'food';
break;
case 2:
postVal = 'health';
break;
case 3:
postVal = 'money';
break;
case 4:
postVal = 'clothes';
break;
case 5:
postVal = 'education';
break;
}
});
}
Widget radioButton(bool isSelected) => Container(
width: 16.0,
height: 16.0,
padding: EdgeInsets.all(2.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(width: 2.0, color: Colors.black)),
child: isSelected
? Container(
width: double.infinity,
height: double.infinity,
decoration:
BoxDecoration(shape: BoxShape.circle, color: Colors.black),
)
: Container(),
);
Widget horizontalLine() => Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Container(
width: ScreenUtil.getInstance().setWidth(120),
height: 1.0,
color: Colors.black26.withOpacity(.2),
),
);
createFund() {
var authP = Provider.of<AuthP>(context);
var uid = authP.uid;
DocumentReference ds =
Firestore.instance.collection('posts').document(postName);
Map<String, dynamic> posts = {
"userID": uid,
"postName": postName,
"postDetails": postDetails,
"postCat": postVal,
"postImgUrl": postImgUrl,
};
setState(() {
_saveImage();
});
ds.setData(posts).whenComplete(() {
print("posts updated");
});
}
Future<String> _saveImage() async {
_uploadTask = _storage.ref().child(filepath).putFile(_imageFile);
var downURL = await (await _uploadTask.onComplete).ref.getDownloadURL();
postImgUrl = downURL.toString();
print('LINK URL : $postImgUrl');
return postImgUrl;
}
Future<void> _pickImage(ImageSource source) async {
File selected = await ImagePicker.pickImage(source: source);
setState(() {
_imageFile = selected;
});
}
#override
Widget build(BuildContext context) {
ScreenUtil.instance = ScreenUtil.getInstance()..init(context);
ScreenUtil.instance =
ScreenUtil(width: 750, height: 1334, allowFontScaling: true);
return Form(
key: _fundFormKey,
child: Scaffold(
backgroundColor: Colors.white,
resizeToAvoidBottomPadding: true,
body: Stack(
fit: StackFit.expand,
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 20.0),
child: Image.asset("assets/imagemain.jpg"),
),
Expanded(
child: Container(),
),
Image.asset("assets/image_02.png")
],
),
SingleChildScrollView(
child: Padding(
padding: EdgeInsets.only(left: 28.0, right: 28.0, top: 60.0),
child: Column(
children: <Widget>[
SizedBox(
height: ScreenUtil.getInstance().setHeight(20),
),
Container(
width: double.infinity,
height: ScreenUtil.getInstance().setHeight(850),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8.0),
boxShadow: [
BoxShadow(
color: Colors.black12,
offset: Offset(0.0, 15.0),
blurRadius: 15.0),
BoxShadow(
color: Colors.black12,
offset: Offset(0.0, -10.0),
blurRadius: 10.0),
]),
child: Padding(
padding:
EdgeInsets.only(left: 16.0, right: 16.0, top: 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text("Raise Fund",
style: TextStyle(
fontSize:
ScreenUtil.getInstance().setSp(45),
fontFamily: "Poppins-Bold",
letterSpacing: .6)),
SizedBox(
height: ScreenUtil.getInstance().setHeight(30),
),
Text("Title",
style: TextStyle(
fontFamily: "Poppins-Medium",
fontSize:
ScreenUtil.getInstance().setSp(26))),
TextField(
keyboardType: TextInputType.multiline,
maxLines: null,
decoration: InputDecoration(),
onChanged: (String name) {
getPostName(name);
},
),
SizedBox(
height: ScreenUtil.getInstance().setHeight(30),
),
Text("Fund Details",
style: TextStyle(
fontFamily: "Poppins-Medium",
fontSize:
ScreenUtil.getInstance().setSp(26))),
TextField(
keyboardType: TextInputType.multiline,
maxLines: null,
decoration: InputDecoration(),
onChanged: (String postDetails) {
getTaskDetails(postDetails);
},
),
SizedBox(
height: ScreenUtil.getInstance().setHeight(30),
),
Text("Select Fund Type",
style: TextStyle(
fontFamily: "Poppins-Bold",
fontSize:
ScreenUtil.getInstance().setSp(26))),
SizedBox(
height: ScreenUtil.getInstance().setHeight(30),
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Radio(
value: 1,
groupValue: _myPostType,
onChanged: _handleTaskType,
activeColor: Color(0xff4158ba),
),
Text(
'Food',
style: TextStyle(fontSize: 16.0),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Radio(
value: 2,
groupValue: _myPostType,
onChanged: _handleTaskType,
activeColor: Color(0xfffb537f),
),
Text(
'Health',
style: TextStyle(
fontSize: 16.0,
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Radio(
value: 3,
groupValue: _myPostType,
onChanged: _handleTaskType,
activeColor: Color(0xff4caf50),
),
Text(
'Money',
style: TextStyle(fontSize: 16.0),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Radio(
value: 4,
groupValue: _myPostType,
onChanged: _handleTaskType,
activeColor: Color(0xff9962d0),
),
Text(
'Clothes',
style: TextStyle(fontSize: 16.0),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Radio(
value: 5,
groupValue: _myPostType,
onChanged: _handleTaskType,
activeColor: Color(0xff0dc8f5),
),
Text(
'Education',
style: TextStyle(fontSize: 16.0),
),
],
),
],
),
],
),
),
),
SizedBox(
height: ScreenUtil.getInstance().setHeight(20),
),
RaisedButton(
onPressed: () {
_pickImage(ImageSource.gallery);
},
child: Text('Upload Document'),
),
SizedBox(
height: ScreenUtil.getInstance().setHeight(20),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
InkWell(
child: Container(
width: ScreenUtil.getInstance().setWidth(330),
height: ScreenUtil.getInstance().setHeight(100),
decoration: BoxDecoration(
gradient: LinearGradient(colors: [
Color(0xFF17ead9),
Color(0xFF6078ea)
]),
borderRadius: BorderRadius.circular(6.0),
boxShadow: [
BoxShadow(
color: Color(0xFF6078ea).withOpacity(.3),
offset: Offset(0.0, 8.0),
blurRadius: 8.0)
]),
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () {
createFund();
},
child: Center(
child: Text("Raise",
style: TextStyle(
color: Colors.white,
fontFamily: "Poppins-Bold",
fontSize: 18,
letterSpacing: 1.0)),
),
),
),
),
)
],
),
],
),
),
)
],
),
),
);
}
}
here is how you can implement it
final StorageReference storageReference =
FirebaseStorage.instance.ref().child('images/$name');
StorageUploadTask uploadTask = storageReference.putData(asset);
final StreamSubscription<StorageTaskEvent> streamSubscription =
uploadTask.events.listen((event) {
// You can use this to notify yourself or your user in any kind of way.
// For example: you could use the uploadTask.events stream in a StreamBuilder instead
// to show your user what the current status is. In that case, you would not need to cancel any
// subscription as StreamBuilder handles this automatically.
});
await uploadTask.onComplete;
streamSubscription.cancel();
//get your ref url
String docUrl = await (await uploadTask.onComplete).ref.getDownloadURL();
//docUrl is your url as a string
Firestore.instance
.collection('collectiion')
.document()
.updateData({"url": docUrl});
I am facing a anonymus closure error in flutter while signing in a user. It worked a few days before but now its not working, I dont no why. So please help and thanks in advance..Whenever i fill the details and tap on the signin button it throws the below error---
E/flutter ( 2914): [ERROR:flutter/shell/common/shell.cc(184)] Dart Error: Unhandled exception:
E/flutter ( 2914): FormatException: Unexpected end of input (at character 1)
E/flutter ( 2914):
E/flutter ( 2914): ^
E/flutter ( 2914):
E/flutter ( 2914): #0 _ChunkedJsonParser.fail (dart:convert/runtime/libconvert_patch.dart:1358:5)
E/flutter ( 2914): #1 _ChunkedJsonParser.close (dart:convert/runtime/libconvert_patch.dart:511:7)
E/flutter ( 2914): #2 _parseJson (dart:convert/runtime/libconvert_patch.dart:30:10)
E/flutter ( 2914): #3 JsonDecoder.convert (dart:convert/json.dart:540:36)
E/flutter ( 2914): #4 JsonCodec.decode (dart:convert/json.dart:167:41)
E/flutter ( 2914): #5 _SignInState._login.<anonymous closure> (package:restaurant_app/signin.dart:81:23)
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:restaurant_app/globalVar.dart';
import 'package:restaurant_app/homescreen.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:restaurant_app/signup.dart';
import 'package:http/http.dart' as http;
import 'package:flutter_html_view/html_parser.dart';
class SignIn extends StatefulWidget {
#override
_SignInState createState() => _SignInState();
}
class _SignInState extends State<SignIn> with SingleTickerProviderStateMixin
{
TabController controller;
TextEditingController _email = new TextEditingController();
TextEditingController _password = new TextEditingController();
bool loading;
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>
();
#override
void initState() {
// TODO: implement initState
super.initState();
controller = new TabController(length: 2, vsync: this);
loading = false;
_email = new TextEditingController(text: "rajeshvishnani");
_password = new TextEditingController(text: "Rajesh#MaaKiRasoi");
}
#override
void dispose() {
// TODO: implement dispose
super.dispose();
controller.dispose();
setState(() {
loading = false;
});
_email.dispose();
_password.dispose();
}
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
bool _autoValidate = false;
Future _writer(String username, String password, String token) async {
final storage = new FlutterSecureStorage();
await storage.write(key: authTokenKeys, value: token);
print(await storage.read(key: authTokenKeys));
await storage.write(key: nameKeys, value: username);
print(await storage.read(key: nameKeys));
await storage.write(key: passwordKeys, value: password);
}
static final String authTokenKeys = 'auth_token';
static final String nameKeys = 'username';
static final String passwordKeys = 'password';
_login(username, password) async {
setState(() {
loading = true;
});
var body = json.encode({
"username": username,
"password": password,
});
Map<String, String> headers = {
'Content-type': 'application/json',
'Accept': 'application/json',
};
await http
.post("${GlobalVar.Ip}/wp-json/jwt-auth/v1/token",
body: body, headers: headers)
.then((response) {
var body = json.decode(response.body);
if (response.statusCode == 200) {
// TODO: you need to store body['token'] to use in some authentication
loading = false;
_writer(_email.text, _password.text, body['token']);
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (BuildContext ctx) => HomePage()));
} else {
// TODO: alert message
final snackBar = SnackBar(
content: Text(body['message']),
);
_scaffoldKey.currentState.showSnackBar(snackBar);
}
setState(() {
loading = false;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
resizeToAvoidBottomPadding: false,
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('images/art.png'),
fit: BoxFit.fill,
colorFilter: ColorFilter.mode(
Colors.white12.withOpacity(0.2), BlendMode.dstATop),
),
),
child: ListView(
shrinkWrap: true,
physics: BouncingScrollPhysics(),
children: <Widget>[
SizedBox(
height: MediaQuery.of(context).size.height / 30,
),
Align(
alignment: Alignment.topCenter,
child: CircleAvatar(
backgroundColor: Colors.grey,
radius: 55.0,
backgroundImage: AssetImage('images/logo.png'),
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 30,
),
Stack(
alignment: Alignment.center,
children: <Widget>[
SizedBox(
height: MediaQuery.of(context).size.height / 300,
child: new Center(
child: new Container(
height: 10.0,
color: Colors.black12,
),
),
),
Row(
children: <Widget>[
SizedBox(
width: MediaQuery.of(context).size.width / 4,
),
Chip(
label: Text(
"SIGN IN",
style: TextStyle(color: Colors.white, fontSize: 18.0),
),
backgroundColor: Color(0xFFD1A155),
),
SizedBox(
width: MediaQuery.of(context).size.width / 35,
child: Container(
width: MediaQuery.of(context).size.height / 12,
height: 2.0,
color: Colors.white,
),
),
Chip(
label: Text(
"SIGN UP",
style: TextStyle(color: Colors.white, fontSize: 18.0),
),
backgroundColor: Colors.black87,
),
],
)
],
),
SizedBox(
height: MediaQuery.of(context).size.height / 35,
),
Align(
alignment: Alignment.center,
child: Text(
"Welcome back!",
style: TextStyle(
fontSize: 20.0,
color: Color(0xFFD1A155),
),
)),
SizedBox(
height: MediaQuery.of(context).size.height / 30,
),
Form(
key: _formKey,
autovalidate: _autoValidate,
child: Column(
children: <Widget>[
Theme(
data: ThemeData(
hintColor: Colors.black26,
primaryColor: Color(0xFFD1A155),
),
child: Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: TextFormField(
keyboardType: TextInputType.emailAddress,
//validator: _email.text.isEmpty?:null,
controller: _email,
decoration: InputDecoration(
border:
OutlineInputBorder(borderSide: BorderSide()),
prefixIcon: Icon(
Icons.email,
color: Color(0xFFD1A155),
),
hintText: 'Email Address',
hintStyle: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w400)),
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 45,
),
Theme(
data: ThemeData(
primaryColor: Color(0xFFD1A155),
hintColor: Colors.black26),
child: Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: TextFormField(
keyboardType: TextInputType.text,
obscureText: true,
controller: _password,
decoration: InputDecoration(
border:
OutlineInputBorder(borderSide: BorderSide()),
prefixIcon: Icon(
Icons.lock,
color: Color(0xFFD1A155),
),
hintText: 'Password',
hintStyle: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w400)),
),
),
),
Padding(
padding: const EdgeInsets.only(right: 15.0, left: 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
children: <Widget>[
ActionChip(
onPressed: () {},
avatar: Checkbox(
value: false,
onChanged: (bool z) {
print(z);
},
activeColor: Color(0xFFD1A155),
),
label: Text("Remember Me"),
backgroundColor: Colors.transparent,
),
],
),
Text(
"Forgot Password?",
style: TextStyle(
color: Color(0xFFD1A155),
),
),
],
),
),
Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: InkWell(
onTap: () {
_login(_email.text, _password.text);
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => HomePage()));
},
child: loading
? CircularProgressIndicator()
: Container(
height: MediaQuery.of(context).size.height / 13,
//width: MediaQuery.of(context).size.height / 1.8,
decoration: BoxDecoration(
color: Color(0xFFD1A155),
borderRadius: BorderRadius.circular(5.0),
),
child: Center(
child: Text(
"LOGIN",
style: TextStyle(
color: Colors.white, fontSize: 18.0),
),
),
),
),
)
],
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 15,
),
Stack(
alignment: Alignment.center,
children: <Widget>[
SizedBox(
height: 2.0,
child: new Center(
child: new Container(
height: 10.0,
color: Colors.black12,
),
),
),
Container(
height: MediaQuery.of(context).size.height / 18,
width: MediaQuery.of(context).size.height / 11,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(23.0),
color: Colors.white,
border: Border.all(color: Colors.black12)),
child: Center(
child: Text(
"OR",
style: TextStyle(fontSize: 18.0),
)),
),
],
),
SizedBox(
height: MediaQuery.of(context).size.height / 30,
),
Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: Row(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height / 13,
width: MediaQuery.of(context).size.width / 2.2,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: Colors.white,
border: Border.all(color: Colors.black12)),
child: Row(
children: <Widget>[
SizedBox(
width: 18.0,
),
Icon(Icons.tag_faces),
SizedBox(
width: 10.0,
),
Text(
"Facebook",
style: TextStyle(fontSize: 22.0, color: Colors.blue),
),
],
),
),
SizedBox(
width: MediaQuery.of(context).size.width / 40,
),
Container(
height: MediaQuery.of(context).size.height / 13,
width: MediaQuery.of(context).size.width / 2.3,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: Colors.white,
border: Border.all(color: Colors.black12)),
child: Row(
children: <Widget>[
SizedBox(
width: 18.0,
),
Icon(Icons.tag_faces),
SizedBox(
width: 10.0,
),
Text(
"Google+",
style: TextStyle(fontSize: 22.0, color: Colors.red),
),
],
),
),
],
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 20,
),
Align(
alignment: Alignment.center,
child: InkWell(
onTap: () => Navigator.push(
context, MaterialPageRoute(builder: (context) => SignUp())),
child: RichText(
text: TextSpan(
text: "Don't have an account?",
style: TextStyle(fontSize: 20.0, color: Colors.black87),
children: <TextSpan>[
TextSpan(
text: ' Sign up',
style: TextStyle(
color: Color(0xFFD1A155),
fontWeight: FontWeight.bold)),
])),
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 30,
),
],
),
),
);
}
}
I also have similar type of error, Be make sure that the argument of .decode method shouldn't be empty object. Instead of using this line:
var body = json.decode(response.body);
Try
if(response.body.isNotEmpty) {
json.decode(response.body);
}
Do try this, hope it will work for you.
Print your body and double check you aren't trying to decode an array rather than on object.
I had similar type of problem, i tried everything but eventually the problem was that I was using http intead of using https even though the apis was in https, i forgot to add s at in http.
After changing to https from http the error was gone.
check your backend it return null object in the response body