Search code examples
javaandroidstaticencapsulation

How to handle a user session for android app


I am creating an application where a user can log in using their login details. Once the user is verified, the users data will download from a web-server into a class called User. The User class holds user information such as their name, age, birthday, username, email, etc. The User class will only be instantiated once per application life-cycle. Previously, I was instantiating the User class into a public static variable so I could easily access it from every other activity and class, but as this is poor practice because of the lack of encapsulation, I need help figuring out how to handle the User class.

Thanks

Edit: This is my code for logging in:

private class LoginTask extends AsyncTask<String, JSONObject, Boolean> {
            private String email, password;
            private ProgressBar progressBar;
            public LoginTask(ProgressBar progressBar, String email, String password) {
                this.progressBar = progressBar;
                this.email = email;
                this.password = password;
            }

            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                progressBar.setVisibility(View.VISIBLE);
            }

            private HttpURLConnection loginConnection(String email, String encPass)
            {
                return Connection.getConnection(Links.LOGIN_SCRIPT, "email=" + email + "&password=" + encPass);
            }

            private HttpURLConnection saltConnection(String email) {
                return Connection.getConnection(Links.GET_SALT, "request_salt=set&request_email=" + email);
            }

            private HttpURLConnection existsConnection(String email) {
                return Connection.getConnection(Links.USER_EXISTS + "?email=" + email);
            }

            @Override
            protected Boolean doInBackground(String... info) {
                try {
                    String existString = Connection.getStringFromConnection(existsConnection(email));
                    int existInt = Integer.parseInt(existString);
                    if (existInt == Connection.SUCCESS) {
                        String saltString = Connection.getStringFromConnection(saltConnection(email));
                        JSONObject saltJson = new JSONObject(saltString);
                        String salt = saltJson.getString("salt"); //Perfect
                        if (salt.length() > 0) {
                            String encPass = Utils.SHA256(password + salt);
                            JSONObject encPassObj = new JSONObject();
                            encPassObj.put("email", email);
                            encPassObj.put("encPass", encPass);
                            publishProgress(encPassObj);
                            if (encPass.length() > 0) {
                                String loginString = Connection.getStringFromConnection(loginConnection(email, encPass));
                                int logInt = Integer.parseInt(loginString);
                                if (logInt == Connection.SUCCESS) {
                                    //Globals.user = new User(email, encPass);
                                    return true;
                                } else {
                                    return false;
                                }
                            }
                        }
                    }
                }  catch (JSONException e) {
                    e.printStackTrace();
                }
                return false;
            }

            @Override
            protected void onProgressUpdate(JSONObject... values) {
                super.onProgressUpdate(values);
                try {
                    JSONObject object = values[0];
                    setEmail(object.getString("email"));
                    setPassword(object.getString("encPass"));
                    preferences.saveLoginDetails(object.getString("email"), object.getString("encPass"));
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
            //UI
            @Override
            protected void onPostExecute(Boolean result) {
                super.onPostExecute(result);
                progressBar.setVisibility(View.INVISIBLE);
            }
        }

The LoginTask will return a true or false value based on a successful login, and the email and encrypted password will be used to create a new user in the Global class.

Example:

public class Global {
    public static User user = new User(email, password);
}

My only issue here is encapsulation of the user class. How can I improve it?


Solution

  • If you only have one user, then you need to set your class as a singleton class. That way you know that there will only be one instance of that class, and that every activity accessing it will be using the same object.

    Look at this question: Creating an Object accessible by all Activites in Android

    So lets say that we create a Singleton class like so:

    public class SessionUser {
        private static SessionUser instance = null;
        protected SessionUser() {
          // Exists only to defeat instantiation.
        }
    
        public static SessionUser getInstance() {
            if(instance == null) {
                instance = new SessionUser();
             }
             return instance;
        }
    
        private boolean isUserInSession()
        {
            //validation code
            return isInSession;
        }
    }
    

    And you use it in any class like this:

    //Some code
    if (!SessionUser.getInstance().isUserInSession())
    {
        //Go to login
    }
    //More code