1

I'm using Firebase Authentication to sign up a user with a phone number and link that user with the email and password that he provides and if the authentication is successful the email and password should be saved in SharedPreferences and then the app should go to the maps activity, otherwise show a toast message.

When the maps activity starts it first checks some values in the shared preference, if these values exist the map will show up, otherwise, another activity should start.

this process is working very well but the problem is that the maps activity starts before shared preference commits the changes, and as the result maps activity will start another activity because it didn't find the values that are supposed to be saved from the registration activity.

the maps activity is the start point of the app, if you completed the sign-up process and restart the app again, then maps activity will check for these values and then show the map and that's what makes me say that committing the changes is very slow.

so the question is how to make sure that shared preferences committed the changes before moving to maps activity as the maps activity will check for them before showing the map

signInButton.setOnClickListener(v -> {
        if (validateFields())
            if (checkInternet()){
                makeHttpRequest();
                firebaseSignUp();
            }
    });

public boolean validateFields() {
    email = emailEditText.getText().toString().trim();
    password = passwordEditText.getText().toString().trim();
    nurseID = nurseIDEditText.getText().toString().trim();
    if (TextUtils.isEmpty(email)) {
        emailEditText.setError(getResources().getString(R.string.empty_field));
        emailEditText.requestFocus();
        return false;
    }
    else if (TextUtils.isEmpty(password)) {
        passwordEditText.setError(getResources().getString(R.string.empty_field));
        passwordEditText.requestFocus();
        return false;
    }
    else if (TextUtils.isEmpty(nurseID)) {
        nurseIDEditText.setError(getResources().getString(R.string.empty_field));
        nurseIDEditText.requestFocus();
        return false;
    }
    else
        return true;
}

public boolean checkInternet() {
    ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
    try {
        if (networkInfo != null && networkInfo.isConnected())
            return true;
        else
            Toast.makeText(this, R.string.check_connection, Toast.LENGTH_LONG).show();
    } catch (NullPointerException e) {
        Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
    }
    return false;
}

public void makeHttpRequest() {
    StringRequest stringRequest = new StringRequest(Request.Method.POST, NewNurseActivity.url,
            response -> {
                if (parseHtml(response)) {
                    progressBar.setVisibility(View.GONE);
                }
                else {
                    progressBar.setVisibility(View.GONE);
                    notAMemberTextView.setVisibility(View.VISIBLE);
                    notAMemberTextView.setText(R.string.you_are_not_a_member);
                }
            }, error -> {
        parseHtml("response"); //remove this line when app comes to live
        linearLayout.setVisibility(View.GONE);
        notAMemberTextView.setVisibility(View.VISIBLE);
        notAMemberTextView.setText(R.string.unexpected_response_code);
        progressBar.setVisibility(View.GONE);
    }) {
        @Override
        protected Map<String, String> getParams() {
            Map params = new HashMap();
            params.put("member_code", nurseID);
            return params;
        }
    };
    int socketTimeOut = 10000;
    RetryPolicy retryPolicy = new DefaultRetryPolicy(socketTimeOut,
            0, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
    stringRequest.setRetryPolicy(retryPolicy);
    RequestQueue queue = Volley.newRequestQueue(this);
    queue.add(stringRequest);
}

public boolean parseHtml(String response) {
        String nurseName = "ahmed";
        editor.putString("name", nurseName);
        editor.putString("nurseId", nurseID);
        editor.commit();
        return true;
}

public void firebaseSignUp() {
    AuthCredential credential = EmailAuthProvider.getCredential(email, password);
    try {
        Objects.requireNonNull(firebaseAuth.getCurrentUser()).linkWithCredential(credential).
                addOnSuccessListener(authResult -> {
                    editor.putString("email", email);
                    editor.putString("password", password);
                    editor.apply(); //here I tried editor.commit() but also didn't work 
                    startActivity(new Intent(NewNurseActivity.this, MapsActivity.class));
                    finish();
                }).addOnFailureListener(e -> {
            Log.e("sign_in_error", e.getMessage());
            Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
        });
    }
    catch (NullPointerException ignored){}
}

And here's how I'm checking for my values:

nurseId = PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("nurseId", "");
    name = PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("name", "");
    email = PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("email", "");
    password = PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("password", "");
    if (name.equals("") || nurseId.equals("") || email.equals("") || password.equals("")) {

        startActivity(new Intent(this, WelcomeActivity.class));
        finish();
    }
Ahmed Gamal
  • 55
  • 1
  • 10
  • If MapsActivity is starting point where do you do firebase signup? – Jake Nov 19 '21 at 23:13
  • If you are sure that sharedPreferences saves your data after starting a new activity you can replace apply with commit. Commit returns boolean indicating if you successfully saved your data. At this point you can solve your problem with regular if(isMyDataSaved) goMapsActivity else anotherActivity. – Jake Nov 19 '21 at 23:23
  • `editor.commit()` will write immediately, but `editor.apply()` will also immediately save the values in the SharedPreferences in-memory storage even if the disk write is delayed. It is almost certain that your issue is somewhere else (either something about how the map activity retrives the values, or using a different shared pref between the two activities, or something else). You never show how you define `editor`, or if it is the same in the Maps activity. – Tyler V Nov 20 '21 at 03:07
  • This is going to block the main thread but put a thread sleep right before the `startActivity` for 1000 milliseconds, if `SharedPreferences` still doesn't pull the updated data on the other side then its not just slow but broken. – avalerio Nov 20 '21 at 05:32
  • @JeenbekKhydyr MapsActivity starts by checking for those values if they exist the map will show up else nurse registration activity will show up – Ahmed Gamal Nov 21 '21 at 11:35

1 Answers1

1

That's not a common approach to store the email and password in SharedPreferences to actually know when the user is authenticated. The simplest solution would be to use a listener as explained in my answer from the following code:

In this way, you can redirect the user to the LoginActivity if it is not logged in, or to the MapActivity otherwise.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Hey @AlexMamo, I tried your answer but unfortunately that didn't help and I'm getting the same results, I know that this is not a common approach to store email and password but this is for testing prupose. I will update my question to let you know how the checking prupose goes. – Ahmed Gamal Nov 21 '21 at 11:25
  • I don't know how you get the same behavior, as the listener fires only when the auth state has changed. Ok, keep me posted. – Alex Mamo Nov 21 '21 at 11:51