Search code examples
androidauthenticationondestroy

Android handle onStop and onDestroy user behavor


I have a login user flow, user logins with Google+ or Facebook. Then in the next activity he choose gender and a nick name if its his first time in the app (Shared Preferences). When user press 'Go' button, he triggers the upload function:

public void uploadUserData() {
        FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
        if (firebaseUser != null) {

            final String userUid = firebaseUser.getUid();
            final String username = editUsername.getText().toString().trim();
            final String user_class = String.valueOf(class_spinner.getSelectedItem());
            final String user_gender = String.valueOf(gender_spinner.getSelectedItem());
            FirebaseDatabase database = FirebaseDatabase.getInstance();
            DatabaseReference users = database.getReference("Users");
            users.child(userUid).child("userName").setValue(username); 

After this, user dont see again this activity and his account has all the informations i need.

My problem is how to prevent user from exit app (onDestroy) without have press enter button. If he do it, i dont have the nickname and the next time he opens the app the activity he faces need the username. (Throws null exception obviously).

The flow: Welcome activity

if (!prefManager.isFirstTimeLaunch()) {
            launchHomeScreen();
            finish();
        }
private void launchHomeScreen() {
        startActivity(new Intent(WelcomeActivity.this, MainActivity.class));
        finish();
    }

In main activity:

@Override
            public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
                if (firebaseAuth.getCurrentUser() != null) {
                    FirebaseUserMetadata metadata = mAuth.getCurrentUser().getMetadata();
                    if (metadata.getCreationTimestamp() == metadata.getLastSignInTimestamp()) {
                        // The user is new, show them a fancy intro screen!
                        startActivity(new Intent(MainActivity.this, NewUserActivity.class));

                    } else {

                        if (prefManager.isFirstTimeLaunch()) {
                            // This is an existing user, show them a welcome back screen.
                            startActivity(new Intent(MainActivity.this, NewUserActivity.class));
                        }
                        else{
                            startActivity(new Intent(MainActivity.this, UserProfile.class));
                        }
                    }

                }

            }
        };

And in NewUserActivity:

btnEnterDungeons.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(!TextUtils.isEmpty(editUsername.getText().toString().trim())) {
                    uploadUserData();
                    Intent intent = new Intent();
                    intent.setClass(NewUserActivity.this, GameChooseActivity.class);
                    prefManager.setFirstTimeLaunch(false);
                    finishAffinity();
                    startActivity(intent);
                }

So if user destroy the NewUserActivity with no pressing the btnEnterDungeons the prefManager remains. But when the cycle starts again as use is already logged in with Google+ or Facebook... goes to NewUserActivity and throw exception for UserProfile.

End the error occurs in line 164 in UserProfile. That means it shows NewUserActivity but loads UserProfile too.

//Method to get data from Firebase user and show them in profile
    private void getData() {
        final Context mContext = UserProfile.this;
        FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
        String userid = user.getUid();
        final long joinedDate = user.getMetadata().getCreationTimestamp();
        final SimpleDateFormat sdf = new SimpleDateFormat("MMM dd,yyyy HH:mm");
        final Date resultdate = new Date(joinedDate);
        DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Users");
        reference.child(userid).addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                User user = dataSnapshot.getValue(User.class);
                userName.setText(user.getUserName());
                userClass.setText(user.getUser_class());
                imageURL = user.getAvatar();
                Picasso.with(mContext).load(imageURL).into(userAvatar);
                dateofJoin.setText((sdf.format(resultdate)));
                PvPWins.setText(String.valueOf(user.getPvP_Wins()));
                PvPScore.setText(String.valueOf(user.getPvP_scores()));
                userScore.setText(String.valueOf(totalScore));
                userGender.setText(user.getUser_gender());


            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
            }
        });

Solution

  • You can use the Shared Preferences to check if the user has completed the "Registration" task or not.

    So typically the process will look as follow:

    1. In your Launcher activity, might be your "SplashScreen" or the "Login" activity, you check the Shared Preferences and see if the value of processCompleted is true, by default the value is false
    2. If value is true , it means the user has already completed the process so you can launch the "Home" intent directly
    3. If the value is false, it means the user didn't complete the process, so you show the "Login" intent
    4. When the user clicks on "GO" it means he finished the process so you update the value of processCompleted in Shared Preference with true.
    5. Next time the user opens the app the processCompleted will be true and you will be sure that he actually gave all informations you need.

    Hope it helps.