How to start an activity before resuming the app when restart? - android

I have a quiet big application, and sometimes the user uses the HOME BUTTON to 'exit' the application or he receives a call etc. but when he clicks again on the icon, the application is resumed.
What I want is everytime somthing like this happens, the app restarts on the login activity (security process) before resuming the previous activity running before he exit the app.

When the HOME button is pushed, I believe your activity's onStop() and/or onPause() functions will be called. Override one of these methods and set a member variable to check if your activity was interrupted. Now override onResume() to check that variable to determine if you want to start your login activity.
Hopefully this idea gets you in the right direction.
You might also consider creating a super class that extends Activity and override the onStop()/onPause()/onResume() methods to exhibit this functionality. That way, all of your activities outside of your login activity can extend this class, allowing you to place the functionality that you desire in exactly one location.

Pass a Extra to any activity you call after login: intent.putExtra("isLogin", "Yes");
In every activity you call:
declare a field boolean isLogin;
In onCreate:
Intent sender = getIntent();
isLogin = sender.getStringExtra("isLogin","No") == "Yes";
In the onResume of every activity do this:
if(isLogin){
isLogin = false;
}else{
callActivityLogin();
}

Related

Android Pause / Resume

Just looking at this documentation about Activity Lifecycle
https://developer.android.com/reference/android/app/Activity.html
it seems to me the onResume callback is not really a real resume. Because it will run if
a. Activity is just created, even if it was not paused.
b. Activity was paused and then it's resumed.
I am sending a user to another activity to do stuff, and depending on what the user did on those other activities, when they return, I need to decide whether to reload the app manifest. However, I don't even wanna check if the app was not paused at all! (ie. the user just opened the activity)
Is there a better way to track if the user is really resuming other than creating a variable in onPause that I will check when the user returns?
Declare a boolean flag in your activity:
boolean hasBeenPaused = false;
Now in your onPause(), set this to true:
public void onPause(){
hasBeenPaused = true;
}
Since your onResume gets called whether or not the app was previously paused, you can now check the boolean and know if it's a fresh start onResume or post pause onResume
public void onResume(){
if(hasBeenPaused){
//onPause was called
//May be because of home button press, recents opened, another activity opened or a call etc...
}else{
//this is a call just after the activity was created
}
}
If you want to persist, you can even save this variable inside onSaveInstanceState and get the saved state in your onCreate
If you are absolutely against setting the variable in onPause and want to ensure that a change was made before reloading the data then set a variable in your API calls that triggers a reload when the user comes back to the activity. Depending on your application structure you could even do the reload before hitting onResume in the activity.
Also be aware that onResume will be called if you're in a fragment and provide a popup (such as an activity indicator).

Android: How to get back to the Calling Activity without using finish()

I call an activity called Activity1 from an Activity called MainActivity using the following:
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
So, when the control comes to Activity1. The normal activity lifecycle is started. i.e onCreate() is called and so on.
when i click the back button when the control is in Activity1. The finish method is called, which in turn calls the onDestroy() and now the control is back with the MainActivity screen.
#Override
public void onBackPressed() {
Log.d(TAG, "onBackPressed()");
finish();
}
The next time i call Activity1. The onCreate is called again as i called the onDestroy (when i pressed the back button) from the previous call.
Question:
1. is there a way to pass control back to the MainActivity when the back button is pressed without having to call the "finish()" method?
2. problem with calling finish, every time i call Activity1 from MainActivity, A new instance of Activity1 is created. that is the lifecycle again starts from onCreate()..
i do not want this to happen as this is has become a major performance issue.
The main point i'm looking for is whether i can start the activity1 from the resume state rather than oncreate, when i call it after the first time.
I don't believe you need to call the "finish()" method on onBackPressed. Android does that for you when you press the back button. The onBackPressed is used to last minuet tidy up (save stuff to sharepreferences, etc).
Android default behaviour is to call onCreate whenever a new activity is place on the screen. You cannot call a new Intent without this to happen.
I'm not sure why this is performance issue for you. Can you go in a little more detail what activity1 is doing? Are you doing heavy network communication? Is it possible you can cache the store results?
in Actitity1 you define your WebView as:
private static WebView webView = null;
in onCreate() you only create it if it's null:
if(webView == null){
//create webview and load from network
}
Use this approach wisely as it may easly lead to memory leaks if you point to objects in other activities, or objects that may be kept alive (runnables, messages, etc.)

