Undefined name 'FirebaseAuth' - flutter

The FirebaseAuth was working fine for me a few hours back but now I am receiving an error as :
Undefinded name 'FirebaseAuth' .I am unable to resolve it. Don't know what is the real issue. Would be a great help for me if anybody could step in and provide me a or more solutions.
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:jiwdopani/UserLogIn/MenuUse.dart';
import 'package:jiwdopani/services/error_handler.dart';
import 'package:jiwdopani/UserLogIn/login_page.dart';
class AuthService {
handleAuth() {
return StreamBuilder(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (BuildContext context, snapshot) {
if (snapshot.hasData) {
return UserMenu();
} else
return LoginPage();
});
}
//Sign out
signOut() async {
try {
return await FirebaseAuth.instance.signOut();
}
catch(e){
print(e.toString());
return null;
}
}
//Sign In
signIn(String email, String password, context) {
FirebaseAuth.instance
.signInWithEmailAndPassword(email: email, password: password)
.then((val) {
UserMenu();
}).catchError((e) {
ErrorHandler().errorDialog(context, e);
});
}
//Signup a new user
signUp(String email, String password) {
return FirebaseAuth.instance
.createUserWithEmailAndPassword(email: email, password: password);
}
//Reset Password
resetPasswordLink(String email) {
FirebaseAuth.instance.sendPasswordResetEmail(email: email);
}

I fixed some of your code by adding types to the functions:
class AuthService {
Widget handleAuth() {
return StreamBuilder(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (BuildContext context, snapshot) {
if (snapshot.hasData) {
return Container(); //change it back to your widget
} else
return Container();//change it back to your widget
});
}
//Sign out
void signOut() async {
try {
return await FirebaseAuth.instance.signOut();
} catch (e) {
print(e.toString());
return null;
}
}
//Sign In
void signIn(String email, String password, BuildContext context) {
FirebaseAuth.instance
.signInWithEmailAndPassword(email: email, password: password)
.then((val) {
return Container();
});
}
//Signup a new user
Future<UserCredential> signUp(String email, String password) async {
return await FirebaseAuth.instance
.createUserWithEmailAndPassword(email: email, password: password);
}
//Reset Password
void resetPasswordLink(String email) {
FirebaseAuth.instance.sendPasswordResetEmail(email: email);
}
}
Anyway, I think it's best not to have Widgets or UI in Auth Class, it is always better to separate UI from logic.

Related

How to get user credential while moving to welcome screen in flutter

I have created simple home screen for login and register,
Here I have taken readymade code from a channel, and now I need to change little bit..
code is simple, so no more details to explain
just I want to pass Usercredential to my welcome screen...
here is my code
class MainPage extends StatelessWidget {
const MainPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context,snapshot){
if(snapshot.hasData)
{
print(snapshot.data);
return WelcomePage(usercredential:
//how to get usercredential,
);
}
else
{
return AuthPage();
}
},
),
);
}
}
here is my login page's login code
Future signin() async {
UserCredential? usercredential;
try {
usercredential=await FirebaseAuth.instance.signInWithEmailAndPassword(
email: txtemailcontroller.text, password: txtpasswordcontroller.text);
} on FirebaseAuthException catch (e) {
print("Error is =" + e.toString());
}
}
and register page's register code
Future signup() async {
UserCredential? usercredential;
try {
if (txtconfirmpasswordcontroller.text.trim() ==
txtpasswordcontroller.text.trim()) {
usercredential = await FirebaseAuth.instance
.createUserWithEmailAndPassword(
email: txtemailcontroller.text,
password: txtpasswordcontroller.text);
} else {
print("passwrod does not match");
}
} on FirebaseAuthException catch (e) {
print('Error while register' + e.toString());
}
if (usercredential != null) {
String userid = usercredential.user!.uid;
UserModel newuser = UserModel(
email: txtemailcontroller.text,
userid: userid,
fullname:
txtfirstnamecontroller.text + ' ' + txtlastnamecontroller.text,
profilepicture: '');
}
}
so far I know, user credential generated while createuserwithemailandpassword and signinwithemailandpassword method, but how to get it here....where I need...
Add this In your Welcome page:
User? currentUser=FirebaseAuth.instance.currentUser;
Then you can call it any where and get user details like email & id & display name.
for example:
currentUser.email
or
currentUser.uid

Flutter Connection State Management

