Main activity removed from stack - set uset state as offline - android

When the main activity is loaded I can set the logged user's state as online by updating a remote database row. If the user exits the app I must set the user state as offline.
If the app is exited using back button I have the onDestroy() method and in there I can set the user state as offline, but if I exit using Home button and I kill the app from settings onDistroy() isn't called.
Is there a way to know when the main activity is no longer on stack, so I can update the user's state?

onStop will be triggered when user clicks on back or home button. So handle your events in onStop.
public void onStop () {
//do your stuff here
super.onStop()
}
EDIT:
Also try
#Override
protected void onPause()
super.onPause();
}
Also you could have it check if the app is finishing with
if (this.isFinishing()){
//Insert your finishing code here
}

The home button doesn't call onDestroy as the activity is still on the Activity stack where as with the back button it is generally removed. When the ActivityManager decides to remove the activity from the stack, usually after a period of inactivity or when resources are required, onDestory will be called at which point your field will be reset.
I am not able to say definitively because I don't know all the information but it would seem that removing the users logged in state when you press home (in onStart as suggested by coder_For_Life22) might be bad, as if you returned to the activity the user would have to log in again, perhaps unnecessarily and the client side session management will become even more complex.
Your method of session management seems fairly questionable anyway unless you have some sort of server side session management where, for example if there was inactivity on the session the database field would be reset.
UPDATE
The only way I can think it might be possible is using the ActivityManager.getRunningTasks() or ActivityManager.getRunningAppProcesses() and checking if your app is among them. If you kill your app like you are suggesting then your app will not be among them and thus you know. It seems like a hugely complex solution if at all possible as you would need a separate background service running (which you could call getSystemService(ACTIVITY_SERVICE) on to get the ActivityManager) just so after you kill your app you still have something running which can check for this and perform the appropriate actions.
Killing your app this way neglects the activity life cycle and thus there isn't a hook in your activity where you can perform shut down calls.
It seems much more sensible to check for inactivity on the server side and reset the field this way, people don't often kill their apps like this and when they do they aren't likely to quickly hand the phone to someone else who would be able to access the information maliciously.
If the data requires such security then you should rethink your security model.

Related

Is onPause() or onStop() called even if phone dies due to lack of power?

If I, for example, need to keep some very important data which the user can edit within my app, should I need to save them every time user changes such data or is it ok if I would save it within onPause(), onStop() or onDestroy() methods?
Can somehow application end without any of those methods calling? (For instance when battery runs out)
This certainly can't be done in onDestroy().
According to the documentation:
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 yes, the application can end without calling any of the lifecycle methods.
In that scenario when the phone is shutting down, you can use the ACTION_SHUTDOWN Intent.
More info here. For all other cases onPause should do the work. Even in the link provided, there is a statement that onPause will be called if the app is in FG.
Apps will not normally need to handle this, since the foreground
activity will be paused as well.
However, if it is not so expensive operation, I would go with saving data after edit.
As per the documentation of Android activity life cycle, onPause is called when an activity is going into the background, but has not (yet) been killed.
Hence, in most Android documentation, and sample codes you will find onPause is used for saving any persistent state the activity is editing, to present a "edit in place" model to the user and making sure nothing is lost if there are not enough resources.
So in your use case, all you need to do is implement onPause for your Activity and write a code to Save the activity state (EditText content or any other ongoing user interactions). Android system will save the activity state which you can always get back in onCreate of your Activity when android launch your activity next time.
in this case please verify your phone activity via debug interface , some of phones are terminate your application this is force quit.

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

android: pause (close) app so that it is re-opened on the same state

I have an app that records some data (time, user’s gps position etc). Now I want to implement this: when user presses back I pop an alertdialog with two options to “pause” or “exit”. I can do that overriding the onKeyDown method. Now “exit” should mean to close the app and the recording of data is stopped. “pause” should mean that the user can close the app for some minutes and then continue when he re-opens from the exactly same point.
I have done some research, but I got confused on many points:
1) Can I guarantee somehow that the activity gets paused and not destroyed? Moreover finish() destroys the activity. Is there some method to pause it programmatically?
2) If only the onPause is called then when app is opened again shouldn’t start from onResume? So all the counters (which I normally set to zero in the onCreate method) should remain in the last state?
3) One obvious way would be to save the whole state of the counters etc in the device db and then restore it when user re-opens. But it is more painful, and most of all this a good practice?
Thanks in advance for any clarification!
you Can't guarantee that the activity never will be destroyed, cause if the system needs memory or something it will automaticaly close some apps, but you can save your state of your app in a variable "savedinstancestate" witch you can save in a persistance database, or in the SD.
If you want to pause the app you should call the "onPause" method and then call the method "onResume" if you do this, you will be able to restart your app from the last state.
if you want to stop your app, only call the method "onStop"
i'm not a master of Android, but i hope that this answer could throw some light about your question ;)

Categories

Resources