4

I'm trying to implement some automatic logout code for my Application on Android.

I need to detect if all the activities belonging to an Application have entered the background as opposed to working with onPause() and onResume() for each individual activity. iOS has a helpful applicationDidEnterBackground: method that I could utilize, but I'm unable to find a similar function in Android's Application class.

One approach seems to be to have an AtomicInteger counter and increment it once an activity becomes visible and decrement it when it's finished or onStop() gets called. So if the counter becomes zero, I can start a service that runs in the background and handles the logout. Is this how it's usually done?

RedBlueThing
  • 42,006
  • 17
  • 96
  • 122
Tejaswi Yerukalapudi
  • 8,987
  • 12
  • 60
  • 101

4 Answers4

18

There is no global callback for this, but for each activity it is onStop(). You don't need to mess with an atomic int. Just have a global int with the number of started activities, in every activity increment it in onStart() and decrement it in onStop().

hackbod
  • 90,665
  • 16
  • 140
  • 154
  • 4
    This works great. If you have a base class for all your activities, it's easy to detect when the application is moved to the foreground (count increment from 0 to 1) and when it is moved to the background (count reached 0). – Jonathan Clément Jul 31 '12 at 14:41
  • This answer fits the title of the post better. If you're interested in detecting whether or not the application enters the background, consider this. It works well for me. – Keith Entzeroth Oct 31 '12 at 13:24
  • if `API > 14` `registerActivityLifecycleCallbacks` method can be used for counter increment/decrement – Mickey Tin Jul 30 '13 at 13:47
  • Simple and efficent. Great. – Niki Romagnoli Jul 23 '15 at 16:48
14

You really don't want to log out the user when the "application" goes in the background, any more than you log out the user of a Web app when the user switches to another tab or minimizes their browser window for a moment. If you were to do either of those things in a Web app, your users would consider your Web app to be an epic fail. Similarly, if the user gets a phone call with a wrong number, or the alarm clock goes off, they'll be rather irritated with you if they have to immediately go back in and sign in when they were just using your app 5 seconds ago. Here, by "irritated", I mean one-star ratings on the Market and nasty comments.

A Web app automatic log out is based upon inactivity, using a server session cookie.

Similarly, when I build a secured Android app, I'll be implementing an inactivity-based mechanism, perhaps something like this:

Step #1: Create a Session class with a static singleton instance. The Session object holds the last-accessed timestamp.

Step #2: In each activity's onResume(), see if the Session singleton exists. If not, it's a brand-new process, so if this isn't the authentication activity, immediately do a startActivity() to bring up the authentication activity.

Step #3: Back in each activity's onResume(), if the Session object exists, call something like extend(). This would return a boolean, true indicating the session is still good (and the timestamp has been updated to now), false otherwise. If it returns false, do the same stuff as if the Session object were null.

Step #4: Your authentication activity, upon success, sets up the singleton Session object with the current timestamp.

Step #5: Your Session class' extend() method is where you make the determination if the session is too old.

No matter how the user gets into your application, if the session is too old (or it's a brand-new process), they are forced to authenticate. Yet, if the user briefly is interrupted -- where you and/or the user can define "briefly" -- they don't have to re-authenticate.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Whoops, that's what I meant, I wanted to auto logout after minutes rather than just logging out every time the app enters the background. For a similar question, one of the suggestions made was to run a service in the background and make it send out a BroadCast to all my activities which will implement broadcast receiver, but this is a much better way to do it. – Tejaswi Yerukalapudi Apr 30 '11 at 19:52
  • @Tejaswi Yerukalapudi: Yeah, the service-and-receiver approach would be rather heavyweight. – CommonsWare Apr 30 '11 at 22:02
  • 2
    It makes sense some applications log out when they go to background, such as banking apps. Just my opinion... – Miguel Ribeiro Apr 04 '12 at 09:28
  • @CommonsWare Such statements as "You really don't want to log out the user when the 'application' goes in the background" seems a bit short-sighted and close-minded. What makes you a judge of what the developer wants to do in a given app? – bugfixr May 01 '13 at 14:22
  • In my case, I need this functionality to put ongoing notification only when the app is sent to background. – akhy Jul 09 '13 at 06:57
  • Context borrowed from Web app is just brilliant! – zionpi Feb 15 '16 at 09:59
1

I think your suggestion is probably the best way to go. Unfortunately I don't think there's an API call to detect if your app is in the background or not. You'll just have to manipulate the onPause() and onResume() methods. Just keep in mind that you'll need need to account for transitions between activities, so once your AtomicInteger reaches 0, I'd wait a short amount of time and recheck that it's still 0 to make sure it wasn't just transitioning activities.

Jason Robinson
  • 31,005
  • 19
  • 77
  • 131
0

Create an Application class and include in the manifest

<application
        android:name="com.example.hello.MyApplication"



public class MyApplication extends Application implements
        ActivityLifecycleCallbacks, ComponentCallbacks2 

override the following method

@Override
public void onTrimMemory(int level) {
        // this method is called when the app goes in background.
        // you can perform your logout service here
        super.onTrimMemory(level);
    }

this is valid of API level 14 and above.

You can even perform the the logout based on the amount of time the app is in background, which i would suggest is a better option. here is what you can do to create as "session timeout"

  1. save the time stamp in SharedPreferences inside the onTrimMemory(int level) method

  2. on all your activities onStrat() get the time stamp from sharedPref and compare it with current time. based on this you can perform a logout.

  3. and clear the shared pref on onCreat of MyApplication

spaceMonkey
  • 4,475
  • 4
  • 26
  • 34