본문으로 바로가기

유저 상태 체크 : onAuthStateChanged

 

auth 상태가 변경되는 것을 감지합니다.

아래와 같이 작성하면, 유저가 로그인 했을 때는 MainPage()를 안 했을 때는 AuthPage()를 보여줍니다.

home: StreamBuilder<FirebaseUser>(
  stream: FirebaseAuth.instance.onAuthStateChanged,
  builder: (context, snapshot) {
    if(snapshot.hasData) {
      return MainPage();
    }
    return AuthPage();
  }

 

로그인한 상태로 다시 앱에 진입할 때 깜빡거리는 것을 막기 위해서 처음인지 체크하고 처음이면 스피너를 돌립니다.

깜빡거리는 이유는 처음 앱을 실행했을 때는 firebase와 통신하기 전이기 때문에 null값을 던지기 때문입니다.

void main() {
  return runApp(MyApp());
}

// 처음 인지 체크함
bool isItFirstData = true;

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: white
      ),
      home: StreamBuilder<FirebaseUser>(
        stream: FirebaseAuth.instance.onAuthStateChanged,
        builder: (context, snapshot) {
        
          // 처음 데이터인가? 스피너를 돌리자 (로그인으로 인식할 때까지)
          if (isItFirstData) {
            isItFirstData = false;
            return MyProgressIndicator();
          } else {
            // 아니면 그냥 일반적으로 하듯 실행
            if(snapshot.hasData) {
              return MainPage();
            }
            return AuthPage();
          }
        }
      )
    );
  }
}

 

 

회원가입: createUserWithEmailAndPassword

 

FirebaseAuth.instance.createUserWithEmailAndPassword를 이용합니다.

입력한 controller에서 text를 추출해서 유저를 만들어봅니다.

get _register async {

  // 유저 생성
  final AuthResult result = await FirebaseAuth.instance
      .createUserWithEmailAndPassword(
      email: _emailController.text, password: _pwController.text);
      
  // 해당 결과로 인해 반환되는 값    
  final user = result.user;
  
  // 유저 생성에 실패했으면 스낵바
  if (user == null) {
    final snackBar = SnackBar(content: Text("Please try again later!"));
    Scaffold.of(context).showSnackBar(snackBar);
  } 
}

 

Register 버튼을 누르면 validate 이후에 작동하도록 만들었습니다.

FlatButton(
  child: Text(
    "Register",
    style: TextStyle(color: Colors.white),
  ),
  color: Colors.blue,
  shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(6)),
  onPressed: () {
    if (_formKey.currentState.validate()) {
      _register;
    }
  },
),

 

만약 다음과 같은 오류가 났다면 에뮬레이터 문젱리 가능성이 큽니다.

AVD의 Target을 Android 7.0 Nougat 을 사용하고 있었는데 이런 오류가 났습니다. 9.0 Pie 이상으로 업데이트해줍시다

 

(https://stackoverflow.com/questions/54733720/firebaseauth-getgoogleapiformethod-returned-gms-com-google-firebase-auth-api)

getGoogleApiForMethod() returned Gms: com.google.firebase.auth.api.internal.zzaq@2cdf471
W/DynamiteModule(31092): Local module descriptor class for com.google.firebase.auth not found.
W/GooglePlayServicesUtil(31092): Google Play services out of date.  Requires 12451000 but found 11743470

 

 

로그인 : signInWithEmailAndPassword

 

get _login async {
  final AuthResult result = await FirebaseAuth.instance
      .signInWithEmailAndPassword(email: _emailController.text, password: _pwController.text);
  final user = result.user;
  if (user == null) {
    simpleSnackBar(context, "Please try again later!");
  }
}

역시 로그인 버튼 등 특정 이벤트가 일어날 때 _login을 끼워주면 됩니다.

FlatButton(
  child: Text(
    "Log in",
    style: TextStyle(color: Colors.white),
  ),
  color: Colors.blue,
  shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(6)),
  onPressed: () {
    if (_formKey.currentState.validate()) {
      // validate가 되면 로그인하도록!
      _login;
    }
  },
),

 

그런데 만약 로그인한 상태에서 앱을 종료하고 다시 앱을 실행하면 어떻게 될까요? 로그인이 된 상태가 유지됩니다. (굳)

문제는 처음 로그인을 체크하는 페이지에서 빈 값을 던지기 때문에 잠깐 AuthPage가 깜빡거립니다.

이 문제를 해결하려면 처음 앱을 실행하는 것인지를 체크해주면 되는데 상단에 수정한 코드를 올려두었습니다.

 

 

 

 

로그아웃: signOut

 

FirebaseAuth.instance의 메서드인 signOut을 이용하면 쉽게 로그아웃할 수 있습니다. 

 

FlatButton.icon(
  onPressed: () {
    FirebaseAuth.instance.signOut();
  },
  icon: Icon(Icons.exit_to_app),
  label: Text("Logout",
      style: TextStyle(
          color: Colors.black87, fontWeight: FontWeight.w500)),
)

 


darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체