How to use keys in stateful widgets? - firebase

I have two files, in one file, i have auth class, which handles the authentication.
Error handling is also in auth class, all i have to do is pass the errors to the login screen,
Here is my auth class
Future<FirebaseUser> handleSignInEmail(String email, String password) async {
FirebaseUser user;
var errorMessage;
try {
AuthResult result = await _auth.signInWithEmailAndPassword(
email: email, password: password);
user = result.user;
} catch (error) {
switch (error.code) {
case "ERROR_INVALID_EMAIL":
errorMessage = "Your email address appears to be malformed.";
break;
case "ERROR_WRONG_PASSWORD":
errorMessage = "Your password is wrong.";
break;
case "ERROR_USER_NOT_FOUND":
errorMessage = "User with this email doesn't exist.";
break;
case "ERROR_USER_DISABLED":
errorMessage = "User with this email has been disabled.";
break;
case "ERROR_TOO_MANY_REQUESTS":
errorMessage = "Too many requests. Try again later.";
break;
case "ERROR_OPERATION_NOT_ALLOWED":
errorMessage = "Signing in with Email and Password is not enabled.";
break;
default:
errorMessage = "An undefined Error happened.";
}
}
if (errorMessage != null) {
Body(
key: errorMessage,// the error occurs here :(
);
return Future.error(errorMessage);
}
return user;
}
Here is my body class, into which i have to pass the error.
class Body extends StatefulWidget {
final errorMess;
Body({Key key, this.errorMess}) : super(key: key);
#override
_BodyState createState() => _BodyState();
}
In my Bodystate, i have this function,
geterrorMesage() {
print(widget.errorMess);
}
When i try to call this function, an Exception occurs-
The argument type 'String' can't be assigned to the parameter type 'Key'.
how to resolve this issue?

You can copy paste run full code below
You can pass _key to Body and use _key.currentState to call geterrorMesage
code snippet
GlobalKey _key = GlobalKey();
...
final _BodyState _bodyState = _key.currentState;
_bodyState.geterrorMesage("this is test");
...
Body(
key: _key,
errorMess: "no error",
),
...
geterrorMesage(String errorMess) {
print(errorMess);
setState(() {
_errorMess = errorMess;
});
}
working demo
full code
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
GlobalKey _key = GlobalKey();
void _incrementCounter() {
final _BodyState _bodyState = _key.currentState;
_bodyState.geterrorMesage("this is test");
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
Body(
key: _key,
errorMess: "no error",
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
class Body extends StatefulWidget {
final errorMess;
Body({Key key, this.errorMess}) : super(key: key);
#override
_BodyState createState() => _BodyState();
}
class _BodyState extends State<Body> {
String _errorMess = "";
geterrorMesage(String errorMess) {
print(errorMess);
setState(() {
_errorMess = errorMess;
});
}
#override
void initState() {
super.initState();
_errorMess = widget.errorMess;
}
#override
Widget build(BuildContext context) {
return Text("${_errorMess}");
}
}

Related

Could not find the correct Provider<AuthenticationService> above this PageHome Widget

Here is my sign in page code below. I continuously get an error stating "The following ProviderNotFoundException was thrown while handling a gesture:
Error: Could not find the correct Provider<AuthenticationService> above this PageHome Widget". But all solutions I have seen do not work for my specific instance. How can I fix this error.
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:provider/provider.dart';
import 'package:optimistic_soundz/main.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: const FirebaseOptions(
));
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: PageHome(),
);
}
}
class PageHome extends StatefulWidget {
PageHome({Key? key}) : super(key: key);
#override
_PageHomeState createState() => _PageHomeState();
}
class _PageHomeState extends State {
final TextEditingController emailController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
TextField(
controller: emailController,
decoration: InputDecoration(
labelText: "Email",
),
),
TextField(
controller: passwordController,
decoration: InputDecoration(
labelText: "Password",
),
),
RaisedButton(
onPressed: () {
context.read<AuthenticationService>().signIn(
email: emailController.text.trim(),
password: passwordController.text.trim(),
);
},
child: Text("Sign in"),
)
],
),
);
}
}
class Signup extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
Provider<AuthenticationService>(
create: (_) => AuthenticationService(FirebaseAuth.instance),
),
StreamProvider(
create: (context) =>
context.read<AuthenticationService>().authStateChanges,
initialData: null,
),
],
child: MaterialApp(
title: 'Log in',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: PageHome(),
),
);
}
}
class AuthenticationWrapper extends StatelessWidget {
const AuthenticationWrapper({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
final firebaseUser = context.watch<User>();
if (firebaseUser != null) {
return PodcastApp();
}
return Text("no siign in");
}
}
class AuthenticationService {
final FirebaseAuth _firebaseAuth;
AuthenticationService(this._firebaseAuth);
Stream<User?> get authStateChanges => _firebaseAuth.authStateChanges();
Future<String?> signIn(
{required String email, required String password}) async {
try {
await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password);
return "Signed In";
} on FirebaseAuthException catch (e) {
return e.message;
}
}
Future<String?> signUp(
{required String email, required String password}) async {
try {
await _firebaseAuth.createUserWithEmailAndPassword(
email: email, password: password);
return "Signed up";
} on FirebaseAuthException catch (e) {
return e.message;
}
}
}
I am trying to create a sign in page that navigates to another widget when given correct info but whenever I sign in using correct or incorrect info nothing happens and I receive the error.

