0

I have an Android (Java) code, where I am trying to return true or false based on User Authentication from Firebase Auth. Let's see the code below first

public class MainActivity extends AppCompatActivity {

    private FirebaseAuth firebaseAuth;
    private FirebaseFirestore db = FirebaseFirestore.getInstance();
    private static  final String KEY_PHONE= "phone";

    boolean status = false;

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

        firebaseAuth = FirebaseAuth.getInstance();
        checkUserAuthStatus(firebaseAuth);
    }

    private void checkUserAuthStatus(FirebaseAuth firebaseAuth) {
        if(firebaseAuth.getCurrentUser() != null) { // Check User for Auth
            Toast.makeText(this, "Got Authentication", Toast.LENGTH_SHORT).show();
            if(checkPhone(firebaseAuth)) { // User has Phone Check <------ 
                Toast.makeText(this, "MAIN", Toast.LENGTH_SHORT).show();
                startActivity(new Intent(this, UserDataActivity.class));
                this.finish();
            }
            else { // User does not have Phone
                Toast.makeText(this, "Update Mobile Number", Toast.LENGTH_LONG).show();
                startActivity(new Intent(this, UserPhoneAuthentication.class));
                this.finish();
            }
        }
        else { // Does not have authentication
            startActivity(new Intent(this, UserEmailAuthentication.class));
            this.finish();
        }
    }

    public boolean checkPhone(FirebaseAuth firebaseAuth) {
        FirebaseUser currentFirebaseUser = firebaseAuth.getCurrentUser();
        String user_id = currentFirebaseUser.getUid();
        db.collection("users").document(user_id).get()
                .addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
                    @Override
                    public void onSuccess(DocumentSnapshot documentSnapshot) {
                        if(documentSnapshot.exists()) {
                            String user_phone = documentSnapshot.getString(KEY_PHONE);
                            Toast.makeText(MainActivity.this, "Phone Number: "+user_phone, Toast.LENGTH_SHORT).show();
                            if(!user_phone.equals("null")) {
                                Toast.makeText(MainActivity.this, "Phone is not null", Toast.LENGTH_SHORT).show();
                                status = true;
                            }
                        } else {
                            Toast.makeText(MainActivity.this, "User does not exist", Toast.LENGTH_SHORT).show();
                        }
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Toast.makeText(MainActivity.this, "Error: "+e.toString(), Toast.LENGTH_SHORT).show();
                    }
                });

        Toast.makeText(this, "Returning: "+status, Toast.LENGTH_SHORT).show();
        return status;
    }
}

Not to mention that the scenario is TRUE as the user is already there and has a Phone Number updated.

But the problem is that, when the checkUserAuthStatus(firebaseAuth); is called from onCreate() it directly returns FALSE first. The order of execution in the form of Toast is:

  1. Got Authentication (Executes firebaseAuth.getCurrentUser() != null as true)
  2. Returning False: Toast at the end of checkPhone(firebaseAuth) (JUMPS TO THE END OF checkPhone(firebaseAuth)!!!)
  3. Update Phone Number (Executes !checkPhone(firebaseAuth))
  4. Phone Number: xxxxxxxxxx (Goes back inside checkPhone(firebasAuth) as true)
  5. Phone is not null

I might be doing a rookie mistake somewhere or maybe not aware of some basic concepts. Any suggestions and implementations with the code would help

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
mustangDC
  • 945
  • 1
  • 12
  • 33
  • 2
    Firebase APIs are asynchronous and return immediately. The provided callbacks dont' block, and execute some time later when the request is done. – Doug Stevenson May 28 '20 at 19:44
  • 2
    Your `return status;` runs before the `status = true;` is called. You can't return data that is asynchronously loaded. All code that needs the data needs to be inside `onSuccess` or be called from there. See https://stackoverflow.com/questions/50434836/getcontactsfromfirebase-method-return-an-empty-list/50435519#50435519 and https://stackoverflow.com/questions/51000169/how-to-check-a-certain-data-already-exists-in-firestore-or-not/51002413#51002413 – Frank van Puffelen May 28 '20 at 19:52
  • 1
    @mustangDC The code inside `onSuccess(...)` and/or `onFailure(...)` runs some times **after** your `checkPhone(...)` method has already returned. That's what asynchronous means, and "listeners" are always asynchronous. – Andreas May 28 '20 at 19:56
  • Thanks for the trifle yet important concept – mustangDC May 28 '20 at 19:58

0 Answers0