Issue in using onStop() and onResume() - android

I am using onStop() to save a boolean value which I need when the activity resumes.
Here is my code:
#Override
protected void onStop()
{
super.onStop();
Bundle bundle = new Bundle();
bundle.putBoolean("value",value);
getIntent().putExtras(bundle);
}
#Override
protected void onResume()
{
super.onResume();
if(getIntent().getExtras() != null)
{
Bundle bundle = getIntent().getExtras();
value = bundle.getBoolean("value");
}
}
My issue is no matter what the value of the boolean is, my onResume() always retrieves it as FALSE. This issue only occurs if I leave my activity using the BACK button. If I press home, things seem to work fine(i.e if the boolean was TRUE then onResume() retrieves it as TRUE.
Please do help me because I don't understand why onResume() always gets the value of the boolean as FALSE even when I save it as TRUE in onStop().
I also tried onRestart(), onPause() and onBackPressed() but I still can't get the proper boolean value to be saved.

You have two issues here.
the correct way to save values during activity destruction is to use onSaveInstanceState(Bundle) and get the value from the Bundle passed to onCreate(Bundle).
Check example below:
public class SavedInstanceExample extends AppCompatActivity {
private boolean myBoolean;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_savded_instace_example);
if (savedInstanceState != null) {
myBoolean = savedInstanceState.getBoolean("key");
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("key", myBoolean);
}
}
When you press the back button the activity will be finished. That means completely gone. And values saved one the methods explained above will not be there.
The way to save something to survive the Activity being finished is to save it to the disk. One common/simple way to do it is using the SharedPreferences

When the Android application opens the following activity lifecycle methods will be called.
onCreate();
onStart();
onResume();
and when you press the back button, the application will be destroyed by calling following methods
onPause();
onStop();
onDestroy();
And in the second case when you press home button the following methods will be called
onPause();
onStop();
That means your application is not destroyed completely and you can open it from recent apps so that the activity re-appears by calling
onStart();
onStop();
That is why your code works in this case.
Activity gives onSavedInstanceState() method to save your data during configuration changes or something else.
Here is the link for Android documentation for
Activity

I would suggest you to read the Google Developers Link for Activity documentation.Google Developers Activity

The OP's code is basically right. onSavedInstanceState is no good if you are not destroying the activity but, for example, replacing a fragment in an activity with another fragment and then returning to it, in which case you have to use onStop and onResume as follows. This is Kotlin and it works but the principle is the same.
override fun onStop() {
super.onStop()
val bundle = Bundle()
bundle.putBoolean("BOOL", false)
activity?.intent?.putExtras(bundle)
}
override fun onResume() {
super.onResume()
if (activity?.intent?.extras != null) {
val bundle = activity?.intent?.extras
val bool = bundle?.getBoolean("BOOL")
println("BOOL is $bool")
}
}
My Java's a bit rusty but I suspect the OP's problem might have been that he mixed up boolean and Boolean?

Related

Restarting app without worrying about onSaveInstanceState

How do I simply just restart my ENTIRE app instead of trying to worry about saving the instance perfectly in onSaveInstanceState and reinitializing everything perfectly when resumed/restored in onRestoreInstanceState? (this can quickly become error prone)
UPDATE 10.1.16
I chose to do this in onCreate since onRestoreInstanceState behaves oddly sometimes.
This method is based on the fact that the onCreate(Bundle) is null unless the activity is being revived in which case it is whatever onSaveInstanceState(Bundle) set it to.
I set TWO flags. One in onSaveInstanceState in the Bundle so to know that it is a valid Bundle set by me. The other in the class itself to determine if onCreate was called because of recreation or rotation. And so in onCreate I checked to see if onSaveInstanceState is not null, check the Bundle flag, and check bInit (which defaults to false). If both flags are true then it means android dumped and destroyed our apps memory and the safest way to ensure everything is initialized again in a linear-style application is to just restart it and launch the beginning activity.
public class SomeMiddleActivity extends AppCompatActivity
{
private static boolean bInit = false; // only way it will be false again is if android cleared our memory and we are recreating
#Override
public void onSaveInstanceState(Bundle state)
{
// set a flag so that onCreate knows this is valid
state.putBoolean("StateSaved", true);
super.onSaveInstanceState(state);
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
// this must be called first always for some reason
super.onCreate(savedInstanceState);
if (savedInstanceState != null)
{
if (savedInstanceState.getBoolean("StateSaved", false) && !bInit)
{
// we were recreated... start app over
Intent intent = new Intent(getApplicationContext(), Startup.class);
startActivity(intent);
finish();
return;
}
}
bInit = true; // this will stay true until android has cleared our memory
.......
}
Hope this helps someone and although this has worked thus far, if anyone has a different suggestion let me know.
And FYI: the onSaveInstanceState(Bundle, PersistableBundle) version of onSaveInstanceState is never called ever so I dont know why they even implement it. (?)
REFERENCES:
ACCORDING TO ANDROID DOCUMENTATION
onCreate
Bundle: If the activity is being re-initialized after previously being shut down then this Bundle contains the data it most recently supplied in onSaveInstanceState(Bundle). Note: Otherwise it is null.
Try implementing this way
private final String IS_RE_CREATED = "is_re_created";
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putBoolean(IS_RE_CREATED, true);
super.onSaveInstanceState(outState);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (savedInstanceState.containsKey(IS_RE_CREATED)) {
boolean isRecreated = savedInstanceState.getBoolean(IS_RE_CREATED, false);
if (isRecreated) restartApplication(this);
}
}
public void restartApplication(Context context) {
String packageName = context.getPackageName();
PackageManager packageManager = context.getPackageManager();
// Intent to start launcher activity and closing all previous ones
Intent restartIntent = packageManager.getLaunchIntentForPackage(packageName);
restartIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
restartIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(restartIntent);
// Kill Current Process
Process.killProcess(Process.myPid());
System.exit(0);
}
Note: It is not a recommended to forcefully restart application.
How do I simply just restart my app instead of trying to worry about saving the instance
You mean the current activity? Do nothing (Don't implement onSaveInstanceState and onRestoreInstanceState).
The activity gets created automatically when changes happen. If there is no saved instance state, the activity won't restore any data.
Edit:
I think I came across similar issue too few weeks earlier, where I've to kill all the activities in the back stack and open a fresh new activity.
// Start Main Activity
Intent intent = new Intent(this, MainActivity.class);
finishAffinity();
startActivity(intent);
Use finishAffinity(). This works on > API 16.
When you kill all the activities in the back stack and open the main activity, it is kind of similar to restarting your app.

Android Save Instance State

I have created two activities A and B. In the Activity A, using onSaveInstanceState method I am saving bundle value ex(outState.putString("selectSaveDate", this.CalSelectedDate)) and going to the Activity B. When I hit back button to the Activity A , In the oncreate method the bundle value is null. I am unable to get my saved value in the oncreate method.
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.clear();
Log.i("bundleSave", "tester1" + this.CalSelectedDate);
outState.putString("selectSaveDate", this.CalSelectedDate);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState != null){
Log.i("todolist", "dsa" + savedInstanceState.getString("selectSaveDate"));
}
}
You only store data in a bundle in the OnSaveInstanceState method to persist data when your activity is destroyed and re-created (such as when rotating the screen or when the android os may decide to kill your activity if it is low on resources). When you launch activity B on top of your currently executing activity A, A is put in to a stopped state (therefore, your A activity is not destroyed). Also, when you come back from onStop, the next method that is called is onStart() (technically onRestart() is called be before onStart() but I find that callback is rarely ever implemented.
In conclusion, if your trying to keep persist data between launching an activity on top of your currently executing activity, you can just store that data in instance variables for that activity. If your trying to persist data between app launches then your going to want to look into storing data in Android's built in sqllite database or Android's SharedPreferences.
You should also obtain a real good understanding of the Activity lifecycle (its tricky but needed to code successfully in android):
http://developer.android.com/training/basics/activity-lifecycle/index.html
please try to Override onSaveInstanceState(Bundle savedInstanceState) and write the application state values you want to change to the Bundle parameter like this:
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
// Save UI state changes to the savedInstanceState.
// This bundle will be passed to onCreate if the process is
// killed and restarted.
savedInstanceState.putDouble("myDouble", 1.9);
savedInstanceState.putInt("MyInt", 1);
savedInstanceState.putString("MyString", "How are you");
// etc.
}
it will get passed in to onCreate and also onRestoreInstanceState where you'd extract the values like this:
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Restore UI state from the savedInstanceState.
// This bundle has also been passed to onCreate.
double myDouble = savedInstanceState.getDouble("myDouble");
int myInt = savedInstanceState.getInt("MyInt");
String myString = savedInstanceState.getString("MyString");
}
or follow activity life cycle for better understanding.

Deleting values when the user closes the application