I am not able to catch the data from firebase messaging when my app is closed in Flutter

I am trying to catch key-value data from firebase messaging, i.e. by receiving notifications from firebase. I made a class for functionality and then assigned values to two global variables. Still, when I receive notification and click on it, no data is shown in my ui. Even title and body of notification is not shown when I start my app from scratch, i.e. first I run my app, close it, receive notification and then open it by clicking on it. I want that whether my app is closed, running in background or opened, key-value data could be feteched and desplayed on UI.
Here is my code -
variables.dart -
import 'package:flutter/cupertino.dart';
ValueNotifier<String> data = ValueNotifier("");
ValueNotifier<String> bodyData = ValueNotifier("");
notification.dart -
import 'dart:async';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter_application_notifications/variables.dart';
Future<void> onBackgroundMessage(RemoteMessage message) async {
await Firebase.initializeApp();
if (message.data.containsKey("data")) {
data.value = message.data["data"];
}
if (message.data.containsKey("body")) {
bodyData.value = message.data['body'];
}
}
class Messaging {
final firebaseMessaging = FirebaseMessaging.instance;
final streamController = StreamController<String>.broadcast();
final titleController = StreamController<String>.broadcast();
final bodyController = StreamController<String>.broadcast();
setNotifications() {
FirebaseMessaging.onBackgroundMessage(onBackgroundMessage);
FirebaseMessaging.onMessage.listen((message) async {
if (message.data.containsKey('data')) {
streamController.sink.add(message.data['data']);
}
if (message.data.containsKey('notification')) {
streamController.sink.add(message.data['notification']);
}
titleController.sink
.add(message.notification?.title ?? "Recieved Null Title");
bodyController.sink
.add(message.notification?.body ?? "Recieved Null Body");
});
final token = firebaseMessaging
.getToken()
.then((value) => print("Token is - $value"));
}
dispose() {
streamController.close();
bodyController.close();
titleController.close();
}
}
main.dart -
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_application_notifications/notification.dart';
import 'package:flutter_application_notifications/variables.dart';
void main() async {
await init();
runApp(const MyApp());
}
Future init() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String notificationTitle = "No title";
String notificationBody = "No Body";
String notificationData = "No Data";
int _counter = 0;
#override
void initState() {
super.initState();
final firebaseMessaging = Messaging();
firebaseMessaging.setNotifications();
firebaseMessaging.streamController.stream.listen(_changeData);
firebaseMessaging.bodyController.stream.listen(_changeBody);
firebaseMessaging.titleController.stream.listen(_changeTitle);
}
_changeData(String message) {
setState(() {
notificationData = message;
});
}
_changeTitle(String message) {
setState(() {
notificationTitle = message;
});
}
_changeBody(String message) {
setState(() {
notificationBody = message;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"Title is - $notificationTitle",
),
Text(
"Body is - $notificationBody",
),
Text(
"Data is - $notificationData",
),
ValueListenableBuilder(
valueListenable: data,
builder: (context, value, child) {
return Text('Received data is $value');
},
),
],
),
),
);
}
}

