I am a beginner with Android, developing my final project for University. I have a problem that I do not know how to solve or how to start with it. When I launch my app I interact with it and then i press Home button on the emulator. I do whatever else and then I press the button to see open apps and select my app and then it opens in the very exact situation it was when i left it to go to the home... That's what I wanted BUT if while running my app I change to another app or go to home and I launch the app from the menu (press menu and find my app in the grid and tap the icon) it launches the app from the launch activity, being a new instance, overriding the previos app status...
What can be the error? What info should I provide to get some guidance?
Thank you very much in advance and excuse my messy explanation...
Miguel
PD: I tried to find this same issue, but I found nothing because I do not even know what to google for.... sorry
Perhaps, you should understand the Android Activity life cycle first.
http://developer.android.com/images/activity_lifecycle.png
Then you have to override all these methods (given in the diagrom) and you should use the debugger to know how, when, which method is called and note down the activity state in every case. The methods are:
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onRestart() {
super.onRestart();
}
#Override
protected void onStart() {
super.onStart();
}
#Override
protected void onStop() {
super.onStop();
}
#Override
protected void onDestroy() {
super.onDestroy();
}
Then to override them, you can add your own code to maintain/save the activity sate.
The developer guide has a good introduction on this topic:
http://developer.android.com/training/basics/activity-lifecycle/recreating.html
Save the state of your application inside the onPause() of the Activity. Place your code to restore the state of your application inside of onResume() inside of the Activity. This is part of the Activity lifecycle.
Just don't let the onResume() misleading language confuse you. The thing that resumes is the UI thread in this case, so this method will get called even when the application initially begins (when the UI appears).
If you have trouble fixing this, just post your Activity code in your question.
Related
Original question:
A button in my app starts an activity, which needs some time to prepare classes.
To let a user know this, I start a new loading activity that starts the actual activity.
This activity needs to be shown before the actual is started.
But all methods of the Android lifecycle seem to be called before the activity is shown to the user and if I start a new activity before the activity I'm currently in is shown, it won't be shown anymore.
I tried:
Starting the activity in another thread, but this does not work because the startActivity(...) seems to block the UI reload
Waiting a few milliseconds before starting the activity, but this seems dirty
Any help is appreciated! Please tell me if using a forward activity is not the right solution!
Answer for people who are searching:
Use this code to do something when the activity is already visible:
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
// do something
}
}
If the activity can also turn visible shortly after your code, use Androids lifecycle methods (here probably onResume()):
#Override
protected void onResume() {
super.onResume();
// do something
}
There is a function in my android app that needs to run every time the user tries to edit his or her profile. There are two parts of edit profile in my app (please don't ask why, it has a very long tedious reason behind it). I need to revert back the changes the user did in the first part of the edit profile if the user decides to cancel everything. I have made a cancel button in the part two of edit profile but my question is, what if user presses the return button or the home button on the device and the app calls the onPause() and on onStop()? how can I run the same code in these two phases of the activities? Anyone out there who knows how to put code in different states on activities? Do I just make a function onPause() and stick the code in there? Would that work?
Yes, it should definitely work. In your case, you should write your code in onPause() method.
Here is a summary of the Activity Lifecycle:
onCreate():
Called when the activity is first created. This is where you should do all of your normal static set up: create views, bind data to lists, etc. This method also provides you with a Bundle containing the activity's previously frozen state, if there was one.
Always followed by onStart().
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Write your code here
}
onStart():
Called when the activity is becoming visible to the user.
Followed by onResume() if the activity comes to the foreground, or onStop() if it becomes hidden.
#Override
public void onStart() {
super.onStart();
//Write your code here
}
onResume():
Called when the activity will start interacting with the user. At this point your activity is at the top of the activity stack, with user input going to it.
Always followed by onPause().
#Override
public void onResume() {
super.onResume();
//Write your code here
}
onPause():
Called when the system is about to start resuming a previous activity. This is typically used to commit unsaved changes to persistent data, stop animations and other things that may be consuming CPU, etc. Implementations of this method must be very quick because the next activity will not be resumed until this method returns.
Followed by either onResume() if the activity returns back to the front, or onStop() if it becomes invisible to the user.
#Override
public void onPause() {
super.onPause();
//Write your code here
}
onStop():
Called when the activity is no longer visible to the user, because another activity has been resumed and is covering this one. This may happen either because a new activity is being started, an existing one is being brought in front of this one, or this one is being destroyed.
Followed by either onRestart() if this activity is coming back to interact with the user, or onDestroy() if this activity is going away.
#Override
public void onStop() {
super.onStop();
//Write your code here
}
onDestroy():
The final call you receive before your activity is destroyed. This can happen either because the activity is finishing (someone called finish() on it, or because the system is temporarily destroying this instance of the activity to save space. You can distinguish between these two scenarios with the isFinishing() method.
#Override
public void onDestroy() {
super.onDestroy();
//Write your code here
}
You can do many things inside both onPause and onStop, just remember to call super.onPause();, super.onStop(); or whatever you need inside each one, just follow the pattern below. Simply add the code to your Activity and you're good to go.
#Override
public void onPause() {
super.onPause(); // Always call the superclass method first
// Do what you want.
}
Additionaly, if you want your users to be able to go back on your activity and edit something instead of closing it, you can just call onBackPressed():
#Override
public void onBackPressed() {
super.onBackPressed();
// You can just call onStop to close the app
// or do what you want.
}
Only onPause is guaranteed to be called
This is a very basic question, I have a few screens, now when you go from one to another you can then press back and cycle back through all the windows.
I'd rather that when you pressed back it took you to a specific window for instance:
Menu Screen
---->User clicks Info
Info Screen
---->User clicks Ride Info
Ride Info
---->User clicks back
Info Screen
Now is this to do with the hierarchical parent, will this define where it goes back to?
The second part of my question is if I don't have any resources to release or information to store for an on-resume what should I do when the user pauses my app? At the moment if you go back to the menu screen and re-select the app it will start a new instance rather than resuming. Do I just simply implement:
#Override
public void onPause() {
super.onPause(); // Always call the superclass method first
}
and
#Override
public void onResume() {
super.onResume(); // Always call the superclass method first
}
Apologies if this is a bit basic!
You might want to look in to setting FLAGS for your intent while opening new activity Android Dev
Something like this -
Intent a = new Intent(this,A.class);
a.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(a);
There is no basic questions here :)
Easiest way to do this is to override the onBackPress() function.
Sample :
#Override
public void onBackPressed() {
//Do what you want here
}
For saving variables when users leave the app, you need to override onSaveInstanceState(Bundle bundle)
#Override
protected void onSaveInstanceState(Bundle bundle) {
super.onSaveInstanceState(outState);
bundle.putInt("sample", 1);
}
For your two parts:
1) It's almost always best to let Android handle the back button, the order of which is determined by the back stack: see here for an explanation. If you want hierarchical navigation, I would recommend looking into the up button - see this developer page for a good explanation of how to use the different navigation tools.
Additionally, if you don't want to have an activity appear in your back stack, you can set the attribute android:noHistory="true" in your manifest, which will mean that the user can't return to it using the back button.
2) If the user has left your app, it's automatically paused, you don't need to implement onPause or onResume for this to happen. However, it's also up for collection to be terminated by the OS. If this happens, then it will be restarted when the user opens it from the launcher again. Any previously running instances of the app should automatically be opened.
I'm building an Android app specifically a log in page whereby I'd like the app to completely shut down the app if the user was to exit the log in page in any way i.e. using the SWITCH, HOME or BACK buttons.
The only time the app should not completely shut down should be when user successfully logs in i.e. when the custom created log in button or enter button is pressed.
I've been able to do successfully shut down the app but in shuts down even when the user successfully logs. It isn't meant to do this.
Below is my code for the complete shut down - I took over the onDestroy(), onBackPressed(), finish() and onStop() methods:
// Deal with back button
public void onBackPressed() {
System.runFinalizersOnExit(true);
System.exit(0);
}
// Deal with exiting of app
public void finish() {
System.runFinalizersOnExit(true);
System.exit(0);
}
// Deal with exiting of app
public void onDestroy() {
System.runFinalizersOnExit(true);
System.exit(0);
}
// Deal with exiting of app
public void onStop() {
System.runFinalizersOnExit(true);
System.exit(0);
}
DOES ANYONE HAVE ANY IDEAS REGARDING MY ISSUE
YOUR ASSISTANCE IS GREATLY APPRECIATED
Look here for an explanation of the onStop() method. I suppose you open another Activity when the user has successfully logged in, your Activity above becomes invisible and calls onStop() where you exit your app. So just don't override onStop().
The onStop() method is called each time your activity is made invisible: when your app goes to the background, when the screen is turned off, or when you switch to another activity.
Regardless, what you are trying to do is strongly discouraged.
See this forum thread (Dianne Hackborn being one of the lead developer of the Android Framework).
Force closing your app using System.exit(), Process.killProcess() and the likes has a strong risk of conflict with the Android application lifecycle, and can corrupt its saved state, leading to unexpected and unpleasant behaviors for your users.
A better way is to use the flags FLAG_ACTIVITY_SINGLE_TOP and FLAG_ACTIVITY_CLEAR_TOP when launching your login activity.
This should remove previous activities from application, which would be the same as starting a new application from a user point of view.
Just create a class member boolean mLoggedIn and set it to true when the custom created log in button or enter button is pressed.
Then
#Override
protected void onPause()
{
super.onPause();
if (!mLoggedIn)
{
finish();
}
}
My end-goal is to have an application that runs a block of code when it (the application, not the activity) is opened up after being left ( back from home screen, etc... )
According to the Activity Lifecycle, this should be the onRestart() event on a per activity basis ( at least how I interpret it )
Both onRestart() and onResume() are being called whether I am returning to the Activity within the application (back button) AND when the app is called back up.
Given this diagram
I am interpreting it this way:
RED = movement between activities within the application
BLUE = moving to an activity outside the Application
Is my understanding incorrect?
EDIT (Clarifying specific use case)
I'm attempting to use onRestart() to replicate some security logic (PIN Validation) found in onCreate(), but it's being called even when I press the back button inside the application...
My observation is that its hard to tie the lifecycle events to user behavior on the device or emulator. Where your app is paused, if the device needs memory or wants to recover resources, it will terminate the activity, causing onCreate to be called. There is just too many scenarios to build an adequate state machine to tell yourself "how" or "why" your activity was terminated.
The only way I've found to manage this is to create a service to hold the application state and manually manage the state. The problem is trying to use the Activity state to manage the application state. The Activity design seems to have limitations that just make it a poor choice for achieving the goal you've stated.
That would be because when unless your are using Fragments each "screen" in your application is a new activity, when you click the back button it restarts the activity of the page before it.
If I am understanding what you want to do correctly you want to put your code on onCreate, not onRestart.
SEE COMMENT THREAD FOR ANSWER
Here is how to do this:-
Have a base activity that all your activities are derived from.
Add in to the base activity:-
int nAppState;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
nAppState = 0;
.
.
}
protected override void OnStop()
{
AppState();
base.OnStop();
}
public static int IMPORTANCE_BACKGROUND = 400;
protected override void AppState()
{
ActivityManager am = (ActivityManager)GetSystemService(Context.ActivityService);
IList<ActivityManager.RunningAppProcessInfo> list2 = am.RunningAppProcesses;
foreach (ActivityManager.RunningAppProcessInfo ti in list2)
{
if (ti.ProcessName.ToLower() == "com.mycompany.myapp")
{
nAppState = ti.Importance;
break;
}
}
}
protected override void OnRestart()
{
base.OnRestart();
if (nAppState == IMPORTANCE_BACKGROUND)
{
// Show a log in screen
RunOnUiThread(delegate { StartActivity(new Intent(this, typeof(LoginAppearActivity))); });
nAppState = 0;
}
}
Please note that this is in Mono C#, it will be the same code for Java, I'll leave it up to you to convert it!!
Yes, your assertions for red and blue are correct.
However, note the alternate pathway from onPause() and onStop(). Process being killed for memory reasons is a) out of your control and b) imperceptible to you if you only use onRestart() to detect "coming back" to the activity.
You have an option to avoid the previous activity by avoiding/removing the activity to come in Stack by setting some flag before calling the startActivity(intent):
intent.setFlags(i.getFlags() | Intent.FLAG_ACTIVITY_NO_HISTORY);
This will avoid the present activity to get called on back press. Alternatively you can also ovverride the onBackPressed() method of the current activity.