Hello I am doing my fist App in Flutter and i am just setting up the authentication with FireBase, and a mistake its happenning. Im trying to manage the state and navigate between Home and Login with the streambuilder, and its working fine but only if i do a hot restart on Android Studio after registering a new user. After the hot reload it works fine, i am able to login with any of the existing users and it navigates to the home screen, and when i log out goes back to login screen, but if i create new user than just stops working, the screens do not alterate anymore when i log in with any of the old users...
here its my main
class _MyAppState extends State<MyApp> {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(primaryColor: cPrimary),
home: StreamBuilder(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if(snapshot.connectionState == ConnectionState.active){
if(snapshot.hasData){
return Home_Screen();
} else if (snapshot.hasError){
return Center(child: Text('${snapshot.error}'),);
}
} else if (snapshot.connectionState == ConnectionState.waiting){
return Center(child: CircularProgressIndicator(color: cPrimary,));
}
return LoginScreen();
}
)
);
}
}
Here is my login and register functions
//Sign Up
Future <void> signUp({
required String email,
required String password,
required String username,
}) async {
try {
if(email.isNotEmpty && password.isNotEmpty && username.isNotEmpty){
UserCredential userCredential = await _auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
//add user to database
await _firestore.collection('users').doc(userCredential.user!.uid).set({
'username' : username,
'email' : email,
'uid' : userCredential.user!.uid,
});
}
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
print('The password provided is too weak.');
} else if (e.code == 'email-already-in-use') {
print('The account already exists for that email.');
}
} catch (e) {
print(e);
}
}
//Log In
Future <void> logIn({
required String email,
required String password,
}) async {
try {
if(email.isNotEmpty && password.isNotEmpty ){
UserCredential userCredential = await _auth.signInWithEmailAndPassword(
email: email,
password: password,
);}
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
print('No user found for that email.');
} else if (e.code == 'wrong-password') {
print('Wrong password provided for that user.');
}
}
}
and here its how i am calling the functions on my screens
ElevatedButton(
onPressed: () async {
setState(() {
_isLoading = true;
});
await AuthService().logIn(
email: _emailController.text,
password: _passwordController.text,);
setState(() {
setState(() {
_isLoading = false;
});
});
},
ElevatedButton(
onPressed: () async {
setState(() {
_isLoading = true;
});
await AuthService().signUp(
email: _emailController.text,
password: _passwordController.text,
username: _usernameController.text,
);
setState(() {
_isLoading = false;
});
After creating the user account, ensure you log in as well.
//Sign Up
Future <void> signUp({
required String email,
required String password,
required String username,
}) async {
try {
if(email.isNotEmpty && password.isNotEmpty && username.isNotEmpty){
UserCredential userCredential = await _auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
//add user to database
await _firestore.collection('users').doc(userCredential.user!.uid).set({
'username' : username,
'email' : email,
'uid' : userCredential.user!.uid,
});
}
// add this
await logIn(email: email, password: password);
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
print('The password provided is too weak.');
} else if (e.code == 'email-already-in-use') {
print('The account already exists for that email.');
}
} catch (e) {
print(e);
}
}

UserProfile crashes after auth.getCurrentUser()

I am making an app in flutter an now when i try to show the user Name on the profile i got this error
════════ Exception caught by widgets library ═══════════════════════════════════
The following NoSuchMethodError was thrown building UserPage(dirty, dependencies: [MediaQuery], state: _UserProfile#ca57c):
The getter 'auth' was called on null.
Receiver: null
Tried calling: auth
The relevant error-causing widget was
UserPage
lib/HomePage.dart:92
When the exception was thrown, this was the stack
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
#1 _UserProfile.build
package:tariffo/UserPage.dart:131
#2 StatefulElement.build
package:flutter/…/widgets/framework.dart:4619
#3 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4502
#4 StatefulElement.performRebuild
package:flutter/…/widgets/framework.dart:4675
...
═══════════════════════════════════════════════════════════════════════════════
and i used this code
FutureBuilder(
future:
Provider.of(context).auth.getCurrentUser(),
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.done) {
return Text("${snapshot.data.displayName}",
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 22,
));
} else {
return CircularProgressIndicator();
}
},
),
This is the code that i used for my auth.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'User.dart';
String email, name, photoUrl;
class Authentication {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
final GoogleSignIn _googleSignIn = GoogleSignIn();
Stream<String> get onAuthStateChanged => _firebaseAuth.onAuthStateChanged.map(
(FirebaseUser user) => user?.uid,
);
// GET UID
Future<String> getCurrentUID() async {
return (await _firebaseAuth.currentUser()).uid;
}
// GET CURRENT USER
Future getCurrentUser() async {
return await _firebaseAuth.currentUser();
}
// Email & Password Sign Up
Future<String> createUserWithEmailAndPassword(
String email, String password, String name) async {
final authResult = await _firebaseAuth.createUserWithEmailAndPassword(
email: email,
password: password,
);
// Update the username
await updateUserName(name, authResult.user);
return authResult.user.uid;
}
Future updateUserName(String name, FirebaseUser currentUser) async {
var userUpdateInfo = UserUpdateInfo();
userUpdateInfo.displayName = name;
await currentUser.updateProfile(userUpdateInfo);
await currentUser.reload();
}
// Email & Password Sign In
Future<String> signInWithEmailAndPassword(
String email, String password) async {
return (await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password))
.user
.uid;
}
// Sign Out
signOut() {
return _firebaseAuth.signOut();
}
// Reset Password
Future sendPasswordResetEmail(String email) async {
return _firebaseAuth.sendPasswordResetEmail(email: email);
}
// Create Anonymous User
Future singInAnonymously() {
return _firebaseAuth.signInAnonymously();
}
Future convertUserWithEmail(
String email, String password, String name) async {
final currentUser = await _firebaseAuth.currentUser();
final credential =
EmailAuthProvider.getCredential(email: email, password: password);
await currentUser.linkWithCredential(credential);
await updateUserName(name, currentUser);
}
Future convertWithGoogle() async {
final currentUser = await _firebaseAuth.currentUser();
final GoogleSignInAccount account = await _googleSignIn.signIn();
final GoogleSignInAuthentication _googleAuth = await account.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
idToken: _googleAuth.idToken,
accessToken: _googleAuth.accessToken,
);
await currentUser.linkWithCredential(credential);
await updateUserName(_googleSignIn.currentUser.displayName, currentUser);
}
// GOOGLE
Future<String> signInWithGoogle() async {
final GoogleSignInAccount account = await _googleSignIn.signIn();
final GoogleSignInAuthentication _googleAuth = await account.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
idToken: _googleAuth.idToken,
accessToken: _googleAuth.accessToken,
);
return (await _firebaseAuth.signInWithCredential(credential)).user.uid;
}
// APPLE
}
class NameValidator {
static String validate(String value) {
if (value.isEmpty) {
return "Name can't be empty";
}
if (value.length < 2) {
return "Name must be at least 2 characters long";
}
if (value.length > 50) {
return "Name must be less than 50 characters long";
}
return null;
}
}
class EmailValidator {
static String validate(String value) {
if (value.isEmpty) {
return "Email can't be empty";
}
return null;
}
}
class PasswordValidator {
static String validate(String value) {
if (value.isEmpty) {
return "Password can't be empty";
}
return null;
}
}
and this is the code for User.dart
import 'package:flutter/material.dart';
class User {
final String uid;
User({this.uid});
String adress;
bool business;
Map<String, dynamic> toJson() => {
'adress': adress,
'business': business,
};
}
Now it just appear a red background when i try to acces the profile page pressing the profile icon button
provider_widget.dart
import 'package:flutter/material.dart';
import 'auth.dart';
class Provider extends InheritedWidget {
final Authentication auth;
Provider({Key key, Widget child, this.auth}) : super(key: key, child: child);
#override
bool updateShouldNotify(InheritedWidget oldWidget) {
return true;
}
static Provider of(BuildContext context) =>
(context.inheritFromWidgetOfExactType(Provider) as Provider);
}