Provider in different route - Flutter

I'm new in Flutter development, i'm making an app with Firebase Auth, in where I'm using an Authentication Wrapper class that, if user is logged in, goes to Home Screen, else goes to SignIn Screen.
The problem is that, when I want to navigate to AuthWrapper, I get this error message in a red screen:
Error: Could not find the correct Provider<UserFirebaseModel> above this Builder Widget
This happens because you used a `BuildContext` that does not include the provider
of your choice. There are a few common scenarios:
- You added a new provider in your `main.dart` and performed a hot-reload.
To fix, perform a hot-restart.
- The provider you are trying to read is in a different route.
Providers are "scoped". So if you insert of provider inside a route, then
other routes will not be able to access that provider.
- You used a `BuildContext` that is an ancestor of the provider you are trying to read.
Make sure that Builder is under your MultiProvider/Provider<UserFirebaseModel>.
This usually happens when you are creating a provider and trying to read it immediately.
Here there are the most important classes of my code, where I think the problem is.
main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StreamProvider.value(
value: Authentication().user,
initialData: UserFirebaseModel.initialData(),
child: MaterialApp(
title: 'AccessCity',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
fontFamily: 'Montserrat',
),
routes: getAppRoutes(),
initialRoute: '/',
onGenerateRoute: (RouteSettings settings) {
return MaterialPageRoute(
builder: (BuildContext context) => HomeTempPage(),
);
},
),
);
}
}
authWrapper.dart
class AuthWrapper extends StatelessWidget {
#override
Widget build(BuildContext context) {
final user = Provider.of<UserFirebaseModel>(context);
print(user);
// ignore: unnecessary_null_comparison
if (user == null) {
return LoginPage();
} else {
return Home();
}
}
}
routes.dart
Map<String, WidgetBuilder> getAppRoutes() {
return <String, WidgetBuilder>{
// Home Temporal Page
'/': (BuildContext context) => HomeTempPage(),
// Components Pages
'generalBigButton': (BuildContext context) => GeneralBigButtonPage(),
'textEntryField': (BuildContext context) => TextEntryFieldPage(),
'secureTextEntryField': (BuildContext context) =>
SecureTextEntryFieldPage(),
'underlinedButton': (BuildContext context) => UnderlinedButtonPage(),
// Modules
'login': (BuildContext context) => LoginPage(),
'authWrapper': (BuildContext context) => AuthWrapper(),
};
}
homeTempPage.dart
const String _title = 'Home Temporal';
const String _goAccessCityButton = 'Ir a AccessCity';
const String _goAccessCityLabel = 'Ir a pantalla Login de la app';
class HomeTempPage extends StatefulWidget {
#override
_HomeTempPageState createState() => _HomeTempPageState();
}
class _HomeTempPageState extends State<HomeTempPage> {
final model = HomeTempModel();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(_title),
backgroundColor: mainBlue,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(height: 10),
MaterialButton(
child: Text(_goAccessCityButton),
color: Colors.blue,
textColor: Colors.white,
onPressed: () {
model.navigateToStart(context);
},
),
Text(_goAccessCityLabel),
SizedBox(height: 30),
Expanded(
child: Container(
child: ListView(
children: model.getComponents(context),
),
),
),
],
),
),
);
}
}
In this last class, the line
navigateToStart() method
goes to route 'authWrapper'.
UserFirebaseModel
class UserFirebaseModel {
final String id;
final String email;
UserFirebaseModel(this.id, this.email);
factory UserFirebaseModel.initialData() {
return UserFirebaseModel('', '');
}
}
Authentication class
class Authentication {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
// Create user based on User (ex FirebaseUser)
UserFirebaseModel? _userFromFirebaseUser(User? user) {
final _mail;
if (user != null) {
_mail = user.email;
if (_mail != null) {
return UserFirebaseModel(user.uid, _mail);
}
} else {
return null;
}
}
// Auth change user stream
Stream<UserFirebaseModel?> get user {
return _firebaseAuth.authStateChanges().map(_userFromFirebaseUser);
}
// Sign in with email and password
Future<String?> signIn({
required String email,
required String password,
}) async {
try {
await _firebaseAuth.signInWithEmailAndPassword(
email: email,
password: password,
);
print("Signed in");
return "";
} on FirebaseAuthException catch (e) {
return e.message;
}
}
User? getUser() {
try {
return _firebaseAuth.currentUser;
} on FirebaseAuthException {
return null;
}
}
}
Thanks for your help, i need to solve it!

Flutter/Firebase: Dynamic homepage depending on user loginStatus using MultiProvider issues

I want to check if the user is already logged in and show him page depending on that.
Here is my main.dart:
...
import 'firebase/authentication_service.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
Provider<AuthenticationService>(
create: (_) => AuthenticationService(FirebaseAuth.instance),
),
StreamProvider(
create: (context) =>
context.read<AuthenticationService>().authStateChanges,
initialData: null,
),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
backgroundColor: Colors.transparent,
primaryColor: Color(0xff4d629f),
buttonBarTheme:
ButtonBarThemeData(alignment: MainAxisAlignment.center)),
home: AuthenticationWrapper(),
),
);
}
}
class AuthenticationWrapper extends StatelessWidget {
#override
Widget build(BuildContext context) {
final firebaseUser = context.watch<User>();
if (firebaseUser != null) {
//If the user is successfully Logged-In.
return HomePage();
} else {
//If the user is not Logged-In.
return LoginPage();
}
}
}
And here is my Authentication_service.dart:
class AuthenticationService {
final FirebaseAuth _firebaseAuth;
UserModel userModel = UserModel.empty();
final userRef = FirebaseFirestore.instance.collection('users');
AuthenticationService(this._firebaseAuth);
Stream<User?> get authStateChanges => _firebaseAuth.authStateChanges();
Future<String> signIn(
{required String email, required String password}) async {
try {
await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password);
return "Signed in";
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found')
return "There is no user for that e-mail";
else if (e.code == 'wrong-password')
return "Entered wrong Password";
else
return "Something went wrong: $e";
}
}
...
And there are errors:
The following ProviderNotFoundException was thrown building AuthenticationWrapper(dirty):
Error: Could not find the correct Provider above this AuthenticationWrapper Widget
This happens because you used a BuildContext that does not include the provider
of your choice. There are a few common scenarios:
You added a new provider in your main.dart and performed a hot-reload.
To fix, perform a hot-restart.
The provider you are trying to read is in a different route.
Providers are "scoped". So if you insert of provider inside a route, then
other routes will not be able to access that provider.
You used a BuildContext that is an ancestor of the provider you are trying to read.
Make sure that AuthenticationWrapper is under your MultiProvider/Provider.
This usually happens when you are creating a provider and trying to read it immediately.
For example, instead of:
Widget build(BuildContext context) {
return Provider<Example>(
create: (_) => Example(),
// Will throw a ProviderNotFoundError, because `context` is associated
// to the widget that is the parent of `Provider<Example>`
child: Text(context.watch<Example>()),
),
}
consider using builder like so:
Widget build(BuildContext context) {
return Provider<Example>(
create: (_) => Example(),
// we use `builder` to obtain a new `BuildContext` that has access to the provider
builder: (context) {
// No longer throws
return Text(context.watch<Example>()),
}
),
}
Unfortunately it didn't help or i just can't implement it in a right way.
#SumerSingh solution worked, i just changed it a bit for my use.
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
bool _initialized = false;
bool _error = false;
void initializeFlutterFire() async {
try {
await Firebase.initializeApp();
setState(() {
_initialized = true;
});
} catch (e) {
setState(() {
_error = true;
});
}
}
#override
void initState() {
initializeFlutterFire();
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'App',
debugShowCheckedModeBanner: false,
home: Scaffold(
body: _error
? splashScreen()
: !_initialized
? splashScreen()
: SplashScreen()));
}
}
class SplashScreen extends StatefulWidget {
SplashScreen({Key? key}) : super(key: key);
#override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
final FirebaseAuth _auth = FirebaseAuth.instance;
var currentUser;
AuthenticationService _authService =
new AuthenticationService(FirebaseAuth.instance);
late final UserModel userModel;
bool isAuthinticated = false;
_isUserSignedin() async {
currentUser = _auth.currentUser;
userModel = await _authService.getUserFromDB(uid: _auth.currentUser!.uid);
setState(() {
currentUser != null ? isAuthinticated = true : isAuthinticated = false;
});
}
#override
void initState() {
super.initState();
_isUserSignedin();
startTime();
}
startTime() async {
var _duration = new Duration(seconds: 4);
return new Timer(_duration, navigationPage);
}
Widget userAuthState() {
if (!isAuthinticated)
return LoginPage();
else if (userModel.type == 'Attendant')
return AttendantMainPage();
else
return SeniorMainPage();
}
void navigationPage() {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (BuildContext context) => userAuthState()),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(body: splashScreen());
}
}
Widget splashScreen() {
return Container(
height: double.maxFinite,
width: double.maxFinite,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
CircleAvatar(
radius: 80.0, child: Image.asset('assets/logo.png')),
Text("APP NAME",
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
CircularProgressIndicator()
]),
);
}
It works well, thank you for help!

