Upload and save image into firebase Storage flutter dart - firebase

i'm trying to upload picture and register user information into firebase storage and firestore the problem is it's not accepting this code for some reason it says i need to put ; after _registerUser()
here is the code i'm using to save and upload information :
Future<void> uploadAndSaveImage() async {
if (_imageFile != null) {
_passwordTextEditingController.text ==
_cPasswordTextEditingController.text
? _emailTextEditingController.text.isNotEmpty &&
_passwordTextEditingController.text.isNotEmpty &&
_cPasswordTextEditingController.text.isNotEmpty &&
_nameTextEditingController.text.isNotEmpty
?uploadToStorage() , _registerUser()
: displayDialog("Please fill up the registration complete form..")
: displayDialog("Password do not match.");
} else {
showDialog(
context: context,
builder: ((c) {
return ErrorAlertDialog(
message: "Please select an image.",
);
}));
}
}
the regiser user function :
FirebaseAuth _auth = FirebaseAuth.instance;
void _registerUser() async {
FirebaseUser firebaseUser;
await _auth
.createUserWithEmailAndPassword(
email: _emailTextEditingController.text.trim(),
password: _passwordTextEditingController.text.trim(),
)
.then((auth) {
firebaseUser = auth.user;
}).catchError((error) {
Navigator.pop(context);
showDialog(
context: context,
builder: (c) {
return ErrorAlertDialog(
message: error.message.toString(),
);
});
});
if (firebaseUser != null) {
saveUserInfoToFireStore(firebaseUser).then((value) {
Navigator.pop(context);
Route route = MaterialPageRoute(builder: (c) => StoreHome());
Navigator.pushReplacement(context, route);
});
}
}
Ps: i'm still new to this it's my third app with flutter

I have used this code to upload the user image from local storage to Firebase with uid as the reference name.
final _firebaseAuth = FirebaseAuth.instance;
FirebaseStorage firebaseStorage = FirebaseStorage.instance;
FirebaseFirestore firebaseFirestore = FirebaseFirestore.instance;
final imgPicker = ImagePicker();
File image;
String photoUrl = "";
bool _uploading = false;
uploadPic() async {
try {
setState(() {
_uploading = true;
});
// picking Image from local storage
final file = await imgPicker.getImage(
source: ImageSource.gallery,
);
if (file != null) {
image = File(file.path);
} else {
setState(() {
_uploading = false;
});
}
// creating ref at Firebase Storage with userID
Reference ref =
firebaseStorage.ref(_firebaseAuth.currentUser.uid).child("dp");
ref.putFile(image).whenComplete(() {
print("Pic Uploaded Successfully!");
setState(() {
_uploading = false;
});
// refreshing the UI when photo updated
getUploadedPic();
});
} catch (e) {
print(e);
}
}
After uploading you may get the image URL as follow:
getUploadedPic() async {
// getting dp URL link
photoUrl = await firebaseStorage
.ref("${_firebaseAuth.currentUser.uid}/dp")
.getDownloadURL()
.whenComplete(() => print("URL UPLOADED AT: $photoUrl"));
}

Related

'streamChatState != null': You must have a StreamChat widget at the top of your widget tree

I am new to flutter and im trying to run a chat app with getstream chat api and firebase.
I keep running into an error every time i try to sign in or sign up
Screenshot
this is main.dart
this is my sign_in_screen.dart
class SignInScreen extends StatefulWidget {
static Route get route => MaterialPageRoute(
builder: (context) => const SignInScreen(),
);
const SignInScreen({Key? key}) : super(key: key);
#override
State<SignInScreen> createState() => _SignInScreenState();
}
class _SignInScreenState extends State<SignInScreen> {
final auth = firebase.FirebaseAuth.instance;
final functions = FirebaseFunctions.instance;
final _formKey = GlobalKey<FormState>();
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
final _emailRegex = RegExp(
r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+#[a-zA-Z0-9]+\.[a-zA-Z]+");
bool _loading = false;
Future<void> _signIn() async {
if (_formKey.currentState!.validate()) {
setState(() {
_loading = true;
});
try {
// Authenticate with Firebase
final creds =
await firebase.FirebaseAuth.instance.signInWithEmailAndPassword(
email: _emailController.text,
password: _passwordController.text,
);
final user = creds.user;
if (user == null) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('User is empty')),
);
return;
}
// Get Stream user token from Firebase Functions
final callable = functions.httpsCallable('getStreamUserToken');
final results = await callable();
// Connnect stream user
final client = StreamChatCore.of(context).client;
await client.connectUser(
User(id: creds.user!.uid),
results.data,
);
// Navigate to home screen
await Navigator.of(context).pushReplacementNamed(Routes.HOME);
} on firebase.FirebaseAuthException catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(e.message ?? 'Auth error')),
);
} catch (e, st) {
logger.e('Sign in error, ', e, st);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('An error occured')),
);
}
setState(() {
_loading = false;
});
}
}
this is my home_page.dart
I tried looking online for answers but none worked.
It looks like you don't have a StreamChat widget in your widget tree; in order to use the Stream Chat Flutter SDK properly, you'll need this widget near the root of your widget tree.
Check out this example from the stream_chat_flutter package for how to do this.

