Can't sign in using google in Flutter - flutter

I am able to Google Sign in using web version of my flutter app but can't Google sign in from android app.
This is the error I'm getting:
GraphicExtModuleLoader::CreateGraphicExtInstance false
D/Surface (29460): Surface::connect(this=0x753ab3e000,api=1)
D/Surface (29460): Surface::setBufferCount(this=0x753ab3e000,bufferCount=3)
D/Surface (29460): Surface::allocateBuffers(this=0x753ab3e000)
V/PhoneWindow(29460): DecorView setVisiblity: visibility = 0, Parent = android.view.ViewRootImpl#9837577, this = DecorView#bcd75e4[MainActivity]
V/PhoneWindow(29460): DecorView setVisiblity: visibility = 4, Parent = android.view.ViewRootImpl#9de9d56, this = DecorView#63bb4f5[SignInHubActivity]
D/Surface (29460): Surface::disconnect(this=0x753ab3e000,api=1)
D/View (29460): [Warning] assignParent to null: this = DecorView#63bb4f5[SignInHubActivity]
E/flutter (29460): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: PlatformException(sign_in_failed, com.google.android.gms.common.api.ApiException: 10: , null, null)
Refereing to this Flutter and google_sign_in plugin: PlatformException(sign_in_failed, com.google.android.gms.common.api.ApiException: 10: , null) answer on StackOverflow, I couldn't understand what this answer is trying to say...
However, I do have provided my SHA1 key on firebase. Re-downloaded and replaced the google-services.json in my flutter app, but still can't sign in on Android.
This is my GoogleSignIn code:
onPressed: () async {
await Firebase.initializeApp();
final FirebaseAuth _firebaseAuth =
FirebaseAuth.instance;
final GoogleSignIn _googleSignIn =
GoogleSignIn();
Future<User> _signIn(BuildContext context) async {
debugPrint("1");
final GoogleSignInAccount googleUser =
await _googleSignIn.signIn();
debugPrint("2");
final GoogleSignInAuthentication googleAuth =
await googleUser.authentication;
debugPrint("a");
final AuthCredential credential =
GoogleAuthProvider.credential(
idToken: googleAuth.idToken,
accessToken: googleAuth.accessToken);
User userDetails = (await _firebaseAuth
.signInWithCredential(credential))
.user;
ProviderDetails providerInfo =
ProviderDetails(userDetails.uid);
List<ProviderDetails> providerData =
<ProviderDetails>[];
providerData.add(providerInfo);
UserDetails details = UserDetails(
userDetails.uid,
userDetails.displayName,
userDetails.email,
userDetails.photoURL,
providerData);
if (details.userName.toString() != '') {
debugPrint("Email ${details.userEmail}");
globals.isLoggedIn = true;
SharedPref prefs = SharedPref();
String photoUrl = details.photoUrl.toString();
prefs.save("photoUrl", photoUrl);
prefs.save("username",
details.userName.toString());
prefs.save(
"email", details.userEmail.toString());
if (mounted) {
setState(() {
inProgress = false;
});
}
} else {
globals.isLoggedIn = false;
debugPrint(
"Check your internet Connection");
}
}
if (mounted) {
setState(() {
inProgress = true;
});
}
await _signIn(context);
debugPrint("LoggedIn");
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Dashboard()),
);
}

Actually I needed to add this line into my app level build.gradle file dependencies section.
implementation 'com.google.android.gms:play-services-auth:19.0.0'
As well needed to link my project from this link too.
https://developers.google.com/identity/sign-in/android/start-integrating#configure_a_project
Might it help someone in future!

Problem is When you registered your app on google console and created clientId, you choose web platform, now you have to create another clientId with Android Platform. You can use same sha1 key.

Related

firebase not creating data when user signs for first time