Start root activity if no other activity live for this android app when press back key

I have a message notification, when user select the notificaton, a message display activity will show.
When user read the message and press back key to close the activity, I want to check if the previous activity is the same app's, if so, just go ahead, if not, I want to start the home activity for this app.
How can I do that?
How about this: Have the notification launch the Home Activity in a state that immediately has the Home Activity launch the MessageDisplayActivity. That is: (1) The intent that the notification sends should target the HomeActivity and include an extra flag identifying the Intent as being from the notification. (2) The HomeActivity, in onCreate(), upon finding that flag then simply launches the MesssageDisplayActivity.
Thus the HomeActivity will exist for a brief moment of time, but probably not long enough to be visible. It will then remain upon the back stack so that the back key will bring you there.
You should consider changing the launch mode of your Activity, so that you never have this problem - using singleTask or singleInstance should make this Activity always be the only one open for your app.
Have Intents within your app that call the message display activity (MDA) pass a boolean value of "true" that's extracted and stored in a field in the MDA. Have the field set by default to "false." Thus, if the MDA is called from an activity within your app, the field will have a boolean value of "true," if it's called from anywhere else (such as a notification), it will be set to false.
Override public void onBackPressed() in the MDA as follows:
public void onBackPressed() {
if (wasCalledFromYourApp == true) {
super.onBackPressed();
} else {
//[code that launches your app's home activity here]
}
}
(This is assuming the notification will only be created by one app).

How to handle activity coming to foreground again