Trying to login with google but always return null

hey guys i trying to login with google using firebase in flutter but its always return null in the next page
how can i get the current user in the next page after login with google
i already connect with firebase and generate sha-1 and sha-256
here's the code
login button
onPressed: () async {
setState(() {
_isSigningIn = true;
});
try {
final user = await googleSignIn.signIn();
final googleAuth = await user.authentication;
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken
);
final googleAccount = await FirebaseAuth.instance.signInWithCredential(credential);
if(googleAccount != null) {
Navigator.pushReplacementNamed(context, HomeScreen.id);
}
} catch (e) {
final snackbar = SnackBar(content: Text(e.toString()));
_scaffoldKey.currentState.showSnackBar(snackbar);
} finally {
setState(() {
_isSigningIn = false;
});
}
},
home_screen.dart
class _HomeScreenState extends State<HomeScreen> {
final _auth = FirebaseAuth.instance;
User _currentUser;
void getCurrentUser() async {
try {
var currentUser = await _auth.currentUser;
if (currentUser != null) {
_currentUser = currentUser;
}
} catch(e) {
print(e);
}
}
#override
void initState() {
super.initState();
getCurrentUser();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(_currentUser.email),
),
);
}
}
thank you
This line is an asynchronous function, it is for this reason that you receive null, you must add an await.
final googleAccount = await FirebaseAuth.instance.signInWithCredential(credential);
In addition to this, to access the information of the current user you must do it this way.
googleAccount.user

I have some problems in Flutter Firebase Login

I am coding an app for my company and I tried to add firebase authentication for login and registration to my app. The app shows no error and runs successfully.
But when a user tries to login with the wrong email and password, it is showing an internal flutter error instead of the toast I have programmed. And also I have used shared preferences to make users stay logged in.
So when a user tried to log in with the wrong credential it is showing an internal flutter error and when the app is re-opened, instead of going to the login screen, it is using the wrong credential and navigates user to Home Screen which is ridiculous.
These are the declared variables:
final FirebaseAuth firebaseAuth = FirebaseAuth.instance;
final _formKey = GlobalKey<FormState>();
TextEditingController _emailcontroller = TextEditingController();
TextEditingController _passwordcontroller = TextEditingController();
bool passvis = true;
bool loading = false;
And this is the function for login:
Future loginForm() async {
FormState formSate = _formKey.currentState;
if (formSate.validate()) {
final User firebaseUser = (await firebaseAuth
.signInWithEmailAndPassword(
email: _emailcontroller.text,
password: _passwordcontroller.text)
.catchError((errMsg) {
displayToast("Error: " + errMsg.toString(), context);
}))
.user;
if (firebaseUser != null) {
setState(() {
loading = true;
});
usersRef.child(firebaseUser.uid).once().then((DataSnapshot snap) {
if (snap.value != null) {
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) {
return LocationHome();
}));
displayToast("Succesfully LoggedIn!", context);
} else {
firebaseAuth.signOut();
displayToast("No user found! Please try SignUp", context);
}
});
} else {
displayToast("Error Occured! Cannot log you in", context);
}
}
}
}
And for Registration the code is below:
Future validateForm() async {
FormState formSate = _formKey.currentState;
if (formSate.validate()) {
final User firebaseUser = (await firebaseAuth
.createUserWithEmailAndPassword(
email: _emailcontroller.text,
password: _passwordcontroller.text)
.catchError((errMsg) {
displayToast("Error: " + errMsg.toString(), context);
}))
.user;
if (firebaseUser != null) {
Map userDataMap = {
"name": _namecontroller.text.trim(),
"email": _emailcontroller.text.trim(),
"phone": _phonecontroller.text.trim(),
};
usersRef.child(firebaseUser.uid).set(userDataMap);
displayToast("Succesfully Registered!", context);
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) {
return LocationHome();
}));
} else {
displayToast("User was unable to create", context);
}
}
}
}
The main.dart file is also coded correctly:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
SharedPreferences preferences = await SharedPreferences.getInstance();
var circle = preferences.getString("circle");
runApp(MaterialApp(
title: 'TaakStore',
home: circle == null ? Login() : Home(),
));
}
DatabaseReference usersRef =
FirebaseDatabase.instance.reference().child("users");
Dont worry about the displayToast function. It is a function manually created with flutter toast.
To display a toast, try the following:
try {
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: _emailcontroller.text,
password: _passwordcontroller.text
);
} on FirebaseAuthException catch (e) {
displayToast("Error: " + e.message.toString(), context);
print(e.message);
}
To check if the user is logged in or not use the following:
FirebaseAuth.instance
.authStateChanges()
.listen((User user) {
if (user == null) {
print('User is currently signed out!');
} else {
print('User is signed in!');
}
});
authStateChanges() is of type Stream<User> which will listen for any changes on the state of a user. So if user is logged in, it will return a valid user object and you can navigate to the home screen. Therefore no need to use shared preferences.
To display a toast
try {
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: _emailcontroller.text,
password: _passwordcontroller.text
);
} on FirebaseAuthException catch (e) {
displayToast("Error: " + e.message.toString(), context);
print(e.message);
}
To check if the user is logged in
//inside the main.dart in the "MaterialApp" widget
MaterialApp(home:buildHome(),)
buildHome(){return StreamBuilder(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (BuildContext context, AsyncSnapshot<User> snapshot) {
if (snapshot.hasData) {
print(snapshot);
//if the user is logged in return what you want
return "";
} else {
//else return what you want also
return"";
}
},
);}