when new user signIn, In firebase Authentication tab it is showing users details.
but not adding the function to firestore.
google signIn code:
Future<UserCredential> signInWithGoogle() async {
showDialog(
context: context,
builder: (context) {
return const Center(child: CircularProgressIndicator());
});
final _auth = FirebaseAuth.instance;
// Trigger the authentication flow
final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();
// Obtain the auth details from the request
final GoogleSignInAuthentication? googleAuth =
await googleUser?.authentication;
// Create a new credential
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth?.accessToken,
idToken: googleAuth?.idToken,
);
final UserCredential authResult =
await _auth.signInWithCredential(credential);
final user = authResult.user;
if (authResult.additionalUserInfo!.isNewUser) {
if (user != null) {
await DbServices().addNewUser(FirebaseAuth.instance.currentUser!.uid);
}
}
removeLoading();
// Once signed in, return the UserCredential
return await FirebaseAuth.instance.signInWithCredential(credential);
}
removeLoading() {
return Navigator.of(context).pop();
}
}
**this is addNewUser function:**
Future addNewUser(useruid) async {
int heartid = await updateHeartId();
print('updated Heart Id $heartid....................');
await usersCollection.doc(useruid).set({
'user name': FirebaseAuth.instance.currentUser!.displayName,
'uid': useruid,
'heartId': heartid,
'total hearts': 0,
'ringed': false,
'Timestamp': FieldValue.serverTimestamp(),
'profile pic': '',
'todayRinged': false,
'ringedDay': DateTime.now().day,
});
}
when I looked into it, firebase isn't adding the function addNewUser in firestore.
I don't understand what's happening here.
when I signIn for first time the app crashes saying :
> StateError(Bad state: cannot get a field on a DocumentSnapshotPlatform
> which does not exist)
why is the addNewUser function not adding to firestore?

Flutter Google Sign In error after canceling Choose an account pop-up

After clicking sign in, choose an account pop comes up but if the user pressed back or outside of the pop-up it throws an error.
Error -
Sign in class -
class GoogleSignInProvider extends ChangeNotifier {
final googleSignIn = GoogleSignIn();
GoogleSignInAccount? _user;
GoogleSignInAccount get user => _user!;
Future googleLogin() async {
await googleSignIn.signOut();
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();
}
}
Sign out button -
TextButton(
onPressed: () async {
final googleCurrentUser = GoogleSignIn().currentUser;
if (googleCurrentUser != null) {
await GoogleSignIn().disconnect();
}
FirebaseAuth.instance.signOut();
Navigator.pop(context);
},
child: const Text(
'Yes',
style: TextStyle(color: primaryColor),
))
Instead of if (googleUser == null) return; try using if (googleUser == null) return null;.
Here is my sign in method;
Future<UserCredential?> signInWithGoogle() async {
final _googleSignIn = GoogleSignIn();
await _googleSignIn.disconnect().catchError((e, stack) {
print(e);
});
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
// handling the exception when cancel sign in
if (googleUser == null) return null;
// Obtain the auth details from the request
final GoogleSignInAuthentication? googleAuth =
await googleUser.authentication;
// Create a new credential
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth?.accessToken,
idToken: googleAuth?.idToken,
);
return await FirebaseAuth.instance.signInWithCredential(credential);
}
The sign out method;
Future signOut() async {
var result = await FirebaseAuth.instance.signOut();
return result;
}
This only happens in debugging, in release this won't be an issue.

Flutter - Google Sign In uses previously signed in account (user) even after signing out and signing in with another account

