import 'dart:async';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn _googleSignIn = new GoogleSignIn();
class HomePage extends StatefulWidget {
static String tag = 'home-page';
#override
HomePageState createState() {
return new HomePageState();
}
}
class HomePageState extends State<HomePage> {
Stream<FirebaseUser> _currentUser;
Future<FirebaseUser> signInWithGoogle() async {
print('google signin invoked');
GoogleSignInAccount googleUser = await _googleSignIn.signIn();
GoogleSignInAuthentication googleAuth = await googleUser.authentication;
FirebaseUser user = await _auth.signInWithGoogle(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
print("signed in " + user.displayName);
return user;
}
#override
Widget build(BuildContext context) {
final lblWelcome = Padding(
padding: EdgeInsets.all(8.0),
child: Text('Frnds Payment',
style: TextStyle(fontSize: 28.0, color: Colors.green)));
final btnSignin = new MaterialButton(
child: const Text('Sign In with Google'),
onPressed: () {
print('button clicked');
_currentUser = signInWithGoogle()?.asStream();
});
final txtOutput = new StreamBuilder<FirebaseUser>(
stream: _currentUser,
builder: (BuildContext context, AsyncSnapshot<FirebaseUser> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return new Center(child: new CircularProgressIndicator());
default:
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
else
return new Center(
child: new Text('${snapshot.data.displayName}'));
}
});
final body = Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[lblWelcome, btnSignin, txtOutput],
),
);
return Scaffold(body: body);
}
}
I am newbee to Dart, this is my 1st app.
I need to display the Username after the signin is succesful.
Whenever I start the application it goes to ConnectionState.waiting instead of ConnectionState.none.
Also it does not render the textbox with displayname on succesful signin. reloading it does render the display name.
ConnectionState.none means there is no stream assigned,
but you have
setState(() => _currentUser = signInWithGoogle()?.asStream());
this means the StreamBuilder subscribed to this stream and waits for events.
Related
I get endless loading Icon when selecting an existing account
I can create an account just fine for the first time and login, but when i close android studio then restart main.dart & emulator then try to sign in to that existing account, i get infinite loading icon :
Here's the loginPage.dart code:-
import 'dart:async';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:telegramchatapp/Pages/HomePage.dart';
import 'package:telegramchatapp/Widgets/ProgressWidget.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:shared_preferences/shared_preferences.dart';
class LoginScreen extends StatefulWidget {
LoginScreen({Key key}) : super(key : key);
#override
LoginScreenState createState() => LoginScreenState();
}
class LoginScreenState extends State<LoginScreen> {
final GoogleSignIn googleSignIn = GoogleSignIn();
final FirebaseAuth firebaseAuth = FirebaseAuth.instance;
SharedPreferences preferences;
bool isLoggedIn = false;
bool isLoading = false;
FirebaseUser currentUser;
#override
void initState() {
// TODO: implement initState
super.initState();
isSignedIn();
}
void isSignedIn() async{
this.setState(() {
isLoggedIn = true;
});
preferences = await SharedPreferences.getInstance();
isLoggedIn = await googleSignIn.isSignedIn();
if(isLoggedIn){
Navigator.push(context, MaterialPageRoute(builder: (context) => HomeScreen(currentUserId: preferences.getString("id"))));
}
this.setState(() {
isLoading = false;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [Colors.blueAccent, Colors.black12],
),
),
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
"Solef App",
style: TextStyle(fontSize: 82.0, color: Colors.white, fontFamily: "Signatra"),
),
GestureDetector(
onTap: controlSignIn,
child: Center(
child: Column(
children: <Widget>[
Container(
width: 270.0,
height: 65.0,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
"assets/images/google_signin_button.png"),
),
),
),
Padding(
padding: EdgeInsets.all(1.0),
child: isLoading ? circularProgress() : Container(),
),
],
),
),
)
],
),
),
);
}
Future<Null> controlSignIn() async {
preferences = await SharedPreferences.getInstance();
this.setState(() {
isLoading = true;
});
/*GoogleSignIn _googleSignIn = GoogleSignIn(
scopes: [
'email',
'https://www.googleapis.com/auth/contacts.readonly',
],
);*/
GoogleSignInAccount googleUser = await googleSignIn.signIn();
GoogleSignInAuthentication googleAuthentication = await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(idToken: googleAuthentication.idToken, accessToken: googleAuthentication.accessToken);
FirebaseUser firebaseUser = (await firebaseAuth.signInWithCredential(credential)).user;
//SignIn Success
if(firebaseUser != null){
//check if already signup
final QuerySnapshot resultQuery = await Firestore.instance.collection("users").where("id", isEqualTo: firebaseUser.uid).getDocuments();
final List<DocumentSnapshot> documentSnapshots = resultQuery.documents;
//save data to firestore - if new user
if(documentSnapshots.length == 0){
Firestore.instance.collection("users").document(firebaseUser.uid).setData(
{
"nickname": firebaseUser.displayName,
"photoUrl": firebaseUser.photoUrl,
"id": firebaseUser.uid,
"aboutMe": "I'm using SOLEF chat app.",
"createdAt": DateTime.now().millisecondsSinceEpoch.toString(),
"chatingWith": null,
});
//write data to Local
currentUser = firebaseUser;
await preferences.setString("id", currentUser.uid);
await preferences.setString("nickname", currentUser.displayName);
await preferences.setString("photoUrl", currentUser.photoUrl);
}else{
//write data to Local
currentUser = firebaseUser;
await preferences.setString("id", documentSnapshots[0]["id"]);
await preferences.setString("nickname", documentSnapshots[0]["nickname"]);
await preferences.setString("photoUrl", documentSnapshots[0]["photoUrl"]);
await preferences.setString("aboutMe", documentSnapshots[0]["aboutMe"]);
}
Fluttertoast.showToast(msg: "SignIn Successful.");
this.setState(() {
isLoading = false;
});
Navigator.push(context, MaterialPageRoute(builder: (context) => HomeScreen(currentUserId: firebaseUser.uid)));
}
//SignIn Not Success - Failed
else{
Fluttertoast.showToast(msg: "Try Again, SignIn Failed.");
this.setState(() {
isLoading = false;
});
}
}
}
Here's the Homepage.dart:
import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
import '../main.dart';
class HomeScreen extends StatefulWidget {
final String currentUserId;
HomeScreen({Key key, #required this.currentUserId}) : super(key : key);
#override
State createState() => HomeScreenState();
}
class HomeScreenState extends State<HomeScreen> {
#override
Widget build(BuildContext context) {
return RaisedButton.icon(onPressed: logoutUser, icon: Icon(Icons.close), label: Text("Sign Out"));
}
final GoogleSignIn googleSignIn = GoogleSignIn();
Future<Null> logoutUser() async{
await FirebaseAuth.instance.signOut();
await googleSignIn.disconnect();
await googleSignIn.signOut();
Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) => MyApp()), (Route<dynamic> route ) => false);
}
}
class UserResult extends StatelessWidget
{
#override
Widget build(BuildContext context) {
}
}
The problem is you're not using the try catch block.
For example, you can do something like this:
Future signInAnon() async {
setState(() {
_isLoading = true;
});
FirebaseAuth auth = FirebaseAuth.instance;
try {
await auth.signInAnonymously();
} on FirebaseAuthException catch (e) {
setState(() {
_isLoading = false;
});
showSimpleNotification(
const Text(
'Sign In Error',
style: TextStyle(color: Colors.white),
textAlign: TextAlign.center,
),
contentPadding: const EdgeInsets.all(12),
background: Colors.red,
);
} catch (e) {
setState(() {
_isLoading = false;
});
}
}
Then, on listening to the user signing, you can do this:
class AppWrapper extends StatefulWidget {
const AppWrapper({Key? key}) : super(key: key);
#override
_AppWrapperState createState() => _AppWrapperState();
}
class _AppWrapperState extends State<AppWrapper> {
#override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, AsyncSnapshot<User?> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
return errorPage();
} else if (snapshot.hasData) {
return const HomePage();
} else {
return const SigningPage();
}
},
);
}
Unhandled Exception: type 'Future' is not a subtype of type 'QuerySnapshot' in flutter googlesignin using firebase.Got problem with this line: final QuerySnapshot result=FirebaseFirestore.instance.collection('users').where('id',isEqualTo: user.uid).get();
it is used for sign inwith google using firebase
import 'package:shared_preferences/shared_preferences.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'home.dart';
import 'package:flutter_auth_buttons/flutter_auth_buttons.dart';
import 'package:flutter_signin_button/flutter_signin_button.dart';
class Login extends StatefulWidget {
#override
_LoginState createState() => _LoginState();
}
class _LoginState extends State<Login> {
final FirebaseAuth firebaseAuth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = new GoogleSignIn();
SharedPreferences preferences;
bool loading = false;
bool isLogedIn = false;
#override
void initState() {
super.initState();
isSignedIn();
}
void isSignedIn() async {
setState(() {
loading = true;
});
preferences = await SharedPreferences.getInstance();
isLogedIn = await googleSignIn.isSignedIn();
if (isLogedIn) {
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => HomePage()));
}
setState(() {
loading = false;
});
}
Future<Null> handleSignIn() async{
preferences = await SharedPreferences.getInstance();
final GoogleSignInAccount googleUser = await googleSignIn.signIn();
final GoogleSignInAuthentication googleSignInAuthentication = await googleUser.authentication;
AuthCredential credential = GoogleAuthProvider.credential(idToken: googleSignInAuthentication.idToken, accessToken: googleSignInAuthentication.accessToken);
//final UserCredential userCredential = await firebaseAuth.signInWithCredential(credential);
//final User user = userCredential.user;
User user = (await firebaseAuth.signInWithCredential(credential)).user;```
if(user!=null)
{
final QuerySnapshot result=FirebaseFirestore.instance.collection('users').where('id',isEqualTo: user.uid).get();
List<DocumentSnapshot> documents= result.docs;
if(documents.length==0)
{
//insert user to collection
FirebaseFirestore.instance.collection('users').doc(user.uid).set({
"id":user.uid,
"username":user.displayName,
"photourl":user.photoURL});
await preferences.setString("id", user.uid);
await preferences.setString("username", user.displayName);
await preferences.setString("photourl", user.photoURL);
}
else{
// await preferences.setString("id",documents[0].data['id']);
//await preferences.setString("photourl",documents[0]['photourl']);
//await preferences.setString("username",documents[0]['username']);
await preferences.setString("id", documents[0].data()['id']);
await preferences.setString("username", documents[0].data()['username']);
await preferences.setString("photourl", documents[0].data()['photoUrl']);
}
Fluttertoast.showToast(msg: "Login Was successful");
setState(() {
loading=false;
});
Navigator.push(context, MaterialPageRoute(builder: (context)=>HomePage()));
}else{
Fluttertoast.showToast(msg: "Login Failed");
setState(() {
loading=false;
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children:<Widget> [
Center(
child: FlatButton(
color: Colors.red,
onPressed: (){handleSignIn();},child: Text("sigin",style: TextStyle(color: Colors.white),),
)
),
Visibility(
visible: loading ?? true,
child: Center(
child: Container(
alignment: Alignment.center,
color: Colors.white.withOpacity(0.8),
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.red),
),
)
)
)
],
),
);
}
}```
get() returns a Future<QuerySnapshot>, therefore you need to do the following:
final QuerySnapshot result= await FirebaseFirestore.instance.collection('users').where('id',isEqualTo: user.uid).get();
https://dart.dev/codelabs/async-await
I've built a simple login page that on clicking the button opens the menu to choose a google account and then navigates to the homepage of the app.
The button gets clicked but the login menu doesn't pop up. It throws an error saying :
E/flutter ( 4974): [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: Navigator operation requested with a context that does not include a Navigator. E/flutter ( 4974): The context used to push or pop routes from the Navigator must be that of a widget that is a descendant of a Navigator widget.
I tried adding a new context to the tree but then a different error came up:
E/flutter (22865): [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: NoSuchMethodError: The method 'findAncestorStateOfType' was called on null. E/flutter (22865): Receiver: null E/flutter (22865): Tried calling: findAncestorStateOfType()
What should I do?
Here's my code:
import 'package:flutter/material.dart';
import 'package:sorted/screens/sortedMain.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
class LoginMain extends StatefulWidget {
LoginMain({Key key}) : super(key: key);
#override
_LoginMainState createState() => _LoginMainState();
}
class _LoginMainState extends State<LoginMain> {
final GoogleSignIn _googleSignIn = GoogleSignIn();
final FirebaseAuth _auth = FirebaseAuth.instance;
FirebaseUser _user;
bool isUserSignedIn = false;
#override
void initState() {
super.initState();
checkIfUserIsSignedIn();
}
void checkIfUserIsSignedIn() async {
var userSignedIn = await _googleSignIn.isSignedIn();
setState(() {
isUserSignedIn = userSignedIn;
});
}
Future<FirebaseUser> _handleSignIn() async {
FirebaseUser user;
bool userSignedIn = await _googleSignIn.isSignedIn();
setState(() {
isUserSignedIn = userSignedIn;
});
if (isUserSignedIn) {
user = await _auth.currentUser();
} else {
final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
final GoogleSignInAuthentication googleAuth =
await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
user = (await _auth.signInWithCredential(credential)).user;
userSignedIn = await _googleSignIn.isSignedIn();
setState(() {
isUserSignedIn = userSignedIn;
});
}
_user = user;
return user;
}
void onGoogleSignIn(BuildContext context) async {
FirebaseUser user = await _handleSignIn().then((value) => null);
BuildContext context;
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SortedMain(_googleSignIn, user)),
);
setState(() {
isUserSignedIn == null ? true : false;
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text('Sorted.'),
backgroundColor: Color(0xff0A3D62),
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: <Color>[
const Color(0xFF5761B2),
const Color(0xFF1FC588),
])),
),
),
drawer: null,
body: Container(
padding: EdgeInsets.only(top: 30),
width: 360,
height: 600,
color: const Color(0xFF273748),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
width: 300,
height: 300,
padding: EdgeInsets.all(15),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(20.0),
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Colors.white, Colors.grey[400]]),
),
child: MaterialButton(
height: 50.0,
minWidth: 150.0,
color: Colors.green,
splashColor: Colors.teal,
textColor: Colors.white,
child: new Icon(Icons.arrow_forward),
onPressed: () {
BuildContext context;
onGoogleSignIn(context);
},
)),
],
)),
),
),
);
}
}
Try using the code below for setting up your firebase class
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
class AuthProvider {
final FirebaseAuth _auth = FirebaseAuth.instance;
User _userFromFirebaseUser(FirebaseUser user) {
return user != null ? User(uid: user.uid) : null;
}
Future<bool> loginWithGoogle() async {
try {
GoogleSignIn googleSignIn = GoogleSignIn();
GoogleSignInAccount account = await googleSignIn.signIn();
if (account == null) return false;
AuthResult res =
await _auth.signInWithCredential(GoogleAuthProvider.getCredential(
idToken: (await account.authentication).idToken,
accessToken: (await account.authentication).accessToken,
));
if (res.user == null) return false;
return true;
} catch (e) {
print("Error logging with google");
return false;
}
}
Future<void> logOut() async {
try {
await _auth.signOut();
} catch (e) {
print("error logging out");
}
}
}
class User {
final String uid;
User({ this.uid });
}
and try restricting your Navigator with an if statement so it can't navigate without the completion of the login process.
CustomButtom(
onpressed : () async {
bool res = await AuthProvider().loginWithGoogle();
if (res) {
Navigator.push(context,
MaterialPageRoute(builder: (context) => SortedMain()));
} else
print("Login failed");
},
),
When i try to sign in with my google account in the app i get this error in the console
And the app shut down , i used the sign in method in firebase- google
And this is the code that i used for the sign up page
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
class LoginScreen extends StatefulWidget {
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
LoginButton(), // <-- Built with StreamBuilder
UserProfile()
],
)));
}
}
class UserProfile extends StatefulWidget {
#override
UserProfileState createState() => UserProfileState();
}
class UserProfileState extends State<UserProfile> {
Map<String, dynamic> _profile;
bool _loading = false;
#override
initState() {
super.initState();
// Subscriptions are created here
authService.profile.listen((state) => setState(() => _profile = state));
authService.loading.listen((state) => setState(() => _loading = state));
}
#override
Widget build(BuildContext context) {
return Column(children: <Widget>[
Container(padding: EdgeInsets.all(20), child: Text(_profile.toString())),
Text(_loading.toString())
]);
}
}
class LoginButton extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: authService.user,
builder: (context, snapshot) {
if (snapshot.hasData) {
return MaterialButton(
onPressed: () => authService.signOut(),
color: Colors.red,
textColor: Colors.white,
child: Text('Signout'),
);
} else {
return MaterialButton(
onPressed: () => authService.testSignInWithGoogle(),
color: Colors.white,
textColor: Colors.black,
child: Text('Login with Google'),
);
}
});
}
}
and this for authentification
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:rxdart/rxdart.dart';
class AuthService {
// Dependencies
final GoogleSignIn _googleSignIn = GoogleSignIn();
final FirebaseAuth _auth = FirebaseAuth.instance;
final Firestore _db = Firestore.instance;
// Shared State for Widgets
Observable<FirebaseUser> user; // firebase user
Observable<Map<String, dynamic>> profile; // custom user data in Firestore
PublishSubject loading = PublishSubject();
// constructor
AuthService() {
user = Observable(_auth.onAuthStateChanged);
profile = user.switchMap((FirebaseUser u) {
if (u != null) {
return _db
.collection('users')
.document(u.uid)
.snapshots()
.map((snap) => snap.data);
} else {
return Observable.just({});
}
});
}
Future<String> testSignInWithGoogle() async {
final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
final GoogleSignInAuthentication googleAuth =
await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
final FirebaseUser user =
(await _auth.signInWithCredential(credential)).user;
assert(user.email != null);
assert(user.displayName != null);
assert(!user.isAnonymous);
assert(await user.getIdToken() != null);
final FirebaseUser currentUser = await _auth.currentUser();
assert(user.uid == currentUser.uid);
return 'signInWithGoogle succeeded: $user';
}
Future<String> signOut() async {
try {
await _auth.signOut();
return 'SignOut';
} catch (e) {
return e.toString();
}
}
}
// TODO refactor global to InheritedWidget
final AuthService authService = AuthService();
and this is what i have in pubspec.yml:
dependencies:
flutter:
sdk: flutter
firebase_core: ^0.4.5
firebase_analytics: ^5.0.15
cloud_firestore: ^0.13.6
firebase_auth: ^0.16.1
google_sign_in: ^4.5.1
rxdart: ^0.22.6
cupertino_icons: ^0.1.3
i am trying to implement the sign in button from firebase with google , but all the tutorials are old. I have an error at :onPressed: () => authService.googleSignIn()
Here is the code that i used for authentification:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:rxdart/rxdart.dart';
class AuthService {
// Dependencies
final GoogleSignIn _googleSignIn = GoogleSignIn();
final FirebaseAuth _auth = FirebaseAuth.instance;
final Firestore _db = Firestore.instance;
// Shared State for Widgets
Observable<FirebaseUser> user; // firebase user
Observable<Map<String, dynamic>> profile; // custom user data in Firestore
PublishSubject loading = PublishSubject();
// constructor
AuthService() {
user = Observable(_auth.onAuthStateChanged);
profile = user.switchMap((FirebaseUser u) {
if (u != null) {
return _db
.collection('users')
.document(u.uid)
.snapshots()
.map((snap) => snap.data);
} else {
return Observable.just({});
}
});
}
Future<String> _testSignInWithGoogle() async {
final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
final GoogleSignInAuthentication googleAuth =
await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
final FirebaseUser user =
(await _auth.signInWithCredential(credential)).user;
assert(user.email != null);
assert(user.displayName != null);
assert(!user.isAnonymous);
assert(await user.getIdToken() != null);
final FirebaseUser currentUser = await _auth.currentUser();
assert(user.uid == currentUser.uid);
return 'signInWithGoogle succeeded: $user';
}
Future<String> signOut() async {
try {
await _auth.signOut();
return 'SignOut';
} catch (e) {
return e.toString();
}
}
}
// TODO refactor global to InheritedWidget
final AuthService authService = AuthService();
and this is for the login page
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
class LoginScreen extends StatefulWidget {
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
LoginButton(), // <-- Built with StreamBuilder
UserProfile()
],
)));
}
}
class UserProfile extends StatefulWidget {
#override
UserProfileState createState() => UserProfileState();
}
class UserProfileState extends State<UserProfile> {
Map<String, dynamic> _profile;
bool _loading = false;
#override
initState() {
super.initState();
// Subscriptions are created here
authService.profile.listen((state) => setState(() => _profile = state));
authService.loading.listen((state) => setState(() => _loading = state));
}
#override
Widget build(BuildContext context) {
return Column(children: <Widget>[
Container(padding: EdgeInsets.all(20), child: Text(_profile.toString())),
Text(_loading.toString())
]);
}
}
class LoginButton extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: authService.user,
builder: (context, snapshot) {
if (snapshot.hasData) {
return MaterialButton(
onPressed: () => authService.signOut(),
color: Colors.red,
textColor: Colors.white,
child: Text('Signout'),
);
} else {
return MaterialButton(
onPressed: () => authService.googleSignIn(),
color: Colors.white,
textColor: Colors.black,
child: Text('Login with Google'),
);
}
});
}
}
I thing the AuthService.googleSignIn() in async method
so the cant assign to sync method
onPressed: () => authService.googleSignIn()
use like this
onPressed: () { authService.googleSignIn() }