how to fix: handleWindowVisibility: no activity for token android.os.BinderProxy bug - flutter

I am using flutter_facebook_auth to login and register my user. Backend - firebase.
class FacebookSignInProvider extends ChangeNotifier {
Map<String, dynamic> _userData;
Future<UserCredential> signInWithFacebook(BuildContext context) async {
final LoginResult result = await FacebookAuth.i.login(
permissions: ['name', 'email', 'user_birthday', 'user_gender'],
);
if(result.status == LoginStatus.success){
final userData = await FacebookAuth.i.getUserData(fields: "username,
email, birthday, gender");
_userData = userData;
final OAuthCredential credential =
FacebookAuthProvider.credential(result.accessToken.token);
return await FirebaseAuth.instance.signInWithCredential(credential);
}
Navigator.of(context).pushReplacement(
CupertinoPageRoute(builder: (_) => TabScreen()));
notifyListeners();
return null;
}
}
This goes to the FB Sorry, something went wrong screen.
What bug is this?

Related

How to pass uid and email to sharedpreference method When signUp in flutter?

I built the google signin and email password signup app using flutter,
I want when user log to application then user's "uid" and "email" save in shared preference.
In google login I built when login then pass the boolean value and pass uid and email to shared preference. Then when users close app and when reopen then login in home screen and can get uid and email.
But when user signup or login using email password then can not pass the boolean value and uid and email to google login shared preference. In below I'll mentioned google login method and email password method.
googlelogin method
// handling google sigin in
Future handleGoogleSignIn() async {
final sp = context.read<SignInProvider>();
final ip = context.read<InternetProvider>();
await ip.checkInternetConnection();
if (ip.hasInternet == false) {
openSnackbar(context, 'Check your Internet connection', Colors.red);
googleController.reset();
} else {
await sp.signInWithGoogle().then((value) {
if (sp.hasError == true) {
openSnackbar(context, sp.errorCode.toString(), Colors.white);
googleController.reset();
} else {
// checking whether user exists or not
sp.checkUserExists().then((value) async {
if (value == true) {
// user exists
await sp.getUserDataFromFirestore(sp.uid).then((value) => sp
.saveDataToSharedPreferences()
.then((value) => sp.setSignIn().then((value) {
googleController.success();
handleAfterSignIn();
})));
} else {
// user does not exist
sp.saveDataToFirestore().then((value) => sp
.saveDataToSharedPreferences()
.then((value) => sp.setSignIn().then((value) {
googleController.success();
handleAfterSignIn();
})));
}
});
}
});
}
//login function
}
saveDataToSharedPreferences method and setSignIn boolean value (it has in a siginprovider class in another file)
class SignInProvider extends ChangeNotifier {
//instantiate of firebaseAuth, facebook and google
final FirebaseAuth firebaseAuth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();
bool _isSignedIn = false;
bool get isSignedIn => _isSignedIn;
//hasError, errorCode, provider,uid,email,name,imageUrl
bool _hasError = false;
bool get hasError => _hasError;
String? _errorCode;
String? get errorCode => _errorCode;
String? _uid;
String? get uid => _uid;
String? _email;
String? get email => _email;
SignInProvider() {
checkSignInUser();
}
Future checkSignInUser() async {
final SharedPreferences s = await SharedPreferences.getInstance();
_isSignedIn = s.getBool('signed_in') ?? false;
notifyListeners();
}
Future setSignIn() async {
final SharedPreferences s = await SharedPreferences.getInstance();
s.setBool('signed_in', true);
_isSignedIn = true;
notifyListeners();
}
Future saveDataToSharedPreferences() async {
final SharedPreferences s = await SharedPreferences.getInstance();
await s.setString('email', _email!);
await s.setString('uid', _uid!);
notifyListeners();
}
Future getDataFromSharedPreferences() async {
final SharedPreferences s = await SharedPreferences.getInstance();
_email = s.getString('email');
_uid = s.getString('uid');
notifyListeners();
}
}
**email password signup**
void signUp(String email, String password) async {
if (_formkey.currentState!.validate()) {
await _auth
.createUserWithEmailAndPassword(email: email, password: password)
.saveDataToSharedPreferences()
.sp.setSignIn()
.then((value) => {postDetailsToFirestore()})
.catchError((e) {
Fluttertoast.showToast(msg: e!.message);
});
}
}
in email password signup has postDetailsToFirestore method
postDetailsToFirestore() async {
// calling our fireStore
//calling our user model
// sending these values
FirebaseFirestore firebaseFirestore = FirebaseFirestore.instance;
User? user = _auth.currentUser;
UserModel userModel = UserModel();
if (user != null) {
//writing all the values
userModel.email = user?.email;
userModel.uid = user?.uid;
await firebaseFirestore
.collection("users")
.doc(user?.uid)
.set(userModel.toMap());
Fluttertoast.showToast(msg: "Account created successfully ");
Navigator.pushAndRemoveUntil(
(context),
MaterialPageRoute(builder: (context) => HomeScreen()),
(route) => false);
}
}
in email password signup I called
these 2 methods but show this error
when signup how to pass uid and emaill to saveDataToSharedPreferences method and pass sp.setSignIn() boolean like as in google signing?
You are trying to use method saveDataToSharedPreferences from Future class, not from auth. For fix this issue, call prefs from main object:
final result = await _auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
result.saveDataToSharedPreferences()
.sp.setSignIn()
// etc.

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 Getx: google signin and map data to firebase automatically logs me back in as same user?

I am trying to login with google and have the data mapped to a firebase user. I'm using getX. So far this works HOWEVER it automatically logs me back in as the same user if I logout and then try to log back in again. I'll send the code for my login page and the page where the logout button is if needed, but I suspect this may have to do with my AuthController which I've included here
class AuthController extends GetxController {
static AuthController instance = Get.find();
GoogleSignIn googleSignIn = GoogleSignIn();
Rxn<User> firebaseUser = Rxn<User>();
Rxn<UserModel> firestoreUser = Rxn<UserModel>();
final RxBool admin = false.obs;
String usersCollection = "users";
#override
void onReady() async {
//run every time auth state changes
ever(firebaseUser, handleAuthChanged);
firebaseUser.bindStream(user);
super.onReady();
}
handleAuthChanged(firebaseUser) async {
//get user data from firestore
if (firebaseUser?.uid != null) {
firestoreUser.bindStream(streamFirestoreUser());
print("You are logged in as ${firebaseUser.email}");
await isAdmin();
}
//this is for new users
if (firebaseUser == null) {
print('Send to signin');
Get.offAll(LoginPage());
} else {
Get.offAll(AppSetup());
}
}
// Firebase user one-time fetch
Future<User> get getUser async => auth.currentUser!;
// Firebase user a realtime stream
Stream<User?> get user => auth.authStateChanges();
//Streams the firestore user from the firestore collection
Stream<UserModel> streamFirestoreUser() {
print('streamFirestoreUser()');
return firebaseFirestore
.doc('/users/${firebaseUser.value!.uid}')
.snapshots()
.map((snapshot) => UserModel.fromSnapshot(snapshot));
}
//get the firestore user from the firestore collection
Future<UserModel> getFirestoreUser() {
return firebaseFirestore
.doc('/users/${firebaseUser.value!.uid}')
.get()
.then((documentSnapshot) => UserModel.fromSnapshot(documentSnapshot));
}
//Method to handle user sign in using email and password
// User registration using email and password
googleLogin(BuildContext context) async {
final GoogleSignInAccount? googleUser = await googleSignIn.signIn();
if (googleUser != null) {
final googleAuth = await googleUser.authentication;
if (googleAuth.accessToken != null && googleAuth.idToken != null) {
try {
await auth
.signInWithCredential(
GoogleAuthProvider.credential(
idToken: googleAuth.idToken,
accessToken: googleAuth.accessToken),
)
.then((firebaseUser) async {
print('uid: ' + firebaseUser.user!.uid.toString());
print('email: ' + firebaseUser.user!.email.toString());
//create the new user object from the login modelled data
UserModel _newUser = UserModel(
id: firebaseUser.user!.uid,
email: firebaseUser.user!.email!,
name: firebaseUser.user!.email!,
photoURL: firebaseUser.user!.photoURL,
cart: [],
);
//create the user in firestore here with the _addUserToFirestore function
_updateUserFirestore(_newUser, firebaseUser.user!);
});
} on FirebaseAuthException catch (error) {
Get.snackbar('auth.signUpErrorTitle'.tr, error.message!,
snackPosition: SnackPosition.BOTTOM,
duration: Duration(seconds: 10),
backgroundColor: Get.theme.snackBarTheme.backgroundColor,
colorText: Get.theme.snackBarTheme.actionTextColor);
}
}
}
}
void _updateUserFirestore(UserModel user, User _firebaseUser) {
firebaseFirestore.doc('/users/${_firebaseUser.uid}').update(user.toJson());
update();
}
updateUserData(Map<String, dynamic> data) {
logger.i("UPDATED");
firebaseFirestore
.collection(usersCollection)
.doc(firebaseUser.value!.uid)
.update(data);
}
//check if user is an admin user
isAdmin() async {
await getUser.then((user) async {
DocumentSnapshot adminRef =
await firebaseFirestore.collection('admin').doc(user.uid).get();
if (adminRef.exists) {
admin.value = true;
} else {
admin.value = false;
}
update();
});
}
// This is the proper sign out method!
Future<void> signOut() {
return auth.signOut();
}
}
Simply add this line of code into your logout function
> await googleSignIn.signOut()

Fetch data from firestore after Sign In before showing HomeScreen

When a User sign up for the first time, i want that he gets a own firestore document with some data. This data I want to show on the homescreen but I get an error that the data is not there yet. After hot reload the data is there so the problem is that the homescreen is shown before the data is fetched from firestore although I use a FutureBuilder. I only got this problem when a user signs in for the first time.
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);
await getUserData();
} catch (e) {
print(e.toString());
}
notifyListeners();
}
Future getUserData() async {
final myUser = FirebaseAuth.instance.currentUser;
bool userExist = await checkIfUserExists(myUser.uid);
if (userExist == false) {
print('User dont exist');
await FirebaseFirestore.instance.collection('users').doc(myUser.uid).set({
"email": myUser.email,
"plans": [],
"userScore": "100",
});
} else {
print('User exist');
}
/// Save userData from firestore in a Helper class which is shown on the homescreen
var userData = FirebaseFirestore.instance.collection('users').doc(myUser.uid);
return FutureBuilder(
future: userData.get(),
builder: (context, userDataSnapshot) {
if (userDataSnapshot.data == ConnectionState.done) {
var value = userDataSnapshot.data;
UserManager.userdata = value.data(); //static class where userData is stored
return null;
} else {
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
});
}
Future<bool> checkIfUserExists(String uid) async {
try {
var collectionRef = FirebaseFirestore.instance.collection('users');
var doc = await collectionRef.doc(uid).get();
return doc.exists;
} catch (e) {
throw e;
}
}
EDIT
This is the Button where the user can sign In
ElevatedButton.icon(
onPressed: () {
final provider = Provider.of<GoogleSignInProvider>(context, listen: false);
provider.googleLogin();
},
icon: Icon(MdiIcons.google),
label: Text(
'Sign In with Google',
style: TextStyle(fontSize: 16),
),
),
The problem here is that FutureBuilder is a widget, it should not be used in a function to wait for a future to complete, but in another widget to have callbacks on the completion and change display based on that.
If not rendered, FutureBuilder will do nothing but be instantiated and occupy memory.
You should probably modify your code as such:
...
/// Save userData from firestore in a Helper class which is shown on the homescreen
var userData = await FirebaseFirestore.instance.collection('users').doc(myUser.uid).get();
UserManager.userdata = userData.data();
...
Should you want to add a CircularProgress on your main screen, this would be done by lisntening to your Provider in some way.

UserProfile crashes after auth.getCurrentUser()

I am making an app in flutter an now when i try to show the user Name on the profile i got this error
════════ Exception caught by widgets library ═══════════════════════════════════
The following NoSuchMethodError was thrown building UserPage(dirty, dependencies: [MediaQuery], state: _UserProfile#ca57c):
The getter 'auth' was called on null.
Receiver: null
Tried calling: auth
The relevant error-causing widget was
UserPage
lib/HomePage.dart:92
When the exception was thrown, this was the stack
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
#1 _UserProfile.build
package:tariffo/UserPage.dart:131
#2 StatefulElement.build
package:flutter/…/widgets/framework.dart:4619
#3 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4502
#4 StatefulElement.performRebuild
package:flutter/…/widgets/framework.dart:4675
...
═══════════════════════════════════════════════════════════════════════════════
and i used this code
FutureBuilder(
future:
Provider.of(context).auth.getCurrentUser(),
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.done) {
return Text("${snapshot.data.displayName}",
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 22,
));
} else {
return CircularProgressIndicator();
}
},
),
This is the code that i used for my auth.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'User.dart';
String email, name, photoUrl;
class Authentication {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
final GoogleSignIn _googleSignIn = GoogleSignIn();
Stream<String> get onAuthStateChanged => _firebaseAuth.onAuthStateChanged.map(
(FirebaseUser user) => user?.uid,
);
// GET UID
Future<String> getCurrentUID() async {
return (await _firebaseAuth.currentUser()).uid;
}
// GET CURRENT USER
Future getCurrentUser() async {
return await _firebaseAuth.currentUser();
}
// Email & Password Sign Up
Future<String> createUserWithEmailAndPassword(
String email, String password, String name) async {
final authResult = await _firebaseAuth.createUserWithEmailAndPassword(
email: email,
password: password,
);
// Update the username
await updateUserName(name, authResult.user);
return authResult.user.uid;
}
Future updateUserName(String name, FirebaseUser currentUser) async {
var userUpdateInfo = UserUpdateInfo();
userUpdateInfo.displayName = name;
await currentUser.updateProfile(userUpdateInfo);
await currentUser.reload();
}
// Email & Password Sign In
Future<String> signInWithEmailAndPassword(
String email, String password) async {
return (await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password))
.user
.uid;
}
// Sign Out
signOut() {
return _firebaseAuth.signOut();
}
// Reset Password
Future sendPasswordResetEmail(String email) async {
return _firebaseAuth.sendPasswordResetEmail(email: email);
}
// Create Anonymous User
Future singInAnonymously() {
return _firebaseAuth.signInAnonymously();
}
Future convertUserWithEmail(
String email, String password, String name) async {
final currentUser = await _firebaseAuth.currentUser();
final credential =
EmailAuthProvider.getCredential(email: email, password: password);
await currentUser.linkWithCredential(credential);
await updateUserName(name, currentUser);
}
Future convertWithGoogle() async {
final currentUser = await _firebaseAuth.currentUser();
final GoogleSignInAccount account = await _googleSignIn.signIn();
final GoogleSignInAuthentication _googleAuth = await account.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
idToken: _googleAuth.idToken,
accessToken: _googleAuth.accessToken,
);
await currentUser.linkWithCredential(credential);
await updateUserName(_googleSignIn.currentUser.displayName, currentUser);
}
// GOOGLE
Future<String> signInWithGoogle() async {
final GoogleSignInAccount account = await _googleSignIn.signIn();
final GoogleSignInAuthentication _googleAuth = await account.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
idToken: _googleAuth.idToken,
accessToken: _googleAuth.accessToken,
);
return (await _firebaseAuth.signInWithCredential(credential)).user.uid;
}
// APPLE
}
class NameValidator {
static String validate(String value) {
if (value.isEmpty) {
return "Name can't be empty";
}
if (value.length < 2) {
return "Name must be at least 2 characters long";
}
if (value.length > 50) {
return "Name must be less than 50 characters long";
}
return null;
}
}
class EmailValidator {
static String validate(String value) {
if (value.isEmpty) {
return "Email can't be empty";
}
return null;
}
}
class PasswordValidator {
static String validate(String value) {
if (value.isEmpty) {
return "Password can't be empty";
}
return null;
}
}
and this is the code for User.dart
import 'package:flutter/material.dart';
class User {
final String uid;
User({this.uid});
String adress;
bool business;
Map<String, dynamic> toJson() => {
'adress': adress,
'business': business,
};
}
Now it just appear a red background when i try to acces the profile page pressing the profile icon button
provider_widget.dart
import 'package:flutter/material.dart';
import 'auth.dart';
class Provider extends InheritedWidget {
final Authentication auth;
Provider({Key key, Widget child, this.auth}) : super(key: key, child: child);
#override
bool updateShouldNotify(InheritedWidget oldWidget) {
return true;
}
static Provider of(BuildContext context) =>
(context.inheritFromWidgetOfExactType(Provider) as Provider);
}