The books I have are abysmal at explaining how to work with the lifecycle, there's a lot I'm missing that I'm hoping somebody can fill in.
My app structure is that when it's first started, it starts an activity full of legalbabble that the user has to accept. When he says 'ok', I start my main activity and then I call finish like this:
public void onClick(View view) { //as a result of "I accept"
Intent mainIntent = new Intent(mParent, EtMain.class);
startActivity(mainIntent); // Start the main program
finish();
}
Then in EtMain in the onCreate method, I've got some tabs and I instantiate some classes:
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mTabHost = (TabHost)findViewById(android.R.id.tabhost);
SetupTabs.setMyTabs(mTabHost, this);
mComData = new ComFields(this); // Create the objects
mDepWx = new WxFields(this, DepArr.Departure);
mArrWx = new WxFields(this, DepArr.Arrival);
mDepVs = new DepFields(this);
mArrVs = new ArrFields(this);
mTabHost.setOnTabChangedListener(new OnTabChangeListener(){
}
Questions:
The 'finish' in the first fragment should terminate the legalbabble activity so it'll never be restarted, right? And the EtMain one will remain forever (until killed externally), even if my app gets pushed to the background, right?
The way it is now, when EtMain gets pushed and later brought to the foreground (by tapping on the icon), it goes through the legalbabble screen as though it's a complete start - that's what I'd like to prevent - going thru the legalbabble screen again.
It would seem that I'd want to override onRestart in the second code fragment and put something in there to restart the app, right? That's the part I'm unclear about.
My question then is what needs to be done in onRestart. Do I have to recreate all the tabs and data in the tabs and all my object instantiations? Or is the memory state of the app saved someplace and then is restored back to the state that it was in before something else was brought to the foreground in which case not much needs to be done because all the objects and listeners will still be there?
Yes after the first activity has ended you shouldn't have to view that activity again. You could also write to the shared preferences that the user has previously seen legal info.
If you're UI object creation is in the onCreate method, this should only be called once. Pausing or resuming will not call the onCreate method again.
Unless you explicitly remove your objects and tabChangedListeners in the onPause method, you should not have to touch them in the onRestart method.
Correct, the state of the app is saved automatically. You shouldn't have to touch the onRestart method.
Hope this helps!
I think the problem is that the launch activity in your manifest is the legalbabble activity, so when you click on the icon, the system launches another one. A better architecture would be to launch the legalbabble activity it from your EtMain activity in the onCreate method of the latter, using startActivityForResult. From the docs:
As a special case, if you call startActivityForResult() with a requestCode >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your activity, then your window will not be displayed until a result is returned back from the started activity.
When you get the result in onActivityResult, you can call finish() if the legal stuff was declined; otherwise everything will proceed normally.
This avoids the problem that the launch activity defined in your manifest finishes when the legal stuff is accepted.
EtMain will not remain forever, if the user backs out (by pressing the BACK key) the Activity will be finished (onPause, then onStop, then onDestroy will be called).
In general you can ignore onRestore until you are doing something complicated.
Once the user has exited your application and re-enters (or presses the icon on the Homescreen), onCreate (followed by onStart and onResume) will be called for your first activity, so you do not need any logic in onRestart, your code in onCreate will do the setting up for you as it did the first time. Because of this your legal babble will appear again when the user starts the app after exiting unless you store a preference (in SharedPreferences or a database or file) to indicate you have already displayed it - in which case finish it straight away and start the main activity.
onRestart is only called when the application goes from the stopped state (onStop has been called but not onDestroy) to the started state (onStart is called but onResume has not yet).
For saving data - some components save their state automatically (e.g. EditTexts remember the text in them, TabHosts remember the currently selected tab etc). Some components will not. If you wish to save extra data then make use of onSaveInstanceState and onRestoreInstanceState. You should only use these methods to restore the state of your application or temporary data, not important things, e.g. the id of the resource what the user was looking at, what zoom level they were at etc. For things like contacts or actual data you should commit these changes to a database, SharedPreferences or other permanent storage (e.g. file) when onPause is called.
I recommend taking a look at the Android Activity lifecycle if you are confused. Or ask more questions!

Android: Different start activity depending on user preference

My application starts with a welcome screen Activity, but that screen has an option to skip that screen altogether in future launches.
What's the proper Android way to do this? Initially, I just automatically detected the skipWelcome preference and switched to the 2nd activity from Welcome. But this had the effect of allowing the user to hit the back button to the welcome screen we promised never to show again.
Right now, in the Welcome activity, I read the preference and call finish() on the current activity:
SharedPreferences preferences = getPreferences(MODE_PRIVATE);
boolean skipWelcome = preferences.getBoolean("skipWelcome", false);
if (skipWelcome) {
this.finish();
}
And then I implement onDestroy to move on to the next Activity:
#Override
public void onDestroy() {
super.onDestroy();
startActivity(new Intent(Welcome.this, StartFoo.class));
}
But this makes for some weird visual transitions. I'm starting to think that I need a base Activity that pops open Welcome only if proper, and then goes to StartFoo.
I can't comment on Mayra's answer or I would (not enough rep), but that's the correct approach.
Hidden in the Android documentation is this important phrase for Activity.startActivityForResult(),
"As a special case, if you call
startActivityForResult() with a
requestCode >= 0 during the initial
onCreate(Bundle
savedInstanceState)/onResume() of your
activity, then your window will not be
displayed until a result is returned
back from the started activity. This
is to avoid visible flickering when
redirecting to another activity."
Another important note is that this call does not block and execution continues, so you need to stop execution of the onCreate by returning
if (skipWelcome) {
// Create intent
// Launch intent with startActivityForResult()
return;
}
The final piece is to call finish immediately in the welcome activity's onActivityResult as Mayra says.
There are a few solutions to this.
Did you try just launching the activity and finishing? I vauguely remember that working, but I could be wrong.
More correctly, in if(skipWelcome) you can start the new activity for result, then when onActivityResult is called, immidiately finish the welcome activity.
Or, you can have your launcher activity not have a view (don't set content), and launch either the welcome activity or StartFoo.

Categories

Resources