Getting a call Vs pressing home - android

I run my android app, and when I press home button and come back to the app. Everything is maintained (the score, the state ..etc). assume it goes to OnPause the OnResume.
However, when I get a phone call while running my app, then my app state is reset (score is gone ..etc).
Why is that? Shouldn't it go through the onPause/OnResume as well?

When you get a phone call, it does go through onPause and onStop and when it is brought to the front again it goes through onStart and onResume. It may also be going through onDestroy which will cause it to go through onCreate when you bring it back. Suggest putting Log statements in each of the lifecycle methods to see which are getting called (or breakpoints in the debugger). Then you'll know what approach to take to resume your game.
In reality, you should implement the app such that it can go through onDestroy and recover when starting up again in the way you want.

When your app goes into the background, the Android OS decides if it should kill the app based upon current factors (e.g. available memory). If there are insuffuicient resources to maintain an app in the onPaused() state then they are destroyed (onStop() followed by onDestroy()).
Shouldn't it go through the onPause/OnResume as well?
Based upon the above and documentation, then yes it does go into onPause but then it goes into the other phases afterward.
Here is a handy image to help from the documentation that i know you read.

Related

How to properly finish (reset) an activity as soon as the user leaves it

I have an Activity that I consider a critical operation (Specific communication with another computer over Bluetooth) and I want to make it so that when the user leaves the activity, it cannot be resumed to that state. With other words, if the user resumes the activity it should be recreated.
Since this activity uses Bluetooth it might start one or two activities for result (Enable-Bluetooth activity and Request-Permissions activity) and therefore, I cannot simply finish() the activity in onPause().
By leaving the Activity, I mean presses the home button, takes a phone call or presses the multitask button
I have experimented with some Activity Launch modes (like singleTask) without success.
I already call super.onCreate(null) in the Activity's onCreate() method, preventing it from recreating to a specific state after it has been destroyed, but I want to reset the activity whether onDestroy() has been called or not.
Does anyone have any suggestions on how this should be done correctly?
Edit:
The question in the Possible duplicate explains how to quit an application and it's subtasks completely (whereas just finish() would suit my needs perfectly - if I knew where to call it). This question is about finding a clean way to not resume the previous state of the Activity.
If you never want a state persist once you've left via the home button, or perhaps even when the screen turns off, the simplest thing is to work with the lifecycle events available. It's a whole lot simpler than trying to work around Androids design by doing things like forcing the close of your app.
Since everything needs to be setup each time someone returns to the app, you can move all of your setup logic out of onCreate and into onResume. Then, perform all the required cleanup (kill your BT connection, etc) in onPause. The only possible gotchas are related to things like changing screen rotation/ opening the keyboard which might trigger lifecycle events that you didn't intend. That might make your program less responsive if you have a lot of long running tasks on the UI thread in onResume.

Can I call a method right before my app closes?

