0

When a user registers in my Android app, their data is stored inside a collection, where the document ID is their email address which helps find a user. The password is stored inside the document as well.

So when a user logins, their entered email is checked against a document ID matching that email, if it exists it will log in and display user control panel.

Now after the login, I need to somehow create a user session, so that the user can never go back to the login screen until he logouts. In case the app crashes or lost network connection, a saved user session would be very useful.

Here's my code for the login activity:

import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Patterns;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import com.basgeekball.awesomevalidation.AwesomeValidation;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.firestore.CollectionReference;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import static com.basgeekball.awesomevalidation.ValidationStyle.BASIC;

public class SLogin extends AppCompatActivity
{
public static final String STUDENT_EMAIL = "student_email";
private EditText tEmail;
private EditText tPassword;
private String email = "";

private FirebaseFirestore db = FirebaseFirestore.getInstance();
private CollectionReference dbUsers;

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

    tEmail= findViewById(R.id.Email);
    tEmail.addTextChangedListener(new TextWatcher()
    {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after)
        {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count)
        {
            email = s.toString();
        }

        @Override
        public void afterTextChanged(Editable s)
        {

        }
    });
    tPassword=findViewById(R.id.Password);

    // Here you simply set saveEmail to empty string because at this moment when activity is
    // created (onCreate) tEmail field is empty. To update this field dynamically you need set
    // addTextChangedListener on tEmail.
    // saveEmail=tEmail.getText().toString();

    dbUsers = db.collection("Students");
}

//Validation Method
private boolean validate()
{
    AwesomeValidation mAwesomeValidation = new AwesomeValidation(BASIC);
    mAwesomeValidation.addValidation(tEmail, Patterns.EMAIL_ADDRESS, "Invalid Email Address");
    String regexPassword = "(?=.*[a-z])(?=.*[A-Z])(?=.*[\\d])(?=.*[~`!@#\\$%\\^&\\*\\(\\)\\-_\\+=\\{\\}\\[\\]\\|\\;:\"<>,./\\?]).{6,}";
    mAwesomeValidation.addValidation(tPassword, regexPassword, "Use 6 or more characters with a mix of upper & lower letters, numbers & symbols");
    return mAwesomeValidation.validate();
}

//Method to check password matching or not
private void passCheck(@NonNull DocumentSnapshot snapshot)
{
    final String uPass = tPassword.getText().toString();
    final String storedPass = snapshot.getString("password");
    if (storedPass != null && storedPass.equals(uPass))
    {
        Intent intent = new Intent(SLogin.this, StudentCP.class);
        intent.putExtra(STUDENT_EMAIL, email);
        startActivity(intent);
    }
    else
    {
        Toast.makeText(SLogin.this, "Invalid Password!", Toast.LENGTH_LONG).show();
    }
}

public void sLogin(View v)
{
    if (validate())
    {
        DocumentReference dbDocs = dbUsers.document(email);
        dbDocs.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>()
        {
            @Override
            public void onComplete(@NonNull Task<DocumentSnapshot> task)
            {
                if (task.isSuccessful())
                {
                    DocumentSnapshot document = task.getResult();
                    if (document != null && document.exists())
                    {
                        //Toast.makeText(SLogin.this, "You are registered", Toast.LENGTH_LONG).show();

                        // Improved password checking because at first glance I
                        // don't see why you call db fetch again to get document
                        // because if we are here that means we got matching data
                        // and now we only need to check if password match. No need
                        // to call get on db again.
                        //
                        // It's possible to even more optimize calls to DB in case
                        // of wrongly typed password. We can cache input email and
                        // returned password for that email so in case if user
                        // doesn't change email, but types only password again we
                        // can compare newly typed password with cached password
                        // from previous request so we don't make again new DB
                        // request to simply get again same saved password.
                        //
                        // Currently I haven't implemented caching. It's only idea
                        // to think about in future.
                        passCheck(document);
                    }
                    else
                    {
                        Toast.makeText(SLogin.this, "You are not registered", Toast.LENGTH_LONG).show();
                    }
                }
                else
                {
                    Toast.makeText(SLogin.this, "Unable to connect to database", Toast.LENGTH_LONG).show();
                }
            }
        });
    }
}
public void nUser(View v)
{
    Intent intent = new Intent(SLogin.this, RegisterActivity.class);
    startActivity(intent);
}
}

1 Answers1

0

For best practice add the following class

public class PrefUtilities {

private SharedPreferences preferences;
Context context;


private PrefUtilities(Context context) {
    preferences = PreferenceManager.getDefaultSharedPreferences(context);
    this.context = context;
}


public static PrefUtilities with(Context context){
    return new PrefUtilities(context);
}


public void setUserLogin(boolean isUserLogedin){

    preferences.edit().putBoolean(context.getString(R.string.pref_key_user_status),isUserLogedin).apply();

}

public boolean isUserLogedin(){
    return preferences.getBoolean(context.getString(R.string.pref_key_user_status),false);
}


}

check for login status inside onCreate method

if(PrefUtilities.with(this).isUserLogedin()){

   Intent intent = new Intent(SLogin.this, StudentCP.class);
        intent.putExtra(STUDENT_EMAIL, email);
        startActivity(intent);
}

Save login status inside passCheck method

private void passCheck(@NonNull DocumentSnapshot snapshot)
{
    final String uPass = tPassword.getText().toString();
    final String storedPass = snapshot.getString("password");
    if (storedPass != null && storedPass.equals(uPass))
    {

         PrefUtilities.with(this).setUserLogin(true);       

        Intent intent = new Intent(SLogin.this, StudentCP.class);
        intent.putExtra(STUDENT_EMAIL, email);
        startActivity(intent);
    }
    else
    {
        Toast.makeText(SLogin.this, "Invalid Password!", Toast.LENGTH_LONG).show();
    }
}

When user logout use bellow method to change SharedPreferences

PrefUtilities.with(this).setUserLogin(false);

You can also add other methods in PrefUtilities class saving user Email

Vamsi Smart
  • 928
  • 9
  • 16
  • Hi, I get an error message inside PrefUtilities class, Cannot resolve symbol "pref_key_user_status" –  Mar 26 '19 at 07:37
  • @DarkNate declare pref_key_user_status inside strings.xml file or replace context.getString(R.string.pref_key_user_status) with "pref_key_user_status" – Vamsi Smart Mar 26 '19 at 07:47
  • Hey how do I store that "email" variable on local storage? Because it gets cleared after the app is closed and restarted, any ideas? It's bascially an ID for identifying users in the app and to read data back from the database. –  Mar 26 '19 at 09:57
  • 1
    @DarkNate add those two methods in PrefUtilities public void saveUserEmail(String userEmai){ preferences.edit().putString(context.getString(R.string.pref_key_user_email),userEmail).apply(); } public String getUserEmail(){ return preferences.getString(context.getString(R.string.pref_key_user_email),""); } And use same way as saving login status. If answer is useful consider accepting answer – Vamsi Smart Mar 26 '19 at 11:01
  • It's working and your answer is accepted. Thanks for the help. –  Mar 26 '19 at 11:18