Android: "Application level" Pause and Resume [closed]
Asked Answered
T

3

16

I've been trying to get Application Level Pause and Resume similar to an activity's onPause and onResume. I know there's no API that has this functionality.

I try to follow this post: http://curioustechizen.blogspot.com/2012/12/android-application-level-pause-and.html

But I've had no luck so far.

Has anyone been able to achieve this? What paradigm did you use?

Let me know if you need me to paste some code into this question. Thanks for the help

Training answered 3/1, 2014 at 20:32 Comment(8)
What's wrong with onPause and such?Birthroot
it doesn't exist at the Application level but only for ActivitiesTraining
But couldn't you just use onPause in all of your Activities and have the same code?Birthroot
I am the author of this library. Could you elaborate on what issues you faced? I've been using the library for some of my own projects.Sackbut
Sorry forgot to mention - the idea presented in the blog post is not fool-proof. It doesn't take device rotations into consideration. I used another approach to achieve this - here's the librarySackbut
Hey CuriousTechizen. Your blog post is very well written. The issue I was having was that the service methods weren't being called. I followed your post and the similar answer as best I could. I prolly messed it up somehow. Idk, my understanding of android services isn't exactly great. I did however use the paradigm in the other answer (with a count int). Like I just added that to the application subclass. It works for the purpose I need. Are they any advantages of using a service vs a count int??Training
The library I posted uses a count int as well (in an Application sub-class) :-)Sackbut
vardhan-justlikethat.blogspot.in/2014/02/…Donohoe
S
7

Another solution to the problem would be to just keep track of the count of onStart() and onStop() calls from every activity. Example:

First, create a class to hold the counts:

public class ActiveActivitiesTracker {
    private static int sActiveActivities = 0;

    public static void activityStarted()
    {
        if( sActiveActivities == 0 )
        {
            // TODO: Here is presumably "application level" resume
        }
        sActiveActivities++;
    }

    public static void activityStopped()
    {
        sActiveActivities--;
        if( sActiveActivities == 0 )
        {
            // TODO: Here is presumably "application level" pause
        }
    }
}

Then in every activity, simply call the activityStarted() and activityStopped() methods:

@Override
public void onStart() {
    super.onStart();
    ActiveActivitiesTracker.activityStarted();
}

@Override
public void onStop() {
    super.onStop();
    ActiveActivitiesTracker.activityStopped();
}
Sudduth answered 3/1, 2014 at 23:12 Comment(1)
Also consider using registerActivityLifecycleCallbacks(this);Gentle
A
5

I had the same problem. My aim was to lock the App, if the user abandons it. A simple aim, which i thought would be easy to implement. But all the solutions I found were way to complex. So I came to a simple solution: A time based lock.

Basically it works like this:

  • Start countdown to lock app in onPause
  • Stop countdown in onResume
  • If onResume is not called in time, change to locked

Therefor I created a small little class:

public class ApplicationLock {

private static final String TAG = ApplicationLock.class.getSimpleName();
private static final int LOCK_TIME = 1000; //lock after a second
private static boolean lock = true; //default is locked
private static Handler handler = new Handler();
private static Runnable runnable = new Runnable() {
    @Override
    public void run() {
        lock = true;
        Log.i("ActivityTracker", "App locked");
    }
};

public static boolean activityStarted()
{
    handler.removeCallbacks(runnable);
    if(lock)
    {
        Log.i(TAG, "App resumed - LOCKED");
        return true;
    }else{
        Log.i(TAG, "App resumed - NOT LOCKED");
        return false;
    }
}

public static void activityStopped()
{
    handler.postDelayed(runnable, LOCK_TIME);
    Log.i(TAG, "App paused - Starting countdown");

}

Just call activityStopped() in your activities onPause() and activityStarted() in onResume(). Check the result of activityStarted(). If it returns true, lock your app. If the orientation of the app is changed, onResume will be called very quickly after onPause, so the app will not lock.

This solution might not fit every scenario, but in my case it was the best solution. Additionally you can change the countdown, to increase the user experience (The user pressed a wrong button and returns to the app in a few seconds, no need to lock the app). Hope this is useful to someone else.

Ayeshaayin answered 22/9, 2015 at 12:12 Comment(0)
S
1

I have done something very similar to this in an app which used a service that provided GPS functions by several activities. The idea was to only have the service there when one of the activities that used it is visible, and not there when none are visible. In your case, every activity would hook into a service, and you will know when the entire application was paused or resumed by hooking into the service's onCreate() and onDestroy() methods.

Here is a stripped-down example:

Components needed (these could probably be placed into a utility class if you want to reuse them, or I just had them for each activity class):

private boolean mAppActiveServiceBound = false;
private AppActiveService mAppActiveService = null;
private ServiceConnection mAppActiveConnection = new ServiceConnection() {
    public void onServiceConnected( ComponentName className, IBinder service ) {
        mAppActiveService = ( (AppActiveService.AppActiveBinder) service ).getService();
    }
    public void onServiceDisconnected( ComponentName className ) {
        mAppActiveService = null;
    }
};

Then in your onStart() and onStop() methods for each activity:

@Override
public void onStart() {
    super.onStart();
    mAppActiveServiceBound = bindService( new Intent( this, AppActiveService.class ), mAppActiveConnection, Context.BIND_AUTO_CREATE );
}

@Override
public void onStop() {
    super.onStop();
    if( mAppActiveServiceBound ) {
        unbindService( mAppActiveConnection );
        mAppActiveServiceBound = false;
    }
}

And finally, the service itself:

public class  AppActiveService extends Service {
    // Receives interactions from clients:
    private final IBinder mBinder = new AppActiveBinder();

    /**
     * Provides a handle to the bound service.
     */
    public class  AppActiveBinder extends Binder {
        AppActiveService getService() {
            return AppActiveService.this;
        }
    }

    @Override
    public void onCreate(){
        // TODO: Here is presumably "application level" resume
    }

    @Override
    public void onDestroy(){
        // TODO: Here is presumably "application level" pause
    }
}
Sudduth answered 3/1, 2014 at 21:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.