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?
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.