Check authentication state using stream not working in Flutter

Viewed 642

I'm using GoogleSignIn.

On my splash screen, I'm using StreamBuilder to check whether the user is logged in or not, and based on that data I'm trying to show the Login Screen or Home Screen.

When I uninstall and reinstall the app it shows the Login Screen for the first time. And then after it always shows me the Home Screen even if I logged out from the app.

Below is my code for Splash Screen:

class SplashScreen extends StatefulWidget {
  @override
  _SplashScreenState createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> {
  @override
  Widget build(BuildContext context) {
    SizeConfig().init(context);
    return StreamBuilder(
      stream: FirebaseAuth.instance.authStateChanges(),
      builder: (BuildContext context, AsyncSnapshot<User> snapshot) {
        if (snapshot.hasData) {
          print(snapshot.hasData);
          return AnimatedSplashScreen(
            splashIconSize: SizeConfig.blockSizeVertical * 16,
            splashTransition: SplashTransition.fadeTransition,
            nextScreen: HomeScreen(),
            splash: kLogoImage,
            duration: 800,
          );
        } else {
          print(snapshot.hasData);
          return AnimatedSplashScreen(
            splashIconSize: SizeConfig.blockSizeVertical * 16,
            splashTransition: SplashTransition.fadeTransition,
            nextScreen: LoginScreen(),
            splash: kLogoImage,
            duration: 800,
          );
        }
      },
    );
  }
}

Below is my code for Home Screen:

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  final GoogleSignIn googleSignIn = GoogleSignIn();
  User firebaseUser;

  signOut() async {
    await googleSignIn.signOut();
    Navigator.pushReplacementNamed(context, MyRoutes.loginScreen);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Center(
            child: Text('Hello'),
          ),
          MaterialButton(
              child: Text('Log out'),
              color: Colors.red,
              onPressed: () {
                signOut();
              })
        ],
      ),
    );
  }
}
3 Answers

I don't know why it doesn't,t work I think your code is correct but I have another way to do that you can use stream provider instead of stream builder

wrap the stream provider above your material app or cupirtinoapp :

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamProvider.value(
      value: firebaseauht.inistance.onauthchange,
      child: MaterialApp(
        home: Wholescreen(),
      ),
    );
  }
}

then call the provider in the wholescreen :

class Wholescreen extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    var provider = Provider.of<User>(context);
    if (provider!=null) {
      return AnimatedSplashScreen(
            splashIconSize: SizeConfig.blockSizeVertical * 16,
            splashTransition: SplashTransition.fadeTransition,
            nextScreen: HomeScreen(),
            splash: kLogoImage,
            duration: 800,
    } else {
      return AnimatedSplashScreen(
            splashIconSize: SizeConfig.blockSizeVertical * 16,
            splashTransition: SplashTransition.fadeTransition,
            nextScreen: LoginScreen(),
            splash: kLogoImage,
            duration: 800,
          ); 
    }
  }
}

Could it be that GoogleSignIn is not the same as Firebase?

Try replacing googleSignIn.signOut() with FirebaseAuth.instance.signOut() on your home screen.

Change this:

  signOut() async {
    await googleSignIn.signOut();
    Navigator.pushReplacementNamed(context, MyRoutes.loginScreen);
  }

Into this:

  signOut() async {
    await googleSignIn.disconnect();
    Navigator.pushReplacementNamed(context, MyRoutes.loginScreen);
  }

According to the docs the disconnect method is what revokes the authentication/signs the user out.

Related