Flutter onAuthStateChanged stream not updating child when registering or signing in

I wrapped my app inside a StreamProvider.value, where the value is an onAuthStateChanged stream, and the child is the main MaterialApp. My main wrapper listens to this value using Provider.of. This works fine for signing out; once I sign out, the StreamProvider notifies my main wrapper, and the app is redirected to the welcome screen.
But when I try to create an account or sign in, it seems the StreamProvider is not being notified of the onAuthStateChanged stream. This is why it's so weird, if the stream wasn't working, then signing out should also not work. Also, when I hot restart, I do get redirected to the home screen. I've scattered the internet: no luck. Here's the appropriate code:
In main.dart
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StreamProvider<FirebaseUser>.value(
value: AuthService().userStream,
child: MaterialApp(
home: Wrapper(),
theme: ThemeData.light().copyWith(
appBarTheme: AppBarTheme(color: Colors.lightBlue),
scaffoldBackgroundColor: Colors.white,
),
),
);
}
}
In wrapper.dart
class Wrapper extends StatelessWidget {
#override
Widget build(BuildContext context) {
print('Rebuilding');
final user = Provider.of<FirebaseUser>(context);
if (user == null) {
return Welcome();
} else {
return Home();
}
}
}
In auth_service.dart
class AuthService {
FirebaseAuth _auth = FirebaseAuth.instance;
Stream<FirebaseUser> get userStream {
return _auth.onAuthStateChanged;
}
Future registerWithEmailAndPassword(String email, String password) async {
try {
AuthResult result = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
FirebaseUser user = result.user;
return user;
} catch (e) {
print(e.toString());
return null;
}
}
Future signInWithEmailAndPassword(String email, String password) async {
try {
AuthResult result = await _auth.signInWithEmailAndPassword(
email: email, password: password);
FirebaseUser user = result.user;
return user;
} catch (e) {
print(e.toString());
return null;
}
}
void signOut() {
try {
_auth.signOut();
} catch (e) {
print(e);
}
}
}
Also, inside my welcome.dart, I have this set up as a test:
onPressed: () {
FirebaseAuth.instance.onAuthStateChanged
.listen((event) {
print('$event from .listen');
});
}
And this does notify my everytime I sign in, out or register, this tells me that there is nothing wrong with onAuthStateChanged, or the way I set it up.
If you need any more information, let me know. I don't want to make the question any longer. Thank you for your help!

