简体   繁体   中英

Flutter Firebase auth user is not persistent on the device

I'm using firebase phone auth in my Flutter application for android. The login system works properly. However, every time I open the app, it returns null user. Due to which, I have to login every time I open the app. I don't know if this is a bug or a mistake on my end but I'll share the code with you guys over here.

PhoneAuth code:

enum PhoneAuthStatus {
  SignedIn,
  CodeSent,
  HasError,
  SignedOut,
}


class PhoneAuth with ChangeNotifier {
  String verificationId;
  final FirebaseAuth phoneAuth = FirebaseAuth.instance;
  PhoneAuthStatus phoneAuthStatus = PhoneAuthStatus.SignedOut;

  PhoneAuth.initialize() {
    init();
  }

  Future<void> init() async {
    currentUser = await phoneAuth.currentUser();
    if (currentUser == null) {
      phoneAuthStatus = PhoneAuthStatus.SignedOut;
      notifyListeners();
    } else {
      phoneAuthStatus = PhoneAuthStatus.SignedIn;
    }
  }

  PhoneAuthStatus get status => phoneAuthStatus;
  FirebaseUser get user => currentUser;

  Future<void> verifyPhoneNumber(String phNum) async {
    phoneAuth.verifyPhoneNumber(
        phoneNumber: phNum,
        timeout: Duration(seconds: 90),
        verificationCompleted: (AuthCredential phoneAuthCredential) async {
          AuthResult authResult;
          try {
            authResult =
                await phoneAuth.signInWithCredential(phoneAuthCredential);
          } catch (error) {
            phoneAuthStatus = PhoneAuthStatus.HasError;
            notifyListeners();
            return;
          }
          currentUser = authResult.user;
          uid = currentUser.uid;
          phoneAuthStatus = PhoneAuthStatus.SignedIn;
          notifyListeners();
        },
        verificationFailed: (AuthException authException) {
          print(authException.message);
          phoneAuthStatus = (PhoneAuthStatus.HasError);
          notifyListeners();
        },
        codeSent: (String vId, [int forceResendingToken]) async {
          phoneAuthStatus = (PhoneAuthStatus.CodeSent);
          notifyListeners();
          verificationId = vId;
        },
        codeAutoRetrievalTimeout: (String vId) {
          verificationId = vId;
        });
    return;
  }

  Future<void> signInWithPhoneNumber(String code) async {
    final AuthCredential credential = PhoneAuthProvider.getCredential(
      verificationId: verificationId,
      smsCode: code.toString(),
    );
    AuthResult authResult;
    try {
      authResult = await phoneAuth.signInWithCredential(credential);
    } catch (error) {
      phoneAuthStatus = (PhoneAuthStatus.HasError);
      notifyListeners();
      return;
    }
    currentUser = authResult.user;
    phoneAuthStatus = (PhoneAuthStatus.SignedIn);
    notifyListeners();
    return;
  }

  Future<void> signOut() async {
    phoneAuth.signOut();
    phoneAuthStatus = (PhoneAuthStatus.SignedOut);
    notifyListeners();
  }
}

main.dart code:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider.value(value: PhoneAuth.initialize()),
      ],
      child: MaterialApp(
        title: app_name,
        // routes: Routes.routes,
        debugShowCheckedModeBanner: false,
        theme: ThemeData(
            primarySwatch: Colors.blue,
        )
        home: Container(
          child: LocationError(currentWidget: HomePage()),
        ),
      ),
    );
  }
}

The init() function should return PhoneAuthStatus.SignedIn. However, it returns PhoneAuthStatus.SignedOut because the currentUser is null. Please help me and tell me if I'm doing anything wrong. Thank You.

Flutter doctor:

Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 1.20.0, on Microsoft Windows [Version 10.0.18363.959], locale en-US)
 
[!] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
    X Android license status unknown.
      Try re-installing or updating your Android SDK Manager.
      See https://developer.android.com/studio/#downloads or visit https://flutter.dev/docs/get-started/install/windows#android-setup for detailed instructions.
[√] Android Studio (version 4.0)
[√] VS Code (version 1.47.3)
[!] Connected device
    ! No devices available

! Doctor found issues in 2 categories.

Did you check with placing notifyListeners() outside of if block?

     currentUser = await phoneAuth.currentUser();
    if (currentUser == null) {
      phoneAuthStatus = PhoneAuthStatus.SignedOut;
     
    } else {
      phoneAuthStatus = PhoneAuthStatus.SignedIn;
    }
 notifyListeners();

and another guess is, you are calling a future method inside a init() method. maybe that's why you are always getting auth status as signOut.

"The init method is synchronous by design. Rather than creating the FutureBuilder widget in the init method, you could return the FutureBuilder widget in the overridden build method. Feel free to take a look at the documentation for the FutureBuilder widget here for an example of how this could work."

So, I think it is better to use a future builder for verifying the user's presence.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM