Flutter error trying to connect with google account - firebase

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

Related

google sign in button isn't working how to resolve

I have added google sign in button to my login page. but when I CLICK IT its not working at all. I REFER this video for the implementation. how to resolve this. I'm struggling to find the error. appreciate your help on this. all the firebase parts are done according to the video instructions. there's no error to displaying. just button not working.
//google_sign_in.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
class GoogleSignInProvider extends ChangeNotifier{
final googleSignIn =GoogleSignIn();
GoogleSignInAccount? _user;
GoogleSignInAccount get user => _user!;
Future googleLogin()async{
final googleUser= await googleSignIn.signIn();
if (googleUser == null) return;
_user = googleUser;
final googleAuth =await googleUser.authentication;
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
await FirebaseAuth.instance.signInWithCredential(credential);
notifyListeners(); //to update UI
}
}
//main.dart
import 'dart:io';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:lala_live/provider/google_sign_in.dart';
import 'package:lala_live/screens/login.dart';
import 'package:lala_live/screens/splashscreen.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:provider/provider.dart';
const bool USE_EMULATOR = false;
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
if (USE_EMULATOR) {
_connectToFirebaseEmulator();
}
runApp(MyApp());
}
Future _connectToFirebaseEmulator() async {
final fireStorePort = "8080";
final authPort = 9099;
final localhost = Platform.isAndroid ? '10.0.2.2' : 'localhost';
FirebaseFirestore.instance.settings = Settings(
host: "$localhost:$fireStorePort",
sslEnabled: false,
persistenceEnabled: false,
);
await FirebaseAuth.instance.useAuthEmulator('http://$localhost:', authPort);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) => ChangeNotifierProvider(
create: (context)=> GoogleSignInProvider(),
child: MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(fontFamily: 'Quicksand'),
home: FutureBuilder(
future: Future.delayed(Duration(seconds: 3)),
builder: (ctx, timer) => timer.connectionState == ConnectionState.done
? Login() //Screen to navigate to once the splashScreen is done.
: SplashScreen()),
),
);
}
//login.dart
Center(
child: SocialButton(
logo: 'asset/images/googleicon.png',
height: widgetheight,
width: width / 4,
text: 'Google',
onPressed: () {
final provider = Provider.of<GoogleSignInProvider>(context,listen:false);
provider.googleLogin();
},
color: containergrey)),
],
),
Try this,
maybe u forgot to async await
onPressed: () async {
final provider =
Provider.of<GoogleSignInProvider>(context, listen: false);
await provider.googleLogin();
},
googleSignIn.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
class GoogleSignInProvider extends ChangeNotifier {
final googleSignIn = GoogleSignIn();
GoogleSignInAccount? _user;
GoogleSignInAccount get user => _user!;
Future googleLogin() async {
try {
final googleUser = await googleSignIn.signIn();
if (googleUser == null) return;
_user = googleUser;
final googleAuth = await googleUser.authentication;
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
await FirebaseAuth.instance.signInWithCredential(credential);
} catch (e) {}
notifyListeners();
}
Future logout() async {
await googleSignIn.disconnect();
FirebaseAuth.instance.signOut();
}
}
**SignInButton**
import 'package:flutter/material.dart';
class ButtonWidget extends StatelessWidget {
final String text;
final VoidCallback onClicked;
const ButtonWidget({
Key? key,
required this.text,
required this.onClicked,
}) : super(key: key);
#override
Widget build(BuildContext context) => ElevatedButton(
style: ElevatedButton.styleFrom(
shape: const StadiumBorder(),
onPrimary: Colors.white,
padding: EdgeInsets.symmetric(horizontal: 32, vertical: 12),
),
child: Text(text),
onPressed: onClicked,
);
}
Widget buildUpgradeButton() => ButtonWidget(
text: Click to SignIn,
onClicked: () {
final provider =
Provider.of<GoogleSignInProvider>(context, listen: false);
provider.googleLogin();
});

Flutter Google Sign in, Endless loading Icon when selecting an existing account

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();
}
},
);
}