Firestore: Data are Returned Back without the Right Favorite Items Status True or False

I have a flutter app and I am trying to fetch favorites data from cloud firestore database depending on userId.
The problem is that data are returned back without the right favorite items status true or false.
when I print favoriteData in console, I receive empty map like this: {}
Here is my code and how I tried to achieve this:
Future<void> fetchProducts() async {
final List<Product> loadedProducts = [];
var userId = await getCurrentUser();
final response = await Firestore
.instance
.collection("products")
.getDocuments();
final favoriteResponse = await Firestore.instance
.collection("userFavorites")
.document(userId)
.collection("MyFavorites")
.getDocuments();
final favoriteData = favoriteResponse.documents.asMap();
try{
print(favoriteData.toString());
response.documents.forEach((element) {
loadedProducts.add(Product(
id: element.documentID,
title: element.data['title'],
price: element.data['price'],
isFavorite: favoriteData == null ? false : favoriteData[element.documentID] ?? false,
));
});
_items = loadedProducts;
notifyListeners();
}catch(error){
print(error);
}
}
Here where I call fetchProducts which includes favourited items:
class _ProductsScreenState extends State<ProductsScreen> {
var _showOnlyFavorites = false;
var _isInit = true;
var _isLoading =false;
#override
void initState() {
super.initState();
}
#override
void didChangeDependencies() {
if(_isInit){
setState(() {
_isLoading = true;
});
Provider.of<Products>(context,listen: false).fetchProducts().then((_) {
setState(() {
_isLoading = false;
});
});
}
_isInit = false;
super.didChangeDependencies();
}
Here is a screenshot of documents I am trying to get their value:

Load Firestore document first in Flutter

Thanks in advance!
Flutter & Firestore
I'm checking if the user is an admin. I have a collection 'users', within: a bool: admin: true or false. If it's true it shows the admin Screen. Else it shows the main screen.
The problem: the first 1 second I get this Screen. (see screen shot, only 1 second visible) Is there an option to use a loading indicator when the app gets the data from firestore.
I tried adding if (currentUser.admin == null) {}
But that doesn't work.
User currentUser;
//I made a separate modal document
#override
void initState() {
super.initState();
pageController = PageController(initialPage: 0);
getUser();
}
getUser() async {
final FirebaseUser user = await FirebaseAuth.instance.currentUser();
DocumentSnapshot doc =
await Firestore.instance.collection("users").document(user.uid).get();
setState(() {
currentUser = User.fromDocument(doc);
});
print(currentUser.admin);
}
#override
Widget build(BuildContext context) {
if (currentUser.admin == true) {
return AdminScreen(
currentUser: currentUser,
);
} else {
return mainScreen();
}
}
}
Screenshot
UPDATE: tried this:
getUser() async {
final FirebaseUser user = await FirebaseAuth.instance.currentUser();
DocumentSnapshot doc =
await Firestore.instance.collection("users").document(user.uid).get();
if (doc.exists) {
try {
setState(() {
currentUser = User.fromDocument(doc);
});
} catch (e) {
print(e);
}
}
Found it!
For anyone having the same issue.
This was the problem:
if (currentUser.admin == true)
It should be: if (currentUser == null) or if (currentUser != null)
it doesn't work with currentUser.xxxx
You can also do as follows
Firestore.instance
.collection('driverListedRides')
.getDocuments()
.then((QuerySnapshot snapshot) => {
snapshot.documents.forEach((f) {
String _variableName = f.data["YourCollectionFieldId"];
})
});

Resources