I am working on one application in which i move from Activity A(Main Activity) to Activity B to Activity C.
All of this is working fine but the problem occurs when user killed the app by removing it from Task tray.
To understand my problem say user moved from A to B and then C but before finishing the task in activity C user killed the app.
so when user again opens the app by pressing App icon i want to start the last activity C where user was when he killed the app instead of android default behavior of starting(Main Activity A) a fresh instance of app again.
What i have tried:
1) I tried using "onSaveInstanceState" and "onRestoreInstanceState", but i think they are used when orientation is changed or we go back by pressing back button.
2) I tried to save everything in "onPause" as onpause calls 99.99% times when activity destroyed and by using static flags i opens the last activity and it worked for me but i want some good example or technique to this work.
so can anyone help me on achieving the same..??
I request fellow members to provide code examples.
thanks in advance.
Store the state in every Activity's #onPause().
So in every Activity you want:
#Override
protected void onPause() {
super.onPause();
SharedPreferences prefs = getSharedPreferences("RESTART", MODE_PRIVATE);
Editor editor = prefs.edit();
editor.putString("last_left", getClass().getName());
editor.commit();
}
And a Shell Activity which will be a Launcher, Main Activity:
public class Shell extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Class<?> classActivity;
try {
SharedPreferences prefs = getSharedPreferences("RESTART", MODE_PRIVATE);
classActivity = Class.forName(prefs.getString("last_left", getClass.getName()));
}
catch(ClassNotFoundException ex) {
classActivity = your_Activity1.class;
}
startActivity(new Intent(this, classActivity));
}
}
[Source Modified]
you can use SharedPreferences to store last user state.#onPause activity
SharedPreferences.Editor editor = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE).edit();
editor.putString("state", "A/B/C");
editor.commit();
OnResume Activity
SharedPreferences prefs = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE);
String stateApp = prefs.getString("state", null);
if (stateApp != null) {
switc(stateApp){
case 'A':
// Go TO A activity
break;
case 'B':
// Go TO B activity
break;
default:
// Go TO C activity
break;
}
}
The Intent that was used to launch the activity is saved by the system when the process is about to be killed.Once the user returns into the app which has been killed, then the app is restored and the same Intent (Activity A in your case) is fired to launch the activity including all the extras that it might have.
Go for SharedPrefrences:https://developer.android.com/reference/android/content/SharedPreferences.html
refer the official documentation.
Try to use sharedPreferences concept, save the activity name in sharedPreferences while the opening of that activity, then check the sharedPreferences value while reopening the application. I think you got it!
sample tutorial link:
https://developer.android.com/training/basics/data-storage/shared-preferences.html
Related
I've looked all over and can't seem to find an answer to my issue. For some reason the data saved in SharedPreferences reappears after switching activities. Why is my SharedPreferences still the exact same as it was before I cleared it and how can I fix this?
In first activity:
#Override
protected void onStop() {
super.onStop();
SharedPreferences sp = this.getSharedPreferences(TEMP_KEY, MODE_PRIVATE);
Gson gson = new Gson();
String objectJson = gson.toJson(object, Object.class);
String activityJson = "FirstActivity";
SharedPreferences.Editor editor = sp.edit();
editor.putString(CONTINUE_KEY, objectJson);
editor.putString(ACTIVITY_KEY, activityJson);
editor.apply();
}
public void onClickSave() {
Gson gson = new Gson();
String objectJson = gson.toJson(object);
SharedPreferences sp getSharedPreferences(SAVE_KEY, MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putString(object.getDate(), objectJson);
editor.apply();
SharedPreferences spTemp = this.getSharedPreferences(TEMP_KEY, MODE_PRIVATE);
spTemp.edit().clear().apply();
// go back to the main menu
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
}
Before the apply():
After the apply():
In Main Activity:
SharedPreferences sp = this.getSharedPreferences(TEMP_KEY, MODE_PRIVATE);
From main activity:
From Coordinating activities android documentation.
When one activity starts another, they both experience lifecycle
transitions. The first activity stops operating and enters the Paused
or Stopped state, while the other activity is created. In case these
activities share data saved to disc or elsewhere, it's important to
understand that the first activity is not completely stopped before
the second one is created. Rather, the process of starting the second
one overlaps with the process of stopping the first one.
The order of lifecycle callbacks is well defined, particularly when
the two activities are in the same process (app) and one is starting
the other. Here's the order of operations that occur when Activity A
starts Activity B:
Activity A's onPause() method executes.
Activity B's onCreate(), onStart(), and onResume() methods execute in sequence. (Activity B now has user focus.)
Then, if Activity A is no longer visible on screen, its onStop() method executes.
This predictable sequence of lifecycle callbacks allows you to manage
the transition of information from one activity to another.
Back to your case, when you start MainActivity from FirstActivity.
FirstActivity's onPause() method executes.
MainActivity's onCreate(), onStart(), and onResume() methods execute in sequence. (MainActivity now has user focus.)
Then, if FirstActivity is no longer visible on screen, its onStop() method executes.
When the code in onClickSave executes.
SharedPreferences spTemp = this.getSharedPreferences(TEMP_KEY, MODE_PRIVATE);
spTemp.edit().clear().apply();
At this time, TEMP_KEY prefs has been cleared. After MainActivity is visible on screen, FirstActivity will be no longer visible on screen, so its onStop() method executes.
SharedPreferences sp = this.getSharedPreferences(TEMP_KEY, MODE_PRIVATE);
Gson gson = new Gson();
String objectJson = gson.toJson(object, Object.class);
String activityJson = "FirstActivity";
SharedPreferences.Editor editor = sp.edit();
editor.putString(CONTINUE_KEY, objectJson);
editor.putString(ACTIVITY_KEY, activityJson);
editor.apply();
In this code you add two entries into TEMP_KEY prefs again. So when users click on a button in MainActivity, at that time the prefs size is 2 instead of 0 as you expected.
Why is my SharedPreferences still the exact same as it was before I
cleared it?
This is predictable or expected behavior in Android. You can put a log in onCreate(), onStart(), onResume() method of MainActivity, then you can see TEMP_KEY prefs size at that time is always 0.
How can I fix this?
Do not add new entries into TEMP_KEY in onStop(), you should add in onPause() instead.
Save To Shared Preferences
SharedPreferences sp = getSharedPreferences("test" , MODE_PRIVATE);
SharedPreferences.Editor spEditor = sp.edit();
spEditor.putString("hello1" , "hello11");
spEditor.putString("hello2" , "hello22");
spEditor.apply();
Clear From Shared Preferences
SharedPreferences sp1 = getSharedPreferences("test" , MODE_PRIVATE);
SharedPreferences.Editor spEditor1 = sp1.edit();
spEditor1.clear();
spEditor1.apply();
Get From Shared Preferences
SharedPreferences sp2 = getSharedPreferences("test" , MODE_PRIVATE);
String value = sp2.getString("hello1" ,"noting");
Log.i("test_sp" , " == == ==" +value);
First, you have different preference file name for getSharedPreferences(String name, int mode), in onStop() and onClickSave() methods:
// in onStop()
SharedPreferences sp = this.getSharedPreferences(TEMP_KEY, MODE_PRIVATE);
// in onClickSave()
SharedPreferences sp getSharedPreferences(SAVE_KEY, MODE_PRIVATE);
you need to use the same file name to access the same preference.
Second, onStop() is not always guaranteed to be called, so it's not a reliable method to save your preferences. Related answer: Is onStop() always preceded by onPause()
Third, always save the preference when you need to keep the value in it. Don't wait to save it later and hoping that you can depend on either onPause(), onStop(), or onDestroy(). Never assume that your application will gracely terminate by user or system.
I have developed an App where the user has to login into the app using the login Activity. After successful login, the app is directed to Activity B. The app doesn't provide any signout options.So next time when the user uses the app I want to hide the login Activity's layout. Is it possible to do so?If yes, how is it possible?
In LoginActivity do as Suggested by nr4bt but instead of int Put & get Boolean Value in SharedPreference.
write this code
SharedPreferences.Editor editor = getPreferences(MODE_PRIVATE).edit();
editor.putValue("loginStatus", true);
editor.commit();
& onCreate() of LoginActivity Write this code
SharedPreferences prefs = getPreferences(MODE_PRIVATE);
String restoredText = prefs.getBoolean("loginStatus", false);
if (restoredText == true) {
// start activity
finish(); // destroy login so user can't come back with back button
}
Hope this helps you.
Keep a variable in sharedpreferences and check it when your login activity starts
in LoginActivity, when the user press login button and if success,
SharedPreferences.Editor editor = getPreferences(MODE_PRIVATE).edit();
editor.putInt("loginStatus", 1);// removed ""
editor.commit();
Then in onCreate check the variable,
SharedPreferences prefs = getPreferences(MODE_PRIVATE);
int restoredText = prefs.getInt("loginStatus", 0);
if (restoredText == 1) {
// start activity
finish(); // destroy login so user can't come back with back button
}
It is quite simple to achive with SharedPreferences. You just save that user has loged in and later on start check if he already done it or not and act properly.
im new in developing Android Apps.
I know how to set the starting Activity with the AndroidManifest.xml, but i need a way to check something first before i choose the starting Activity.
My Problem:
I created a loginActivity and a mainActivity.
I want to do the following: If i log me in, i'll set a flag to 1 and at the next app start, i want show directly the mainActivity and not the login.
Is there any way to do that? I thought about creating a splashscreen where i can check if im logged in before showing the first Activity.
Thanks, Philip
Updated Code - working:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// get preferences
SharedPreferences userDetails = getApplicationContext().getSharedPreferences("userdetails", 0);
String savedEmail = userDetails.getString("email", "");
String savedPassword = userDetails.getString("password", "");
Boolean savedRemember = userDetails.getBoolean("remember", false);
Boolean savedLogged = userDetails.getBoolean("logged", false);
// check if already logged in
if(savedLogged) {
// start the overview
Intent intent = new Intent(this, ActivityOverview.class);
startActivity(intent);
finish();
}
else {
// initialize the form layout
setContentView(R.layout.activity_login);
// get views
this.email = (EditText)findViewById(R.id.editTextEmail);
this.password = (EditText)findViewById(R.id.editTextPassword);
this.remember = (CheckBox)findViewById(R.id.checkBoxRemember);
// set values to views
this.email.setText(savedEmail);
this.password.setText(savedPassword);
this.remember.setChecked(savedRemember);
}
}
I have something similar in one of my apps. I let the user chose weather it should auto-login or not. This is saved in the SharedPreferences.
When the app starts and in the mainpage, you should check - BEFORE the setContentView(R.layout.activity_login); and set finish(); after startActivity();
if(savedLogged) {
Intent intent = new Intent(this, ActivityOverview.class);
startActivity(intent);
finish();
}
setContentView(R.layout.activity_login);
You don't really need a splash screen.
When the user successfully logs into your app, set a boolean flag in SharedPreferences to true. Check if this flag is true in the login activity's onCreate() and if it is, use an Intent to launch the main activity.
You do not need to display your activity. Not sure what exactly your code flow is going to be but you can safely start i.e. with LoginActivity. in your onCreate() check if you are already logged (whatever it means for you) and if so instantly start MainActivity killing LoginActivity with finish().
Going with a splashscreen would be a good idea. Starting the loginActivity would show the login screen for a split second. This would be undesirable.
How can I reload SharedPreferences when I resume from one activity to another? If I resume, it is possible that user has changed the settings. Is it possible to reload SharedPreferences or do I need to refresh/reload activity. And if, then how?
There is no difference in how you get and set SharedPreferences normally and from doing so in onResume. What you will need to do in addition to getting the most recent preferences, is update any objects you have in the Activity that use preference values. This will ensure your Activity is working with the most recent values.
A simple example:
protected void onResume() {
super.onResume();
getPrefs();
//...Now update your objects with preference values
}
private void getPrefs() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
String myPref = prefs.getString("myPref", "");
}
In my android app the user can enter the text in the EditView and the click on a button which takes him to an other activity where he can select a contact ... and then press a button which
brings him back to the first activity...
now the problem is I need to pass the selected contact to the first activity and display it (which i have done it using a bundle) but i am unable to retain already entered text in the EditView... which i should do (but the text should be retained with out passing it through the the bundle and getting it back)
thanks :)
The text in a view component is automagically saved by the OS, even after a soft kill (user changed phone orientation), but not after a hard kill, the user hit the back button while the parent activity was in focus. So, unless you are doing something non-standard, such as calling onSaveInstanceState without calling super.onSaveInstanceState, the data in the view state should persist.
One solution would be to save the text in the view component as a non view instance property before you launch the child activity, and just read this value back when the focus returns to the parent activity in the method onActivityResult.
JAL
EDIT: The Android Docs Activity page has been extensively updated. View state will not be saved if the widget does not have an ID.
EDIT: What I am saying is that the view state should be persisted by the OS. You should not need to save the view state manually. On a hard kill, you would need to save the state of your activity IF that is the expected behavior of the activity. So here is some code that saves the activity state. Given an instance variable:
String password;
Here we save state on a soft kill:
protected void onSaveInstanceState(Bundle outState){
password= editTextPassword.getText().toString();
outState.putString("password", password);
super.onSaveInstanceState(outState); // save view state
}
Here we save state on a hard kill
#Override
protected void onStop(){
super.onStop();
SharedPreferences prefs = getPreferences(MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putString("password",password);
editor.commit();
Here we restore state in onCreate(Bundle savedInstanceState):
if( savedInstanceState!= null){ // get saved state from soft kill after first pass
try {
password= savedInstanceState.getString("password");
Log.d(TAG,"RestoredState!");
}
catch(Exception e){
Log.d(TAG,"FailedToRestoreState",e);
}
}
else { // get saved state from preferences on first pass
SharedPreferences prefs = getPreferences(MODE_PRIVATE); // singleton
if (prefs != null){
this.password= prefs.getString("password","");
Log.d(TAG,"gettingPrefs");
}
}
Log.d(TAG,"onCreate");
Also given the fact that IF onSaveInstanceState is called it will be called before onStop, it is possible to use the flags isSavedInstanceState and isSavedPreferences to write to prefs ONLY on a hard kill if you reset the flags in onResume as:
protected void onResume() {
super.onResume();
Log.d(TAG,"onResume");
isSavedInstanceState= false;
isSavedPrefs= false;
}
Setting the flags in onCreate will not result in the desired outcome.