Search code examples
androidandroid-fragmentsandroid-activityauthorizationretrofit

Can not perform this action after onSaveInstanceState - android


I have an authorization app. In that app user have accessToken and refreshToken. I done something like this, that if user login on other hardware than in real hardware he logs out automatically. Imagine I have phone1 where I logged in. And now I'm logging in phone2. When I authorize my tokens changes. So I check in phone1 if tokens are changed than logout automatically. But sometimes after that logout I'm getting error like this Exception :

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState.

Here is where I'm log out when tokens are expired. Note that is a

Call<RefreshTokenActivation> newToken = apiClient.newToken(supportObjToken);
        newToken.enqueue(new Callback<RefreshTokenActivation>() {
            @Override
            public void onResponse(Call<RefreshTokenActivation> call, Response<RefreshTokenActivation> response) {
                if (response.isSuccessful()) {

            } else {
                if (response.code() == 401) {

                    //Perform this call if refresh token is expired

                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            Activity activity = (Activity) context;
                            MainActivity mainActivity = (MainActivity) activity;
                            mainActivity.logOut();
                        }
                    }, 1000);
                }
            }
        }

If response is 401, that means that my tokens are expired.If tokens are expired, after a second I throw my user to mainActivity.

Here is the code in MainActivity :

public class MainActivity extends AppCompatActivity
    implements FragmentChangeListener, TabLayoutLocationInterface {
private ConnectionDetector connectionDetector;
private SlidePageTabsMainFragment slidePageTabsMainFragment;
private MainFragment mainFragment;
private RelativeLayout logOut;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    SharedPreferencesManager.init(this);

    setContentView(R.layout.activity_main);

    logOut = (RelativeLayout) findViewById(R.id.list6);
    connectionDetector = new ConnectionDetector(this);
    slidePageTabsMainFragment = new SlidePageTabsMainFragment();
    mainFragment = new MainFragment();

    connectionEnable();
    userLogOut();
}

public void connectionEnable() {
    if (!connectionDetector.isConnected()) {
        Toast.makeText(this, "Please check your Internet", Toast.LENGTH_LONG).show();
    } else {
        Boolean loggedIn = SharedPreferencesManager.getInstance().getUserLogged();
        if (loggedIn) {
            this.replaceFragment(slidePageTabsMainFragment, true);
        } else {
            this.replaceFragment(mainFragment, true);
        }
    }
}

@Override
public void replaceFragment(BaseFragment fragment, Boolean isAddToBackStack) {
    String backStateName = fragment.getFragmentName();
    FragmentManager manager = getSupportFragmentManager();

    FragmentTransaction transaction = manager.beginTransaction();
    transaction.replace(R.id.main_fragment_container, fragment, backStateName);
    transaction.addToBackStack(backStateName);
    transaction.commit();
}

@Override
public int getTabLayoutLocation() {
    SlidePageTabsMainFragment slidePageTabsMainFragment = (SlidePageTabsMainFragment)
            getSupportFragmentManager().findFragmentByTag("SlidePageTabsMainFragment");
    if (slidePageTabsMainFragment == null) {
        return 0;
    }
    return slidePageTabsMainFragment.getTabLayoutLocation();
}

//If user click logOut button
public void userLogOut() {
    logOut.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            SharedPreferencesManager.getInstance().setUserLogin(false);
            SharedPreferencesManager.getInstance().removeUser();
            getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
            replaceFragment(mainFragment, false);
        }
    });
}


//A function for automatic logOut
public void logOut() {
    SharedPreferencesManager.getInstance().setUserLogin(false);
    replaceFragment(new MainFragment(), false);
    getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
    recreate();
    SharedPreferencesManager.getInstance().removeUser();
}

@Override
protected void onResume() {
    super.onResume();
    Log.d("Test", "Text");
}

}

I think there is no something hard. So I getting this exception in transaction.commit(); line in replaceFragment() method in MainActivity. In that call you see I'm calling mainActivity.logOut(); and you see in MainActivity the logOut function.

//A function for automatic logOut
public void logOut() {
    SharedPreferencesManager.getInstance().setUserLogin(false);
    replaceFragment(new MainFragment(), false);
    getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
    recreate();
}

So in this method I change the SharedPreferences value (that I need for checking on application open does user logged in or not?). After that I'm replacing fragment into mainFragment(that's the base fragment and yes I working on fragments). After that I pop all fragments because after logout if I will click back button, it will go back, so after popping I recreate the app. After recreates it feels like app opened first time. Ok so why it throws exception like this? Any idea?


Solution

  • Used transaction.commitAllowingStateLoss(); instead of transaction.commit();

    If you do this than your final state in not allow saved but it is ok if you don't care

    For more clarification about commit() and commitAllowingStateLoss() read this blog.