So in my application I am using SharedPreferences to save fragment state. But I would like to delete those entries inside the SharedPreferences once the user steps outside of the application. I tried the following:
In my main class:
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
if(isFinishing() == true)
{
SM.removePreferences();
}
}
where SM is an instance of a helper class I created. removerPreferences does the following:
public void removePreferences(){
editor.clear();
editor.commit();
}
But I noticed that this was never executed. With the log, I did see that the app goes inside the isFinishing() if statement, but the method is never executed. I also did try the onDestroy(), but the method never got called.
Can someone help me on this ?
use onstop override to do that
like this:
#Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
if(isFinishing() == true)
{
SM.removePreferences();
}
}
Don't save your Fragment's instance state in SharedPreferences, but in the Bundle that is meant to do that. You can access it like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if ((savedInstanceState != null) {
// get your values, for example:
mID = savedInstanceState.getInt("ID");
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// put your values, for example:
outState.putInt("ID", mID);
}
This way you don't have to manage the values yourself.
If you have custom Objects, you can make them implement Parcelable.
In contrast, SharedPreferences are meant to save values that should persist even after the application closes, i.e.: preferences.
The better location to do that is onDestroy() without the if statement.
however, you can read from Android documentation about onDestroy() that:
There are situations where the system will simply kill the activity's hosting process without calling this method (or any others) in it, so it should not be used to do things that are intended to remain around after the process goes away.
So, in my opinion, if you don't want data remains after activity ends, you should use a class to hold it.
I think that what you're looking for can be achieved using onSaveInstanceState mechanism.
Nonetheless, I'll try answering your specific question while assuming that by saying that "the method is never implemented" you mean that the if statement value is always false and that your method doesn't get called.
isFinishing() returns true only when you called finish() on the Activity or if someone else has requested that it will be finished.
If you just click on the home button, you will get isFinishing() == false, thus your method doesn't gets called. So make sure you're actually finishing the Activity and not just pausing it.
Anyways, the best way to find out what's the problem is to use the debugger.

onResume() is not called in physical device instead onCreate() is called

Iam little bit amazed with this.I have an onResume() in my activity.Its called and works well in my emulator, but in a physical device samsung galaxy note for specific with jellybean installed,its not called.Instead onCreate() is called all the time.Why this happens?
public void onResume(){
super.onResume();
if(firsttime){
try {
Toast.makeText(getApplicationContext(), "Resuming Activity",Toast.LENGTH_LONG).show();
addReminder();
} catch(Exception exception) {
exception.printStackTrace();
}
} else {
firsttime=true;
}
}
This is my code.firsttime is a static boolean variable.It is used to prevent onResume() being called when app is started for the first time
Considering your current scenario, you should save variable in preferences instead of relying on activities lifecycle since lifecycle depends on many things.
Using static variable for this scenario is bad choice in general.I think this should solve your problem.
Try to print something inside the onResume and check it in LogCat.... the code inside onResume may be causing this.
or else can you elaborate your question?
I think here is what happens,
when your app not the Top app, the activity manager actually destroy the activity, it only called
public void onSaveInstanceState(Bundle savedInstanceState)
no
onStop
called, so no
noResume
will be called.
The correct to do this is, when put all states of this activity when
public void onSaveInstanceState(Bundle savedInstanceState)
called.
and in your onCreate() function, do such thing
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Always call the superclass first
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of members from saved state
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
} else {
// Probably initialize members with default values for a new instance
}
...
}
to check if you have some saved state.
Most code was copy from android developer site:
http://developer.android.com/training/basics/activity-lifecycle/recreating.html

How to save/restore(update) ref to the dialog during screen rotation?(I need ref in onCreate method of activity.)

protected Dialog onCreateDialog(int id) {
...
AlertDialog.Builder adb = new AlertDialog.Builder(this);
...
mydialog = adb.create();
...
}
But onCreateDialog runs after onCreate.
If you want to be backwards compatible, you do it as follows.
class MyActivity extends Activity {
protected static final class MyNonConfig {
// fill with public variables keeping references and other state info, set to null
}
private boolean isConfigChange;
private MyNonConfig nonConf;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_layout);
nonConf = (MyNonConfig)getLastNonConfigurationInstance();
if (nonConf == null) { nonConf = new NonConfig(); }
// handle the information of the nonConf objects/variables
...
}
#Override
protected void onStop() {
super.onStop();
isConfigChange = false;
}
#Override
public Object onRetainNonConfigurationInstance() {
isConfigChange = true;
return nonConf;
}
#Override
protected void onDestroy() {
super.onDestroy();
// handle objects in nonConf, potentially based on isConfigChange flag
...
}
The nonConf objects will survive all configuration changes (but not real stops of your app). Also, the isConfigChange flag tells you reliably if your activity is going to be re-created immediately or not. Thus, you can cancel/detach tasks or handle other resources adequately based on this information.
Edit: Please note that if onDestroy() is called then you can rely on the isConfigChange flag. Also, if Android is processing a configuration change then onDestroy() will be called. However, if Android is about to end your activity then the call to onDestroy() is optional because Android considers your activity to be killable right after it calls onPause() (pre-Honeycomb) or onStop() (Honeycomb and beyond). That's not a problem though, because if your activity is going to be killed, the state of your numerous objects isn't interesting to anyone anymore. However, if you want to be friendly, this is one more aspect to consider regarding the decision what to put into onPause() and onStop().
Hope this helps.

Categories

Resources