webentwicklung-frage-antwort-db.com.de

Firebase Android onAuthStateChanged () wird zweimal nach signInWithEmailAndPassword () ausgelöst

Wenn ich mich mit signInWithEmailAndPassword() anmelde, wird die onAuthStateChanged() immer zweimal ausgelöst.

Ich bin mir sehr sicher, dass das Listening nur einmal zu firebaseAuth, and I have the code inonStop () `hinzugefügt wird, um den Listener danach zu entfernen.

Weiß jemand, wie man das löst?

Mein Code:

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;
    }
}
16
Terrence

Es wird zweimal ausgelöst, und ich denke, dies ist ein Fehler, den Firebase-Leute beheben sollten (Sie sehen Frank hehehe). Ich kann mir nur vorstellen, dass Sie jetzt eine solche Flagge hinzufügen können.

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;
                }
            }
        };

Weit davon entfernt, ideal zu sein, wird aber vorerst funktionieren. Code wird immer noch zweimal ausgelöst, wir akzeptieren den ersten und verweigern den zweiten mit unserer Flagge. Wenn Firebase-Leute dies beheben und der Listener plötzlich einmal ausgeführt wird, funktioniert unser Code immer noch. Vielleicht ist es für den Hörer vorgesehen, zweimal zu laufen, hoffentlich haben wir einige Antworten von Franks Cross-Post

6
user3597165

Der Doppelanruf ist ein Registrierungsanruf fällig. Darüber hinaus wird onAuthStateChanged in vielen verschiedenen Status mehrfach aufgerufen, ohne dass die Möglichkeit besteht, den Status zu kennen.

Dokumentation sagt:

onAuthStateChanged (FirebaseAuth-Authentifizierung)

Diese Methode wird im UI-Thread bei Änderungen des Authentifizierungsstatus aufgerufen:

  • Gleich nachdem der Zuhörer registriert wurde

  • Wenn ein Benutzer angemeldet ist

  • Wenn der aktuelle Benutzer abgemeldet ist
  • Wenn sich der aktuelle Benutzer ändert
  • Wenn sich das Token des aktuellen Benutzers ändert

Hier einige Tipps, um den aktuellen Stand zu entdecken:

  • Registrierungsanruf: Überspringen Sie den ersten Anruf mit einer Flagge.
  • Benutzer angemeldet: Benutzer vom Parameter ist! = Null.
  • Benutzer abgemeldet: Benutzer vom Parameter ist == null.
  • Aktueller Benutzer ändert sich: Benutzer aus Parameter ist! = Null und letzte Benutzer-ID ist! = Benutzer-ID aus Parameter
  • Aktualisierung des Benutzertokens: Benutzer vom Parameter ist! = Null und die letzte Benutzer-ID ist == Benutzer-ID vom Parameter

Dieser Zuhörer ist ein Chaos und sehr fehleranfällig. Das Firebase-Team sollte sich darum kümmern.

2
Fabricio

Weit davon entfernt, auch ideal, aber es ist eine genauere Lösung.

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
Marcel