Flutter: StreamBuilder Snapshot -- No Data

I am just learning Flutter and am trying to use a StreamBuilder to display a Login / Register page if the user is logged out, or a Profile page if the user is logged in. My code is below:
Auth Service:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class AuthUser {
AuthUser({#required this.uid, #required this.email});
final String uid;
final String email;
}
abstract class AuthBase {
Future<AuthUser> currentUser();
Future<AuthUser> signIn({String email, String pw});
Future<AuthUser> registerUser({String email, String pw});
Stream<AuthUser> get onAuthStateChanged;
Future<void> signOut();
}
class Auth implements AuthBase {
final _firebaseAuth = FirebaseAuth.instance;
AuthUser _userFromFirebase(FirebaseUser user) {
if (user != null) {
return AuthUser(uid: user.uid, email: user.email);
} else {
return null;
}
}
#override
Stream<AuthUser> get onAuthStateChanged {
return _firebaseAuth.onAuthStateChanged.map(_userFromFirebase);
}
#override
Future<AuthUser> currentUser() async {
final user = await _firebaseAuth.currentUser();
return _userFromFirebase(user);
}
#override
Future<AuthUser> signIn({String email, String pw}) async {
final authResult = await _firebaseAuth.signInWithEmailAndPassword(email: email, password: pw);
return _userFromFirebase(authResult.user);
}
#override
Future<AuthUser> registerUser({String email, String pw}) async {
final authResult = await _firebaseAuth.createUserWithEmailAndPassword(email: email, password: pw);
return _userFromFirebase(authResult.user);
}
#override
Future<void> signOut() async {
await _firebaseAuth.signOut();
}
}
StreamBuilder:
class WelcomeScreen extends StatelessWidget {
WelcomeScreen({#required this.auth});
static const String id = '/';
final AuthBase auth;
#override
Widget build(BuildContext context) {
return StreamBuilder<AuthUser>(
stream: auth.onAuthStateChanged,
builder: (context, snapshot) {
if (snapshot.hasData) {
AuthUser user = snapshot.data;
if (user == null) {
return displayLoginOrRegPage(context);
} else {
return ProjectScreen(
user: user,
auth: auth,
);
}
} else {
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
},
);
}
It was my understanding the stream would begin emitting 'null' once it was initialized, and would continue doing so until it fired off an Auth state change...
But the snapshot continually reports "No Data" and thus my code is stuck on the CircularProgressIndicator.
BTW, if I display the log-in screen in place of the progress indicator, the code works. So I'm clearly not understanding the whole stream initialization process.
Can somebody kindly explain to me where I have gone wrong here? Thanks a million in advance.
As you mentioned, when stream initialises it emits null, but when the user is not logged in, it still emits null, which stream considers as no data i.e null that's the reason for the error.
You can use Streambuilder's connection state to differentiate between no user null and null after initialisation.
I hope following code helps you.
if (snapshot.connectionState == ConnectionState.active) {
if (snapshot.data == null) {
return displayLoginOrRegPage(context);
} else {
AuthUser user = snapshot.data;
return ProjectScreen(
user: user,
auth: auth,
);
}
} else {
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
Per #VirenVVarasadiya, it was definitely a case of checking the ConnectionState. Here is the final working code. Thank you!
#override
Widget build(BuildContext context) {
return StreamBuilder<AuthUser>(
stream: auth.onAuthStateChanged,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
if (snapshot.data != null) {
AuthUser user = snapshot.data;
return ProjectScreen(
user: user,
auth: auth,
);
} else {
return displayLoginOrRegPage(context);
}
} else {
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
},
);
}
Try to change WelcomeScreen to state full Widget.