I am able to sign-in and sign-out using Google. However, when I sign back in, I am not redirected to the page that I have specified. It get's stuck on the Login Page.
Here's the onPressed method for the login button:
onPressed: () async {
await Provider.of<Auth>(context, listen: false).signInWithGoogle();
},
The signInWithGoogle() method is in the Auth class below.
Here's the Auth class:
class Auth with ChangeNotifier {
String _token;
String _userId;
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();
bool get isAuth {
return token != null;
}
String get token {
if(_token != null)
return _token;
return null;
}
String get userId {
return _userId;
}
Future<void> signInWithGoogle() async {
final GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
final GoogleSignInAuthentication googleSignInAuthentication =
await googleSignInAccount.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleSignInAuthentication.accessToken,
idToken: googleSignInAuthentication.idToken,
);
final UserCredential authResult =
await _auth.signInWithCredential(credential);
final User user = authResult.user;
assert(!user.isAnonymous);
assert(await user.getIdToken() != null);
final User currentUser = _auth.currentUser;
assert(user.uid == currentUser.uid);
print('User is ' + user.displayName);
_token = await currentUser.getIdToken();
print('Token is ' + _token);
_userId = currentUser.uid;
notifyListeners();
}
Future<void> signOutGoogle() async {
await googleSignIn.signOut();
_token = null;
_userId = null;
notifyListeners();
print("User Sign Out");
}
Future<bool> tryAutoLogin() async {
//will implement later
return false;
}
}
Here's the main.dart
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(
create: (_) => Auth(),
),
ChangeNotifierProxyProvider<Auth,Categories>(
create:null,
update:(ctx,auth, previousCategories) => Categories(auth.token, auth.userId)),
],
//The consumer ensures that the material app gets built whenever Auth object changes
child: Consumer<Auth>(builder: (ctx, auth, _) =>
MaterialApp(
title: 'MyShop',
theme: ThemeData(
textTheme: Theme.of(context).textTheme.apply(
bodyColor: Colors.black,
displayColor: Colors.black,
),
primaryColor: Colors.orange,
accentColor: Colors.deepOrange,
fontFamily: 'Lato',
),
home: auth.isAuth ? CategoriesScreen()
: FutureBuilder(
future: auth.tryAutoLogin(),
builder: (ctx, authResultSnapshot) =>
authResultSnapshot.connectionState ==
ConnectionState.waiting
? SplashScreen()
: LoginPage(),
),
routes: {
CategoriesScreen.routeName: (ctx) => CategoriesScreen(),
LoginPage.routeName: (ctx) => LoginPage()
}
),
)
);
}
}
Here's the logout button:
ListTile(
leading: Icon(Icons.exit_to_app),
title: Text('Logout'),
onTap: () {
Provider.of<Auth>(context, listen:false).signOutGoogle();
Navigator.of(context).pushReplacementNamed(LoginPage.routeName);
},
),
When I sign-in for the first time, I get redirected to the CategoriesScreen() page. However, when log out and log back in, I do not get redirected.
Related
I have been able to get Firebase Authentication to work for Google sign in, Anonymous sign in and from Email and Password sign in, including sending a verification email during email and password sign in thanks to help on stackoverflow. Everything works as intended. Now for my next step I am trying to create a user collection in Firestore using the uid created by Firebase Authentication. I am confident my code is written correctly because I have tested it with (unsecure) Security Rules and the process worked exactly as desired.
I have reviewed the Firebase documentation several times but I cannot figure out what is wrong with my Security Rules code. How can I fix my Security rules to allow a new user to create a Screen name that will be added to the user collection in Firestore? Thanks in advance for the help.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{uid}/jobs/{document=**} {
allow read, write: if request.auth.uid == uid;
}
match /users/{uid}/{document=**} {
allow read, write: if request.auth.uid == uid;
}
}
}
class HomePage extends StatefulWidget {
const HomePage({
Key? key,
}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
void initState() {
super.initState();
createUserInFirestore();
}
Future<void> createUserInFirestore() async {
final GoogleSignIn googleSignIn = GoogleSignIn();
final GoogleSignInAccount? user = googleSignIn.currentUser;
final usersRef = FirebaseFirestore.instance.collection('users');
final DocumentSnapshot doc = await usersRef.doc(user?.id).get();
if (!doc.exists) {
final userName = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const CreateAccountPage(),
),
);
usersRef.doc(user?.id).set({
'id': user?.id,
'userName': userName,
'photoUrl': user?.photoUrl,
'email': user?.email,
'displayName': user?.displayName,
'bio': '',
'timestamp': documentIdFromCurrentDate(),
});
doc = await usersRef.doc(user?.id).get();
}
}
#override
Widget build(BuildContext context) {
return AdaptiveLayoutScaffold(
drawer: const SideSheet(
userImage: FakeUserAvatars.stacy,
userName: 'Stacy James',
),
landscapeBodyWidget: Container(),
portraitBodyWidget: Container(),
);
}
}
class CreateAccountPage extends StatefulWidget {
const CreateAccountPage({
Key? key,
}) : super(key: key);
#override
_CreateAccountPageState createState() => _CreateAccountPageState();
}
class _CreateAccountPageState extends State<CreateAccountPage> {
final _formKey = GlobalKey<FormState>();
late String userName;
void submit() {
_formKey.currentState?.save();
Navigator.pop(context, userName);
}
#override
Widget build(BuildContext context) {
return AdaptiveLayoutScaffold(
appBar: const Header(
automaticallyImplyLeading: false,
pageName: 'User Name',
),
landscapeBodyWidget: Container(),
portraitBodyWidget: ListView(
children: [
Column(
children: [
const Padding(
padding: EdgeInsets.only(top: 16.0),
child: Center(
child: Text('Create a User Name'),
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: TextFormField(
autovalidateMode: AutovalidateMode.always,
decoration: InputDecoration(
hintText: 'Must be between 3 and 20 characters',
labelText: 'User Name',
prefixIcon: Icon(
Icons.person,
color: Theme.of(context).iconTheme.color,
),
),
keyboardType: TextInputType.text,
onSaved: (val) => userName = val as String,
),
),
),
PlatformElevatedButton(
onPressed: submit,
buttonText: 'Create User Name',
),
],
),
],
),
);
}
}
After reading what has been suggested and a few other things I used the Firestore Rules Playground to fix my code and then updated my Auth class to include a new method called createUserInFirestore() to handle the creation of a new user in Firestore using the uid after the user is created by Firebase Authentication.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{uid}/{document=**} {
allow read, create, update, delete: if request.auth.uid == uid;
}
}
}
abstract class AuthBase {
User? get currentUser;
Stream<User?> authStateChanges();
Future<User?> signInWithGoogle();
Future<User?> createUserWithEmailAndPassword(
String email,
String password,
);
Future<void> checkEmailVerified(BuildContext context, Timer timer);
Future<User?> signInWithEmailAndPassword(String email, String password);
Future<User?> signInAnonymously();
Future<void> resetPassword(BuildContext context, String email);
Future<void> confirmSignOut(BuildContext context);
Future<void> signOut();
}
class Auth implements AuthBase {
final _firebaseAuth = FirebaseAuth.instance;
#override
User? get currentUser => _firebaseAuth.currentUser;
#override
Stream<User?> authStateChanges() => _firebaseAuth.authStateChanges();
void _createNewUserInFirestore() {
final User? user = currentUser;
final CollectionReference<Map<String, dynamic>> usersRef =
FirebaseFirestore.instance.collection('users');
usersRef.doc(user?.uid).set({
'id': user?.uid,
'screenName': '',
'displayName': user?.displayName,
'photoUrl': user?.photoURL,
'bio': '',
'darkMode': false,
'timestamp': documentIdFromCurrentDate(),
});
}
#override
Future<User?> signInWithGoogle() async {
final GoogleSignIn googleSignIn = GoogleSignIn();
final GoogleSignInAccount? googleUser = await googleSignIn.signIn();
if (googleUser != null) {
final googleAuth = await googleUser.authentication;
if (googleAuth.idToken != null) {
final UserCredential userCredential =
await _firebaseAuth.signInWithCredential(
GoogleAuthProvider.credential(
idToken: googleAuth.idToken,
accessToken: googleAuth.accessToken,
),
);
_createNewUserInFirestore();
return userCredential.user;
} else {
throw FirebaseAuthException(
code: FirebaseExceptionString.missingGoogleIDTokenCode,
message: FirebaseExceptionString.missingGoogleIDTokenMessage,
);
}
} else {
throw FirebaseAuthException(
code: FirebaseExceptionString.abortedByUserCode,
message: FirebaseExceptionString.canceledByUserMessage,
);
}
}
#override
Future<User?> createUserWithEmailAndPassword(
String email,
String password,
) async {
final UserCredential userCredential =
await _firebaseAuth.createUserWithEmailAndPassword(
email: email,
password: password,
);
_createNewUserInFirestore();
return userCredential.user;
}
#override
Future<void> checkEmailVerified(BuildContext context, Timer timer) async {
final User? user = currentUser;
await user?.reload();
final User? signedInUser = user;
if (signedInUser != null && signedInUser.emailVerified) {
timer.cancel();
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => const HomePage(),
),
);
}
}
#override
Future<User?> signInWithEmailAndPassword(
String email,
String password,
) async {
final UserCredential userCredential =
await _firebaseAuth.signInWithCredential(
EmailAuthProvider.credential(
email: email,
password: password,
),
);
return userCredential.user;
}
#override
Future<void> resetPassword(
BuildContext context,
String email,
) async {
try {
await _firebaseAuth.sendPasswordResetEmail(email: email);
Navigator.of(context).pop();
} catch (e) {
print(
e.toString(),
);
}
}
#override
Future<User?> signInAnonymously() async {
final UserCredential userCredential =
await _firebaseAuth.signInAnonymously();
return userCredential.user;
}
Future<void> _signOut(BuildContext context) async {
try {
final AuthBase auth = Provider.of<AuthBase>(
context,
listen: false,
);
await auth.signOut();
Navigator.pushAndRemoveUntil<dynamic>(
context,
MaterialPageRoute<dynamic>(
builder: (BuildContext context) => const LandingPage(),
),
(route) => false,
);
} catch (e) {
print(
e.toString(),
);
}
}
#override
Future<void> confirmSignOut(BuildContext context) async {
final bool? didRequestSignOut = await showAlertDialog(
context,
cancelActionText: DialogString.cancel,
content: DialogString.signOutAccount,
defaultActionText: DialogString.signOut,
title: DialogString.signOut,
);
if (didRequestSignOut == true) {
_signOut(context);
}
}
#override
Future<void> signOut() async {
final GoogleSignIn googleSignIn = GoogleSignIn();
await googleSignIn.signOut();
await _firebaseAuth.signOut();
}
}
I am flutter-newbie and I have one problem: I want to add Google authentication to my flutter app with firebase. This is my code for login screen:
import 'package:PixiCall/resources/firebase_repository.dart';
import 'package:PixiCall/screens/home_screen.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class LoginScreen extends StatefulWidget {
#override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
FirebaseRepository _repository = FirebaseRepository();
#override
Widget build(BuildContext context) {
return Scaffold(
body: loginButton(),
);
}
Widget loginButton() {
return FlatButton(
padding: EdgeInsets.all(35),
child: Text(
'Login',
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.w900,
letterSpacing: 1.2,
),
),
onPressed: () => performLogin,
);
}
void performLogin() {
_repository.signIn().then((User user) {
if (user != null) {
authenticateUser(user);
} else {
print('There was an error');
}
});
}
void authenticateUser(User user, BuildContext context) {
_repository.authenticateUser(user).then((isNewUser) {
if (isNewUser) {
_repository.addDataToDb(user).then((value) {
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) {
return HomeScreen();
}));
});
} else {
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) {
return HomeScreen();
}));
}
});
}
}
I have this error here:
lib/screens/login_screen.dart:39:25: Error: Too few positional arguments: 2 required, 1 given.
authenticateUser(user);
What is the other parameter which I have to add?
Also I think that I have one more mistake in other file. This is the code from other file:
import 'package:PixiCall/models/user.dart';
import 'package:PixiCall/utils/utilities.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
class FirebaseMethods {
final FirebaseAuth _auth = FirebaseAuth.instance;
GoogleSignIn _googleSignIn = GoogleSignIn();
static final FirebaseFirestore firestore = FirebaseFirestore.instance;
//user class
User1 user = User1();
Future<User> getCurrentUser() async {
User currentUser;
currentUser = await _auth.currentUser;
return currentUser;
}
Future<User> signIn() async {
GoogleSignInAccount _signInAccount = await _googleSignIn.signIn();
GoogleSignInAuthentication _signInAuthentication =
await _signInAccount.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: _signInAuthentication.accessToken,
idToken: _signInAuthentication.idToken,
);
User user = await _auth.signInWithCredential(credential);
return user;
}
Future<bool> authenicateUser(User user) async {
QuerySnapshot result = await firestore
.collection('users')
.where('email', isEqualTo: user.email)
.get();
final List<DocumentSnapshot> docs = result.docs;
//if user is registered then length of list > 0 or else less than 0
return docs.length == 0 ? true : false;
}
Future<void> addDataToDb(User currentUser) async {
String username = Utils.getUsername(currentUser.email);
user = User1(
uid: currentUser.uid,
email: currentUser.email,
name: currentUser.displayName,
profilePhoto: currentUser.photoURL,
username: username);
firestore.collection('users').doc(currentUser.uid).set(user.toMap(user));
}
}
This is the mistake in console:
lib/resources/firebase_methods.dart:32:17: Error: A value of type 'UserCredential' can't be assigned to a variable of type 'User'.
Sorry if I confused you, as I said, I am newbie. If you want any other informations please ask here.
For the first mistake , you defined a function void authenticateUser(User user, BuildContext context) so when you use it, it expects 2 arguments a User type object and a BuildContext object
Then you are calling this function in
void performLogin() {
_repository.signIn().then((User user) {
if (user != null) {
authenticateUser(user);
} else {
print('There was an error');
}
});
}
You are passing only the User object, missing the BuildContext
For GoogleSingIn this was my solution:
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn _googleSignIn = GoogleSignIn();
//create user object based on FB json
User _userFromFirebaseUser(FirebaseUser user) {
return user != null
? User(uid: user.uid, emailVerified: user.isEmailVerified)
: null;
}
//auth change user stream
Stream<User> get user {
return _auth.onAuthStateChanged.map(_userFromFirebaseUser);
}
Future<User> singInUsingGoogle() async {
int age;
String email;
String name;
String lastname;
final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
idToken: googleAuth.idToken, accessToken: googleAuth.accessToken);
final result = await _auth.signInWithCredential(credential);
FirebaseUser user = result.user;
print(result.user.providerData);
await DatabaseService(uid: user.uid).createUserData(
//user info
)
I tried to add splash screen to add splash screen to my app but it gets stuck at splash screen itsalf and does not move to next screens
I have added the code here:-
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
getUserInfo();
}
Future getUserInfo() async {
await getUser();
setState(() {});
print(uid);
navigateUser();
}
navigateUser()
{
if(uid!=null && authSignedIn != false)
{
Timer(Duration(seconds: 2),
()=>Navigator.pushReplacementNamed(context, "/toprofilepage")
);
}
else{
Timer(Duration(seconds: 2),
()=>Navigator.pushReplacementNamed(context, "/tologinpage")
);
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Login',
initial route:'/',
routes: {
'/toprofilepage':(context)=>FirstScreen(),
'/tologinpage':(context)=>LoginPage(),
},
home: Scaffold(
body: Center(
child: Text("Saraswat",style: TextStyle(fontSize: 40,fontWeight: FontWeight.bold,fontStyle: FontStyle.italic),),
),
)
);
}
}
I am getting this following message in console also:-
E/flutter ( 5947): [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: Navigator operation requested with a context that does not include a Navigator.
Code for sign in:-
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();
bool authSignedIn;
String uid;
String name;
String imageUrl;
Future getUser() async {
// Initialize Firebase
await Firebase.initializeApp();
SharedPreferences prefs = await SharedPreferences.getInstance();
bool authSignedIn = prefs.getBool('auth') ?? false;
final User user = _auth.currentUser;
if (authSignedIn == true) {
if (user != null) {
uid = user.uid;
name = user.displayName;
imageUrl = user.photoURL;
}
}
}
Future<String> signInWithGoogle() async {
// Initialize Firebase
await Firebase.initializeApp();
final GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
final GoogleSignInAuthentication googleSignInAuthentication = await googleSignInAccount.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleSignInAuthentication.accessToken,
idToken: googleSignInAuthentication.idToken,
);
final UserCredential userCredential = await _auth.signInWithCredential(credential);
final User user = userCredential.user;
if (user != null) {
// Checking if email and name is null
assert(user.uid != null);
assert(user.displayName != null);
assert(user.photoURL != null);
uid = user.uid;
name = user.displayName;
imageUrl = user.photoURL;
assert(!user.isAnonymous);
assert(await user.getIdToken() != null);
final User currentUser = _auth.currentUser;
assert(user.uid == currentUser.uid);
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setBool('auth', true);
return 'Google sign in successful, User UID: ${user.uid}';
}
return null;
}
void signOutGoogle() async {
await googleSignIn.signOut();
await _auth.signOut();
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setBool('auth', false);
uid = null;
name = null;
imageUrl = null;
print("User signed out of Google account");
}
I tried a lot of things but did not get any solution pls help!.Should I place the navigator function anywhere else or is there some other error pls help!.
Try doing the flow conditions in initialRoute only
Since the firebase has updated the way we check the user is logged in or not. Its not a async task so you can use directly in the MyApp class.
initialRoute: FirebaseAuth.instance.currentUser != null
? HomeScreen.route_name
: AuthScreen.route_name
Or you can use the listener for auth change
FirebaseAuth.instance.onAuthStateChanged.listen((firebaseUser) {
// do whatever you want based on the firebaseUser state
});
so when the auth is changed it will re-direct it to the page you want to, like this
home: StreamBuilder(
stream: FirebaseAuth.instance.onAuthStateChanged,
builder: (streamContext, userSnapshot) {
if (userSnapshot.connectionState == ConnectionState.waiting)
return SplashScreen();
if (userSnapshot.hasData) {
return HomeScreen();
}
return AuthScreen();
},
),
For user logged in
Future<String> signInWithGoogle() async {
final GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
final GoogleSignInAuthentication googleSignInAuthentication =
await googleSignInAccount.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleSignInAuthentication.accessToken,
idToken: googleSignInAuthentication.idToken,
);
final AuthResult authResult = await _auth.signInWithCredential(credential);
final FirebaseUser user = authResult.user;
assert(!user.isAnonymous);
assert(await user.getIdToken() != null);
final FirebaseUser currentUser = await _auth.currentUser();
assert(user.uid == currentUser.uid);
if(authResult.additionalUserInfo.isNewUser == true){
InsertNewUserDetails(user.displayName,user.email,user.photoUrl,user.phoneNumber);
}
if(authResult.user != null){
email = user.email;
name = user.displayName;
imageUrl =user.photoUrl;
globalInstance.isLoggedIn = true;
print(globalInstance.isLoggedIn);
}
return 'signInWithGoogle succeeded: $user';
}
This first time sign in Loginpage checking for is logged account
class MyApp extends StatelessWidget {
#override
String strinbggg;
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.teal,
body: StreamBuilder<FirebaseUser>(
stream: FirebaseAuth.instance.onAuthStateChanged,
builder: (BuildContext context, snapshot) {
if (snapshot.hasData && (!snapshot.data.isAnonymous)) {
// return Text('${snapshot.hasData}');
return Homepage();
} else {
// return SafeArea(
// maintainBottomViewPadding: true,
// child: Text('aasdasdfasfdh : ${snapshot.data.email}',style: TextStyle(color: Colors.black54),));
return LoginPage();
}
},
),
),
);
}
}
When first time login with google its working. When i was close application and start again it will redirecting to the homepage fine but user profile details like displayName , email are returning null value
signInwithgoogle() is use for the first time login that store the user details in firestore and user details set from here
MyApp is starting point of application that will check is user is already logged in
I would suggest, you check the user is already signed in or not using the method
bool isSignedIn = await _googleSignIn.isSignedIn();
and if the user is signed in, then get the credentials using
user = await _auth.currentUser();
when you start the app. In case you are not logged in, show login page. Any example would be something like below
final auth = FirebaseAuth.instance;
class MyApp extends StatelessWidget {
#override
String strinbggg;
Widget build(BuildContext context) {
return MaterialApp(
home: (_isSignedIn() == true ? new Homepage() : new LoginPage()));
}
bool _isSignedIn() async {
bool isSignedIn = await _googleSignIn.isSignedIn();
if(isSignedIn){
GoogleSignInAccount user = await auth.currentUser;
//You can store this in your state.
}
return !(user == null && auth.currentUser == null);
}
}
Please note this is a in editor composed code, not tested, you will have to make adjustments.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
when I select the account I want to login with, it fails. I'm confuse to whats the issue, I followed the tutorial step by step. except for this code:
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleSignInAuthentication.accessToken,
idToken: googleSignInAuthentication.idToken,
);
FirebaseUser firebaseUser = await firebaseAuth.signInWithCredential(credential);
because signInWithGoogle wasn't working.
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'home_everything.dart';
class login extends StatefulWidget {
#override
_loginState createState() => _loginState();
}
class _loginState extends State<login> {
final GoogleSignIn googleSignIn = new GoogleSignIn();
final FirebaseAuth firebaseAuth = FirebaseAuth.instance;
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) => SongHome()));
}
setState(() {
loading = false;
});
}
Future handleSignIn() async{
preferences = await SharedPreferences.getInstance();
setState(() {
loading = true;
});
GoogleSignInAccount googleUser = await googleSignIn.signIn();
GoogleSignInAuthentication googleSignInAuthentication = await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleSignInAuthentication.accessToken,
idToken: googleSignInAuthentication.idToken,
);
FirebaseUser firebaseUser = await firebaseAuth.signInWithCredential(credential);
if(firebaseUser != null) {
final QuerySnapshot result = await Firestore.instance.collection("users")
.where("id", isEqualTo: firebaseUser.uid)
.getDocuments();
final List<DocumentSnapshot> documents = result.documents;
if (documents.length == 0) {
// insert the user into out collection
Firestore.instance.collection("users")
.document(firebaseUser.uid)
.setData({
"id": firebaseUser.uid,
"username": firebaseUser.displayName,
"profilePicture": firebaseUser.photoUrl
});
await preferences.setString("id", firebaseUser.uid);
await preferences.setString("username", firebaseUser.displayName);
await preferences.setString("photoUrl", firebaseUser.displayName);
} else {
await preferences.setString("id", documents[0]['id']);
await preferences.setString("username", documents[0]['username']);
await preferences.setString("photoUrl", documents[0]['photoUrl']);
}
Fluttertoast.showToast(msg: "Logged In");
setState(() {
loading = false;
});
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => SongHome()));
}else{
Fluttertoast.showToast(msg: "Login failed : (");
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
centerTitle: true,
title: new Text("Login", style: TextStyle(color: Colors.redAccent),),
elevation: 0.5,
),
body: Stack(
children: <Widget>[
Center(
child: FlatButton(onPressed: (){
handleSignIn();
},
child: Text("Sign In"),),
),
Visibility(
visible: loading ?? true,
child: Container(
color: Colors.white.withOpacity(0.7),
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation(Colors.red),
),
),
)
],
),
);
}
}
Here is the error log:
E/flutter (15402): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: PlatformException(sign_in_failed, com.google.android.gms.common.api.ApiException: 10: , null)
try this,
FirebaseUser firebaseUser = await firebaseAuth.signInWithCredential(credential).user;