When I hit "Sign in with Google", it does let me choose the account although somehow, the previous user gets loaded.
class GoogleSignInProvider extends ChangeNotifier {
GoogleSignIn? _googleSignIn;
GoogleSignInAccount? _user;
GoogleSignInAccount get user => _user!;
bool _isGoogleLogin = false;
final _auth = FirebaseAuth.instance;
Future signInWithGoogle(context) async {
try {
_googleSignIn = GoogleSignIn();
final googleUser = await _googleSignIn!.signIn();
if (googleUser == null) {
return;
}
_user = googleUser;
final googleAuth = await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
var authCredential = await _auth.signInWithCredential(credential);
_isGoogleLogin = true;
if (authCredential.user != null) {
final snapshot = await FirebaseFirestore.instance
.collection('users')
.doc(authCredential.user!.uid)
.get();
if (!snapshot.exists) {
var userId = authCredential.user!.uid;
FirebaseFirestore.instance.collection('users').doc(userId).set({
"email": googleUser.email,
"workoutsCount": 0,
"lastWorkoutDate": null
});
}
}
notifyListeners();
Navigator.of(context).pushNamed('/dashboard');
} on FirebaseAuthException catch (e) {
showSnackBar(context, e);
} catch (e) {
print('ERROR = ');
print(e);
}
}
Future<void> signOut(context) async {
try {
if (_isGoogleLogin) {
final googleCurrentUser =
GoogleSignIn().currentUser ?? await GoogleSignIn().signIn();
if (googleCurrentUser != null) {
await GoogleSignIn().disconnect().catchError((e, stack) {
FirebaseCrashlytics.instance.recordError(e, stack);
});
}
}
await _auth.signOut();
} catch (e) {
showSnackBar(context, e);
} finally {
_isGoogleLogin = false;
Navigator.of(context).pushNamedAndRemoveUntil(
'/register_login', (Route<dynamic> route) => false);
}
}
Is there something wrong with this code??
Can you try to disconnect the account before signing out:
GoogleSignIn _googleSignIn = GoogleSignIn();
await _googleSignIn.disconnect();
await FirebaseAuth.instance.signOut();
You are using firebase auth then please use thsi for signout user :
How to Signout a user in Flutter with Firebase authentication
Remove if (_isGoogleLogin) from your signOut function. googleCurrentUser will check the consitionn and responses based on the result.
First Create a Global variable
FirebaseAuth firebaseAuth = FirebaseAuth.instance;
GoogleSignIn googleSignIn = GoogleSignIn();
Make sure you are using the above variable for login and logout
final googleCurrentUser = firebaseAuth.currentUser;
if (googleCurrentUser != null) {
googleSignIn.signOut();
await firebaseAuth.signOut();
}
User above code for signout user

Request had insufficient authentication scopes - Error getting birthday from google sign-in using firebase in flutter

I am using Flutter and I would like to get the user's birthday from google sign-in. However, I can only get the user's email, displayName but not the birthdate. I tried to add scope for getting the birthday from people API but I am getting an error. I can successfully get the user's name and email but I cannot get the birthday. Please help..
Here is the error.
W/.pumpit.pump_i(32752):Accessing hidden method Lsun/misc/Unsafe; >compareAndSwapObject(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z (greylist, linking, allowed)
I/flutter (32752): loading birthday
I/flutter (32752): loading completed
I/flutter (32752): api error
I/flutter (32752): {
I/flutter (32752): "error": {
I/flutter (32752): "code": 403,
I/flutter (32752): "message": "Request had insufficient authentication scopes.",
I/flutter (32752): "status": "PERMISSION_DENIED"
I/flutter (32752): }
I/flutter (32752): }
Here is my code:
var googleIdToken;
FirebaseUser user;
Future<FirebaseUser> signInWithGoogle() async {
final GoogleSignIn _googleSignIn = GoogleSignIn(
scopes: ['https://www.googleapis.com/auth/user.birthday.read']
);
final GoogleSignInAccount googleSignInAccount = await _googleSignIn.signIn();
final GoogleSignInAuthentication googleSignInAuthentication = await googleSignInAccount.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleSignInAuthentication.accessToken,
idToken: googleSignInAuthentication.idToken);
googleIdToken = googleSignInAuthentication.idToken;
final AuthResult authResult = await _auth.signInWithCredential(credential);
user = authResult.user;
final host = "https://people.googleapis.com";
final endpoint= "/v1/people/me/connections?personFields=names,birthdays";
final header = await googleSignInAccount.authHeaders;
print('loading birthday');
final request = await http.get("$host$endpoint", headers: header);
print('loading completed');
if(request.statusCode == 200){
print('api working perfectly');
print(request.body);
} else {
print('api error');
print(request.body);
}
// connecting to mongo database
AuthService().googleLogin(googleIdToken).then((val) {
if (val.data['success']) {
var token2 = val.data['token'];
AuthService().getInfo(token2).then((val) async {
print('SUCCESS AUTHENTICATION');
var store = val.data['user'];
showDialog(context: context,
builder: (BuildContext context){
return _SuucessLogin();
});
EasyLoading.dismiss();
});
} else {
print('WRONG EMAIL/ PASS');
}
});
assert(!user.isAnonymous);
assert(await user.getIdToken() != null);
final FirebaseUser currentUser = await _auth.currentUser();
assert(currentUser.uid == user.uid);
return user;
}
Can someone help me? Thank you in advance!
You should use the GetPerson action to get the authenticated user, not ListConnections which is for getting contacts. See documentation https://developers.google.com/people/v1/profiles#get_the_person_for_the_authenticated_user

How to SignIn with google on Parse Server

I'm developing an application with Flutter and Parse Server and I want to register Users from google account.
I have tried:
static Future<void> loginWithGoogle() async {
try {
final _googleSignIn = GoogleSignIn(scopes: ['email', 'https://www.googleapis.com/auth/contacts.readonly']);
final account = await _googleSignIn.signIn(); // I figure out that the real error is here;
final authentication = await account.authentication;
final googleAuth = google(_googleSignIn.currentUser.id, authentication.accessToken, authentication.idToken);
final response = await ParseUser.loginWith('google', googleAuth);
if (response.success) {
print(response);
//currentUser = await ParseUser.currentUser(customUserObject: User.clone());
//Get.offNamed('/oauth');
}
} catch (e) {
print(e);
AlertUtils.showErrorDialog(e.toString());
}
}
but here I faced that error:
plugin: PlatformException(sign_in_failed,
com.google.android.gms.common.api.ApiException: 10: , null)
You cannot do this without registering on Firebase. The official documentation says so.