2016-06-07 35 views
16

Khi tôi sử dụng signInWithEmailAndPassword() để đăng nhập onAuthStateChanged() luôn kích hoạt hai lần.Firebase Android onAuthStateChanged() kích hoạt hai lần sau khi signInWithEmailAndPassword()

Tôi chắc chắn rằng việc nghe chỉ được thêm một lần vào firebaseAuth, and I have the code in onStop() `để xóa người nghe sau đó.

Bất kỳ ai biết cách giải quyết vấn đề này?

Mã của tôi:

public class SignInActivity extends BaseActivity implements 
     View.OnClickListener, 
     GoogleApiClient.OnConnectionFailedListener{ 

    private static final String PREF_KEY_USER_EMAIL = "User_Email"; 
    private static final int RC_SIGN_IN = 1111; 

    private FirebaseAuth firebaseAuth; 
    private FirebaseAuth.AuthStateListener authStateListener; 
    private DatabaseReference firebaseDbReference; 

    private TextView fieldEmail; 
    private TextView fieldPassword; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_sign_in); 
     getSupportActionBar().hide(); 

     firebaseAuth = FirebaseAuth.getInstance(); 
     firebaseDbReference = FirebaseDatabase.getInstance().getReference(); 
     fieldEmail = (TextView) findViewById(R.id.field_email); 
     fieldPassword = (TextView) findViewById(R.id.field_password); 

     String userSavedEmail = getPreferences(MODE_PRIVATE).getString(PREF_KEY_USER_EMAIL, ""); 
     if(userSavedEmail != null) { 
      fieldEmail.setText(userSavedEmail); 
      fieldPassword.requestFocus(); 
     } 

     TextView linkForgotPassword; 
     Button buttonLogin; 

     linkForgotPassword = (TextView) findViewById(R.id.link_forgotPassword); 
     buttonLogin = (Button) findViewById(R.id.button_Login); 
     buttonSignUp = (Button) findViewById(R.id.button_signUp); 

     if (linkForgotPassword != null) { 
      linkForgotPassword.setOnClickListener(this); 
     } 
     if (buttonLogin != null) { 
      buttonLogin.setOnClickListener(this); 
     } 
     if (buttonSignUp != null) { 
      buttonSignUp.setOnClickListener(this); 
     } 

     authStateListener = new FirebaseAuth.AuthStateListener() { 
      @Override 
      public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) { 
       if(firebaseAuth.getCurrentUser() != null) { 
        onAuthSuccess(firebaseAuth.getCurrentUser()); 
       } 
      } 
     }; 
    } 

    @Override 
    protected void onStart() { 
     super.onStart(); 
     firebaseAuth.addAuthStateListener(authStateListener); 
    } 

    @Override 
    protected void onStop() { 
     super.onStop(); 
     if (authStateListener != null) { 
      firebaseAuth.removeAuthStateListener(authStateListener); 
     } 
    } 

    @Override 
    public void onClick(View v) { 
     switch (v.getId()){ 
      case R.id.link_forgotPassword: 
       forgotPassword(); 
       break; 
      case R.id.button_Login: 
       emailLogin(); 
       break; 
      case R.id.button_signUp: 
       emailSignUp(); 
       break; 
     } 
    } 

    @Override 
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { 
     Toast.makeText(this, "Google Play Services error.", Toast.LENGTH_SHORT).show(); 
    } 

    private void forgotPassword(){ 
     FirebaseAuth auth = FirebaseAuth.getInstance(); 
     String emailAddress = fieldEmail.getText().toString(); 

     if(TextUtils.isEmpty(emailAddress)){ 
      Toast.makeText(SignInActivity.this, R.string.msg_EnterEmail, 
        Toast.LENGTH_SHORT).show(); 
     } 
     else { 
      showProgressDialog(); 
      auth.sendPasswordResetEmail(emailAddress) 
        .addOnCompleteListener(new OnCompleteListener<Void>() { 
         @Override 
         public void onComplete(@NonNull Task<Void> task) { 
          hideProgressDialog(); 
          if (task.isSuccessful()) { 
           Toast.makeText(SignInActivity.this, R.string.msg_ResetPasswordEmailSent, 
             Toast.LENGTH_LONG).show(); 
          } 
         } 
        }); 
     } 
    } 

    private void emailLogin(){ 
     if (!validateForm()) { 
      return; 
     } 

     showProgressDialog(); 
     String email = fieldEmail.getText().toString(); 
     String password = fieldPassword.getText().toString(); 

     firebaseAuth.signInWithEmailAndPassword(email, password) 
       .addOnCompleteListener(new OnCompleteListener<AuthResult>() { 
        @Override 
        public void onComplete(@NonNull Task<AuthResult> task) { 
         hideProgressDialog(); 

         if (!task.isSuccessful()) { 
          Toast.makeText(SignInActivity.this, R.string.msg_EmailLoginFailed, 
            Toast.LENGTH_SHORT).show(); 
         } 
         else { 
          // Save the email 
          getPreferences(MODE_PRIVATE).edit() 
            .putString(PREF_KEY_USER_EMAIL, fieldEmail.getText().toString()) 
            .apply(); 
         } 
        } 
       }); 
    } 

    private void emailSignUp(){ 
     if (!validateForm()) { 
      return; 
     } 

     showProgressDialog(); 
     String email = fieldEmail.getText().toString(); 
     String password = fieldPassword.getText().toString(); 

     firebaseAuth.createUserWithEmailAndPassword(email, password) 
       .addOnCompleteListener(new OnCompleteListener<AuthResult>() { 
        @Override 
        public void onComplete(@NonNull Task<AuthResult> task) { 
         hideProgressDialog(); 

         if (task.isSuccessful()) { 
          FirebaseUser user = task.getResult().getUser(); 
          String displayName = displayNameFromEmail(user.getEmail()); 

          // Update profile display name. 
          UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder() 
            .setDisplayName("Jane Q. User") 
            .build(); 
          user.updateProfile(profileUpdates); 
         } else { 
          Toast.makeText(SignInActivity.this, R.string.msg_EmailSignUpFailed, 
            Toast.LENGTH_SHORT).show(); 
         } 
        } 
       }); 
    } 

    private void onAuthSuccess(FirebaseUser user) { 
     // Write new user 
     writeNewUser(user.getUid(), 
       user.getDisplayName(), 
       user.getEmail(), 
       user.getPhotoUrl()); 

     // Go to MainActivity 
     startActivity(new Intent(this.getApplicationContext(), MainActivity.class)); 
     finish(); 
    } 

    private void writeNewUser(String userId, String displayName, String email, android.net.Uri photoUrl) { 
     User user = new User(displayName, email); 

     if(photoUrl != null){ 
      user.setPhotoUrl(photoUrl.toString()); 
     } 

     firebaseDbReference.child("users").child(userId).setValue(user); 
    } 

    private String displayNameFromEmail(String email) { 
     if (email.contains("@")) { 
      return email.split("@")[0]; 
     } else { 
      return email; 
     } 
    } 

    private boolean validateForm() { 
     boolean result = true; 
     if (TextUtils.isEmpty(fieldEmail.getText().toString())) { 
      fieldEmail.setError("Required"); 
      result = false; 
     } else { 
      fieldEmail.setError(null); 
     } 

     if (TextUtils.isEmpty(fieldPassword.getText().toString())) { 
      fieldPassword.setError("Required"); 
      result = false; 
     } else { 
      fieldPassword.setError(null); 
     } 

     return result; 
    } 
} 
+1

Cross-post: https://groups.google.com/forum/#!topic/firebase-talk/IyonCBrR0kg –

Trả lời

6

Nó lửa hai lần và tôi nghĩ rằng đây là một lỗi mà căn cứ hỏa lực chàng trai nên sửa chữa (nhìn bạn Frank hehehe). Điều duy nhất tôi có thể nghĩ rằng bạn có thể làm ngay bây giờ là thêm một lá cờ như thế này.

private boolean flag = true; 
... 
authStateListener = new FirebaseAuth.AuthStateListener() { 
      @Override 
      public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) { 
       if(firebaseAuth.getCurrentUser() != null && flag) { 
        onAuthSuccess(firebaseAuth.getCurrentUser()); 
        flag=false; 
       } 
      } 
     }; 

Xa lý tưởng, nhưng sẽ hoạt động ngay bây giờ. Mã vẫn kích hoạt hai lần, chúng tôi chấp nhận mã đầu tiên và từ chối thẻ thứ hai với cờ của chúng tôi, theo cách này nếu các nhân viên Firebase sửa lỗi và đột nhiên người nghe chạy một lần, mã của chúng tôi vẫn hoạt động. Có thể nó được thiết kế cho người nghe chạy hai lần, hy vọng chúng tôi sẽ có một số câu trả lời từ bài đăng

+0

Điều này thực sự sẽ không hoạt động đầy đủ, Nếu không có thông tin đăng nhập người dùng bạn không thông báo vì người dùng hiện tại sẽ null, cũng như nếu người dùng thay đổi. Xem câu trả lời của tôi – Marcel

+2

đây là một cách giải quyết, nó vẫn xảy ra cho đến bây giờ. Ngay cả hỏa hoạn 3 lần trong trường hợp của tôi! –

+2

Mỗi lần tôi đăng xuất, sau đó đăng nhập lại, nó sẽ kích hoạt thêm một lần nữa cho đến khi tôi khởi động lại ứng dụng của mình. – nilsi

0

của Frank cũng là giải pháp chính xác hơn.

private String authFlag = ""; 

... 

authStateListener = new FirebaseAuth.AuthStateListener() { 
      @Override 
      public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {  
      if (firebaseAuth.getCurrentUser() == null) { 
       if (authFlag != null) { 
       authFlag = null; 
       subscriber.onNext(null); 
       } 
      } else { 
       String uid = firebaseAuth.getCurrentUser().getUid(); 
       if (authFlag == null || authFlag.isEmpty() || !authFlag.equals(uid)) { 
       authFlag = uid; 
       subscriber.onNext(firebaseAuth.getCurrentUser()); 
       } 
      } 
} 
+0

Tôi biết không phải là giải pháp lý tưởng nhưng không chỉ hạ cấp, đăng ý kiến ​​của bạn – Marcel

2

Cuộc gọi kép là do cuộc gọi đăng ký. Không chỉ vậy, onAuthStateChanged sẽ được gọi nhiều lần ở nhiều bang khác nhau, không có khả năng biết được trạng thái của nó.

Documentation nói:

onAuthStateChanged (FirebaseAuth auth)

Phương pháp này được gọi trong thread UI trên những thay đổi trong trạng thái xác thực:

  • Ngay sau khi người nghe có đã được đăng ký

  • Khi một người dùng được đăng nhập

  • Khi người dùng hiện đang đăng xuất
  • Khi người dùng hiện tại thay đổi
  • Khi có sự thay đổi trong của người dùng hiện dấu hiệu

Dưới đây một số các mẹo để khám phá trạng thái hiện tại:

  • Cuộc gọi đăng ký: bỏ qua cuộc gọi đầu tiên bằng cờ.
  • Người dùng đã đăng nhập: người dùng từ tham số là! = Null.
  • Người dùng đã đăng xuất: người dùng từ tham số là == null.
  • Thay đổi người dùng hiện tại: người dùng từ tham số là! = Null và id người dùng cuối cùng!= User id từ tham số
  • tài refresh thẻ: sử dụng từ tham số là = null và cuối cùng người dùng id là == sử dụng id từ tham số

nghe Đây là một mớ hỗn độn và rất bugprone. Nhóm Firebase nên xem xét nó.

+0

Có, tôi đồng ý, và trong kết quả tìm kiếm của tôi tôi thấy đó là do cuộc gọi đăng ký, mặc dù cách phân biệt giữa đăng ký và đăng nhập. –

Các vấn đề liên quan