Here's the situation:
I want to check if the device is rooted or not every time the app comes to foreground (either because they're launching the app through App Drawer or coming back to the app via Recent Apps list). This check is done during onResume(), and it's working well.
The problem is that the intention is to check for root only once when the app comes to foreground, not when user is currently using the app. Since onResume() is called when an Activity comes to foreground, this means the check is done multiple times even when it's not needed, which comes at performance cost.
I thought of using a static variable to lock it, locking just before I perform the check to ensure the check is only called once. This is fine and dandy, but the problem is when to do the unlock?
onPause() is called before another Activity comes to focus, which
would negate the lock. I tried to use isFinishing(), but if a user
presses the back button, the activity is destroyed, which resets the
root checking lock and renders it less desirable. EDIT: Also, the Activity is not finished if the user presses Home button, which means it's also not reliable enough
onStop() and onDestroy() are not guaranteed to be called, and
they're also called if the user presses back button.
Is there a way to call a function exactly once when the app moves to background, without restricted to the constraints of onPause() above? I searched through the Activity, Application, and BroadcastReceiver documentation but couldn't find any mention about such a thing
In the end, I decided to use a combination of onUserLeaveHint(), custom startActivity() and onBackPressed() to do it, with some private static and non-static variables
I used onUserLeaveHint() to detect when user is going back to Home
or to Recent apps list.
onBackPressed() is used to tell the app that it is used for
navigation, while another onBackPressed() override is written at the
app entry point to detect when user is using back button to go back
to Home (can't believe onUserLeaveHint() doesn't account for that)
the custom startActivity() makes sure that onUserLeaveHint() is not
called when another activity is started. While onUserLeaveHint() has issues with forced interruptions (such as user receiving a call), it is deemed acceptable for now.
I did some research and found this blog but it makes use of onStop(), which is not guaranteed to run
Thanks for all the responses. I understand the concern about my security approach, but the question is about detecting when the user is leaving the app

Prevent activity from being destroyed as long as possible

I have an app, a single activity app with fragments in it.
The usual use case for this app is, that you start it and put the phone away and every now and then, you get back to the phone and insert some data... It's a logging app, you are doing something and insert your results into the app...
I have the problem, that every now and then, my activity get's destroyed and is recreated with an empty bundle... (Most of the time this is not the case, but every now and then this happens...). My app sometimes starts a service, even this service is killed in this case...
This means, that the system has killed my app, does it? How can I avoid this?
I need to keep the user data and the current top fragments... And they are saved to the bundle and everything works as long as their states and the data get saved...
Btw., my activity is always the TOP ACTIVITY, only that the screen turns off often... I just want to keep my activity alive as long as possible until the user leaves it with the back button... Or to save the state reliably
IMPORTANT NOTE
onSaveInstance does not always work (it's not part of the lifecycle and therefore not guaranteed to be called)... it only works most of the time... I need a way to that works always... If android kills my app...
don't keep your app in memory
You don't want to block Android from killing your app. What you want is to restore your app's state properly. Then the user will never notice the app has been destroyed and the user still gets the benefit of an app that was destroyed when not in use.
If you really want this use a wakelock. This will drain your users battery so I think twice before implementing this... Info at How do I prevent an Android device from going to sleep programmatically?
onSaveInstanceState explained
To do so check what information is needed in the bundle and persist that information with the onSaveInstanceState(bundle:Bundle) method so you can reuse it in onCreate(sameBundle:Bundle).
More information available from Google documentation at Save your Activity state and Restore your Activity State.
About Android Activity lifecycle
As stated by #prom85 in the comments below it's not guaranteed that the onSaveInstanceState method will be called because it's not part of the lifecycle. Workaround for this is using the onPause lifecycle hook to ensure your data is stored.
More information at Android: onSaveInstanceState not being called from activity
I had a similar problem, I arrived at this post while searching for a solution, you have to play with the manifest to achieve this and also understand what exactly activity is, in Android eco system,
In Android activity is a task which has a pre defined work.
I dig a lot in the documentation, I found that, we can configure activity in two ways,
Persistent
non persistent
if you mention for the activity in the manifest as
android:persistent="true"
and run the below use case
Start the APP
Press back or home button
you select the activity in the back stack again to bring it to front
Activity enters start -> pause -> stop - > resume , it does not get into onDestroy method.
if do not mention
android:persistent="true"
for the same use case
Activity enters start -> pause -> stop -> destroy, and if you select the activity from the back stack
Activity enters resume->create->start
If you want to run a service/task on activity start which keeps running when the app is in back stack, then you have to start that in the onCreate method, and kill them onDestroy by specifying your activity as persistent in manifest.
I hope my above solution might help others who arrive here for the same problem

pressing home button and access app again from app icon call onCreate?

I have an offline-online application, i found a strange issue in it, may be it is not, but i did'nt understand about it..
App requirement is that, if internet is available, even from starting app or from resuming, i call webservices and store data in sqlite, otherwise app stays in offline mode,
I have 2 activities, second activity contains an id, that i passes through intent (that point is important),
My Problem:
if i am in second activity, and internet is running, and i press home button , then this 2nd activity pauses, then stop which is a default behavior in android, i goto settings, turn wifi off, then press app icon again to get back in my app, here i got confused, i expect that my app now will be in onResume, but when i see in logcat its onCreated called and app
crashes, nullPointerException occurs, because this 2nd activity does not have that id, i passed through intent..
Note:
If i use recent app button to go to "settings", then come back again after turing wifi off, and repeat all this behavior, then working fine, its onResumes called not oncreate..
My Question
Why it is going in onCreate while i my expectation is to be onResume while i came back from app icon?
The NPE reason is clear, your second activity doesn't have the value and it crashes.
Why do you get different behavior then!?
It's because the launching intents are different. When you "task switch" Android is merely stopping your app but leaving it there (no guarantee) in case you want to switch back.
Going home (with home) is a clear indication that you want to leave the app, and although it will remain in memory and cached (as long as there is available memory), going back through the launcher (or App Icon as you call it) fires the LAUNCHER category (which goes to your Activity 1 first).
Take a look at this StackOverflow question (and answer) to better understand the consequences.
In any case, your problem is that your app must always be designed to resume in an inconsistent state and be able to recover. Android will kill your references, will destroy your variables and most likely send your app to hell overnight even if you have it running… if the phone goes on standby, chances are processes that aren't doing anything will be paused/stopped and likely killed.
Re-design your app so this is not a problem.
You say:
"I have 2 activities, second activity contains an id, that i passes
through intent (that point is important),"
Well, why not make it easier and have ONE activity and TWO fragments? Then use Fragment Arguments to pass the value?
Or why not store the value in the preferences and/or a local database and recover it during onCreate?
And also why not make it so that if Activity 2 doesn't have a value, it calls Activity 1 and closes itself (better than a crash, huh?).
Etc.
As you can see there are multiple things you should consider. All in all, never trust that your app will be alive, because it won't.
Once your activity's onStop gets called it's susceptible to be killed by the android system to collect resources for other apps which is what i think happened in your case.If it is killed, android will obviously call OnCreate when you get back to the activity.Check this for clarification. For experimenting you can try opening more than one apps from your recent apps and then return to your app. It may crash there too now.
You stated that you can see that the activitiy is stopped (onStop) if you go to the settings. That is the behaviour shown in the Android activity lifecycle. The counterpart for onStop is onCreate. So it does what the documentation tells us. Btw activities are paused if they are visible in some way and get stopped if they are not visible anymore. This would explain why your activity get paused. For further information read Managing the Activity Lifecycle. You can find a whole picture of the lifecycle here.
This type of behaviour can be seen when you change some system configurations like font type,font size or language. But turning wifi on/off won't destroy the app and recreate it again. Check http://developer.android.com/guide/topics/manifest/activity-element.html#config for more information

Android's activity lifecycle after coming out of sleep

If an activity is being shown on the screen and has a button with a click listener attached to it, that gets attached to the button during the onCreate method, and then the device goes into sleep mode (or the user taps on the power button to turn off the screen), when the screen comes back on the activity is still visible as it was prior to going into sleep mode.
The onResume gets called, which is documented as part of the lifecycle for an activity. What I don't understand is why the onCreate doesn't get called again. How is it possible for the button's click listener to even function after coming out of sleep mode? You would think that Android has destroyed all running processes attached to the activity which includes the button's click listener.
What do you mean by, why doesn't the onCreate() get called again?
Simple answer: your activity is not being destroyed when the screen goes off, so there is no reason for onCreate() to be called again.
When the phone's screen is turned off, the activity's onPause() callback is called, followed by onStop(). However, just because it reaches onStop() does not mean that it will always reach onDestroy(). At least to my understanding, Android's OS attempts to keep as much of its memory used as possible so that apps will load back up faster, etc (this is a real over simplification, but I believe that is the general idea). That means that your activity still exists in memory when the screen goes off (at least at the beginning). Only when the system really needs the resources that your activity holds will it call your activity's onDestroy(). That is why your button click listener still works when you turn the screen off. Your activity still exists in memory, which means that your button listener is also still registered.
I think it's important to point out that sleep mode and turning off the screen are not the same thing. When you turn the screen off, it may or may not go into sleep mode right away. When the screen goes off but it doesn't go into sleep mode yet, the cpu is still working and the service is still running. When the phone goes into sleep mode it powers down the CPU, essentially "freezing" all processes, and as a result all services also. Using wakelocks prevents the phone from going into sleep mode, which is why services will still run while the phone's screen is off for an extended period of time. If you haven't read it yet, the Service reference has some pretty good info. It also discusses its lifecycle and how Android prioritizes its memory usage.
Android's activity lifecycle is extremly complicated and even Romain Guy states he doesn't understand it fully after many years of core development on android. You can assume that Android OS can interfere with your Activities lifecycle how it may seem fit when it's in background. The activity lifecycle represents the actual behaviour only very roughly, mostly I got my understanding through experience and trail and error.
In your case if you send your activity in background, if android has RAM available it trys to keep your activity in RAM, so it's going through onPause and onStop. Now this state can persist until you return to your app, then it will go through onStart and onResume, since all your references/fields you created onCreate still exists and can be "reused". On the other hand if the OS decides to it needs more memory it can destroy your activty and will be open for garbage collection and also will go through the onDestroy() lifecycle. The next time you reopen your app a new activity will be created with the state saved onSaveInstanceState() and the whole lifecycle from onCreate() will be run through
With services it's the same thing. Usally service SHOULD not run over long time, they also should stop themselfs immediatelyafter they are done. So if the OS finds a service that runs over long time in the background it trys to get rid of it to save battery / ram after an abitrary amound of time (and perhaps other parameters are included in this decision). On the other hand IF you need a long running service you need to manually keep a wakelock to sginal the OS "I need this done no matter what".
When you press power button or home button ,android OS put your current activity onto back stack,
Reason why onCreate doesnt get called again is,it is specifically made to create views and to do one time memory operation like loading your xml layout into activity.The system works such as you dont have to allocate memories each time you come on that page instead only when you created the page.onResume gets called because you are resuming back to the same activity.
Memroy Managment is very crucial in Android as it is a mobile operating system.
short answer:
onCreate() gets called when a Activity gets created.
the behavior for a device going into sleep and comming back is defined as onPause() and onResume() call. device sleeping will not kill the app or the activity - state keeps (nearly) the same.
#AndroidDev you will get clarity of this question, if you know which methods are calling at what time. below is the method called list at the different scenario
1)when we start activity nothing but calling startActivity(intent) this time
onCreate()
onStart()
onResume()
2)how many ways activity goes in sleep mode?
a)when we pressed lock button it will goes in sleep mode and below methods called
b)when we pressed overview button it will goes in sleep mode and below methods called
c)when we start another activity from present activity it will goes in sleep mode and below methods called
onPause()
onStop()
3)how many ways activity destroy
a)if we called finish() method it will called below methods
b)if we click back button it will called below methods
onPause()
onStop()
onDestroy()
so when ever activity going in sleep mode it's not calling onDestory() method, that why when your coming back from sleep mode your activity not calling onCreate method.
onCreate() will called only first time when you called startActivity() or if you destroy activity calling finish() or back button pressed in this both condition destroy() method will called.

Categories

Resources