FirebaseAuth.instance.userChanges stream does not emit the signed in user after page reload (web)

On Flutter Web, the userChanges stream from a FirebaseAuth instance never emits the signed in user after a page reload. Instead, it only emits null. With the example below, the app gets stuck on the loading page.
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(App());
}
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: '/loading',
onGenerateRoute: (settings) {
switch (settings.name) {
case '/error':
return MaterialPageRoute(builder: (_) => ErrorScreen());
case '/loading':
return MaterialPageRoute(builder: (_) => LoadingScreen());
case '/signin':
return MaterialPageRoute(builder: (_) => SignInScreen());
case '/welcome':
return MaterialPageRoute(builder: (_) => WelcomeScreen());
default:
return MaterialPageRoute(
builder: (_) => Center(child: Text('Unknown route')));
}
},
);
}
}
class ErrorScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Center(
child: Text('An error occurred.'),
),
);
}
}
class LoadingScreen extends StatefulWidget {
#override
_LoadingScreenState createState() => _LoadingScreenState();
}
class _LoadingScreenState extends State<LoadingScreen> {
#override
void initState() {
init();
super.initState();
}
init() async {
try {
await Firebase.initializeApp();
if (kDebugMode) {
await FirebaseAuth.instance.useEmulator('http://localhost:1001');
}
final preferences = await SharedPreferences.getInstance();
bool signedIn = preferences.getBool('IS_SIGNED_IN') ?? false;
String landingPath = '/signin';
if (signedIn) {
landingPath = '/welcome';
// Wait for the userChanges to emit a non-null element.
await FirebaseAuth.instance
.userChanges()
.firstWhere((user) => user != null);
}
Navigator.of(context).pushReplacementNamed(landingPath);
} catch (error) {
print(error);
Navigator.of(context).pushReplacementNamed('/error');
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Center(
child: Text('Loading...'),
),
);
}
}
class SignInScreen extends StatelessWidget {
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: [
TextField(
controller: _emailController,
decoration: InputDecoration(labelText: 'Email address'),
),
TextField(
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
controller: _passwordController,
),
ElevatedButton(
onPressed: () => _submit(context),
child: Text('SIGN IN'),
),
],
),
),
);
}
void _submit(BuildContext context) async {
final email = _emailController.text;
final password = _passwordController.text;
FirebaseAuth.instance
.signInWithEmailAndPassword(email: email, password: password)
.then((credential) async {
final preferences = await SharedPreferences.getInstance();
await preferences.setBool('IS_SIGNED_IN', true);
Navigator.of(context).pushReplacementNamed('/welcome');
});
}
}
class WelcomeScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: [
Text('Welcome!'),
ElevatedButton(
onPressed: () => _signOut(context),
child: Text('SIGN OUT'),
)
],
),
),
);
}
void _signOut(BuildContext context) {
FirebaseAuth.instance.signOut().then((_) async {
final preferences = await SharedPreferences.getInstance();
await preferences.setBool('IS_SIGNED_IN', false);
Navigator.of(context).pushReplacementNamed('/signin');
});
}
}
If it helps, I'm using version 8.3.0 of the Firebase Javascript libraries in my index.html file.
Am I missing something here?
It turns out the code above is fine. The issue is the emulator. Commenting out these lines of code makes the app behave as expected:
if (kDebugMode) {
FirebaseAuth.instance.useEmulator('http://localhost:1001');
}
I've filed a bug report on FlutterFire's repo about this emulator issue.

Resources