flutter firebase [connect UserID to Profile collection]

I am learning flutter and I am stuck on a problem .
I created a little app which allows me to auth via Gmail on firebase.
As soon as I get logged in the email and a generated name will be added to "collection: users"
now I would like to add some more information about the user to the "collection: profilepage".
on my main.dart I ask: is user logged in, then
return(UserNameChooser).
In UserNameChooser I have 2 textfields which will be written into "collection: profilepage".
Now my Question: How can I get the UserID from the "collection: users" and add
the ID to the "collection: profilepage".
Or how do you manage profilepage auth connection?
I tried so many ways but couldn't get it done...
My Main.dart
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:signal/services/auth.dart';
// import 'package:signal/views/home.dart';
import 'package:signal/views/usernamechooser.dart';
import 'views/signin.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.lightBlue,
),
home: FutureBuilder(
future: AuthMethods().getCurrentUser(),
builder: (context, AsyncSnapshot<dynamic> snapshot) {
if(snapshot.hasData){
return UserNameChooser();
}
else{
return SignIn();
}
}
),
);
}
}
My auth.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:signal/helperfunctions/sharedpref_helper.dart';
import 'package:signal/services/database.dart';
import 'package:signal/views/home.dart';
class AuthMethods{
final FirebaseAuth auth = FirebaseAuth.instance;
getCurrentUser() async {
return await auth.currentUser;
}
signInWithGoogle(BuildContext context) async {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
final GoogleSignIn _googleSignIn = GoogleSignIn();
final GoogleSignInAccount googleSignInAccount =
await _googleSignIn.signIn();
final GoogleSignInAuthentication googleSignInAuthentication = await
googleSignInAccount.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
idToken: googleSignInAuthentication.idToken,
accessToken: googleSignInAuthentication.accessToken
);
UserCredential result =
await _firebaseAuth.signInWithCredential(credential);
User userDetails = result.user;
if(result != null){
SharedPreferenceHelper().saveUserEmail(userDetails.email);
SharedPreferenceHelper().saveUserId(userDetails.uid);
SharedPreferenceHelper()
.saveUserName(userDetails.email.replaceAll("#gmail.com", ""));
SharedPreferenceHelper().saveDisplayName(userDetails.displayName);
SharedPreferenceHelper().saveUserProfileUrl(userDetails.photoURL);
Map<String, dynamic> userInfoMap = {
"email": userDetails.email,
"username": userDetails.email.replaceAll("#gmail.com", ""),
"name": userDetails.displayName,
"imgUrl": userDetails.photoURL
};
DatabaseMethods()
.addUserInfoToDB(userDetails.uid, userInfoMap)
.then((value) {
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => Home()));
});
}
}
Future signOut() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.clear();
await auth.signOut();
}
}
My Database.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:signal/helperfunctions/sharedpref_helper.dart';
class DatabaseMethods{
Future addUserInfoToDB(String userId, Map<String, dynamic>userInfoMap)
async {
return FirebaseFirestore.instance
.collection("users")
.doc(userId)
.set(userInfoMap);
}
Future<Stream<QuerySnapshot>> getUserByUserName(String username) async{
return FirebaseFirestore.instance
.collection("users")
.where("username", isEqualTo: username)
.snapshots();
}
Future addMessage(String chatRoomId, String messageId, Map messageInfoMap) async {
return FirebaseFirestore.instance
.collection ("chatrooms")
.doc(chatRoomId)
.collection("chats")
.doc(messageId)
.set(messageInfoMap);
}
updateLastMessageSend(String chatRoomId, Map lastMessageInfoMap){
return FirebaseFirestore.instance
.collection("chatrooms")
.doc(chatRoomId)
.update(lastMessageInfoMap);
}
createChatRoom(String chatRoomId, Map chatRoomInfoMap) async{
final snapShot = await FirebaseFirestore.instance
.collection("chatrooms")
.doc(chatRoomId)
.get();
if(snapShot.exists){
//chatroom already exists
return true;
}else{
//chatroom does not exists
return FirebaseFirestore.instance
.collection("chatrooms")
.doc(chatRoomId)
.set(chatRoomInfoMap);
}
}
Future<Stream<QuerySnapshot>> getChatRoomMessages(chatRoomId) async {
return FirebaseFirestore.instance
.collection("chatrooms")
.doc(chatRoomId)
.collection("chats")
.orderBy("ts", descending: true)
.snapshots();
}
Future<Stream<QuerySnapshot>> getChatRooms() async {
String myUsername = await SharedPreferenceHelper().getUserName();
return FirebaseFirestore.instance
.collection("chatrooms")
.orderBy("lastMessageSendTs", descending: true)
.where("users",arrayContains: myUsername)
.snapshots();
}
Future<QuerySnapshot> getUserInfo(String username) async {
return await FirebaseFirestore.instance
.collection("users")
.where("username", isEqualTo: username)
.get();
}
}
my usernamechooser.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:signal/views/home.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:signal/helperfunctions/sharedpref_helper.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(
MaterialApp(home: UserNameChooser(),));
}
class UserNameChooser extends StatefulWidget{
#override
_UserNameChooserState createState() => _UserNameChooserState();
}
class _UserNameChooserState extends State<UserNameChooser> {
String userNameKey, getUserId;
TextEditingController chosenusername = new TextEditingController();
TextEditingController chosenage = new TextEditingController();
Future<String> getUserName() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString(userNameKey);
}
#override
Widget build(BuildContext context){
return Scaffold(
appBar: AppBar(title: Text("usernamechooser"),
),
body: Container(
padding: EdgeInsets.all(40.0),
child: Center(child: Column(
children: [
Container(
),
TextFormField(
controller: chosenusername,
decoration: InputDecoration(
hintText: "Username"
),
),
SizedBox(
height: 10.0,
),
TextFormField(
controller: chosenage,
decoration: InputDecoration(
hintText: "alter"
),
),
SizedBox(
height: 10.0,
),
TextButton(
onPressed: (){
Map <String,dynamic> data = {"choseusername": chosenusername.text,"chosenage": chosenage.text};
FirebaseFirestore.instance.collection("userprofile").add(data);
Navigator.push(context, MaterialPageRoute(builder: (context) => Home(),));
},
child: Text("Submit"),
),
]
),
)
)
);
}
}
and last but not least my shared_preferences.dart
import 'package:shared_preferences/shared_preferences.dart';
class SharedPreferenceHelper {
static String userIdKey = "USERKEY";
static String userNameKey = "USERNAMEKEY";
static String displayNameKey = "USERDISPLAYNAMEKEY";
static String userEmailKey = "USEREMAILKEY";
static String userProfilePicKey = "USERPROFILEPICKEY";
//save data
Future<bool> saveUserName(String getUserName) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.setString(userNameKey, getUserName);
}
Future<bool> saveUserEmail(String getUseremail) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.setString(userEmailKey, getUseremail);
}
Future<bool> saveUserId(String getUserId) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.setString(userIdKey, getUserId);
}
Future<bool> saveDisplayName(String getDisplayName) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.setString(displayNameKey, getDisplayName);
}
Future<bool> saveUserProfileUrl(String getUserProfile) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.setString(userProfilePicKey, getUserProfile);
}
// get data
Future<String> getUserName() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString(userNameKey);
}
Future<String> getUserEmail() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString(userEmailKey);
}
Future<String> getUserId() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString(userIdKey);
}
Future<String> getDisplayName() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString(displayNameKey);
}
Future<String> getUserProfileUrl() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString(userProfilePicKey);
}
}
Problem Solved ...
here how i did it :
I loaded the currentUser.uid into the var useruid ..
var useruid = FirebaseAuth.instance.currentUser.uid;
and sent this uid to the user db :)

Unhandled Exception: type 'Future<QuerySnapshot>' is not a subtype of type 'QuerySnapshot'

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

Sign in button firebase

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() }

Resources