Artur Szymański
Artur Szymański

Reputation: 1648

Best way to determine when app is foreground

I would like to ask You about best way to determine that my app is currently visible to user (foreground). I know there are two solutions:

  1. Using ActivityManager but this is very expensive way.
  2. Create any boolean variable and change its state in onResume() and onPause() of every Activity. This solution has one main disadvantage additional code to remember about.

Do you know any other, better way? What do you think, whats better and why?

EDIT


According to my second sollution skywell suggest that we can create an Activity where in onResume() and onPause() we can change state of our boolean variable. Every Activity in application should extends our new Activity. But this idea generate few new problems:

  1. We have to duplicate that new Activity for every kind (For example ActionBarActivity) of needed Activity.
  2. We still have to remember about extends correct Activity, it can be problematic in larger teams.

Great explanation of my second solution is provide in DroidAks's post.

Upvotes: 0

Views: 93

Answers (2)

DreamOnJava
DreamOnJava

Reputation: 655

Answer made by DroidAks is good, but not good enough. As we all know, having state in static variables isn't the prettiest thing to do. Doing that means that You have to remember that You need to manage this state and clean it up. Also, in this case, having static variables in Application class means that Your classes will be solely reliant on this particular Application class. What if You'd like to make a library out of Your code, which would be used in many apps?

Here is my proposal:

public class MyApplication extends Application
{
    private boolean visible;
    public boolean isVisible()
    {
        return visible;
    } 
    //use Application events to manage app visibility state
}

While in Your Activity code:

public class MyActivity extends Activity
{
    @Override
    protected void onResume() 
    {
        super.onResume();
        MyApplication myApp = (MyApplication)this.getApplication();
        //myApp.isVisible();
    }
}

If the above MyApplication class implementation was not enough (there may be trouble with setting visible to false ), then move on to even more proper solution of this problem:

public /*abstract*/ class MyActivity extends Activity
{
    private boolean visible;
    protected boolean isVisible()
    {
        return visible;
    } 
    //use Activity events to manage activity visibility state
    //for ex.
    @Override
    protected void onResume() 
    {
        super.onResume();
        visible = true;
    }
}

public class MyConcreteActivity extends MyActivity
{
    @Override
    protected void onResume() 
    {
        super.onResume(); // calls onResume from base MyActivity,
                          // thus always setting visible state properly
        //isVisible();
    }
}

Remember to update Your manifest file accordingly.

EDIT


We have to duplicate that new Activity for every kind (For example ActionBarActivity) of needed Activity. We still have to remember about extends correct Activity, it can be problematic in larger teams.

All of above is solved by having an interface, that is passed around to classes requiring functionality of asking the object about its visibility state.

public interface Hideable
{
   boolean isVisible();
}

If one would like to use Your class, then this class should explicitly have Hideable interface as one of its constructor/public method parameters. If You would like to restrict the parameter to extend Activity AND implement Hideable then this generic example (with wildcard usage) is right thing to do:

//TODO design new parameter name
public <T extends Activity & Hideable> void myMethod(T iNeedToBeHideableActivity)

After seeing such a method, the developer should:

  1. Extend one of pre-defined activities already implementing this interface.
  2. Or implement this interface in their own activity.
  3. Ask You about what exactly is a wildcard.

The requirement of proper behavior is obvious in this case - the interface should announce, whether particular object is visible or not.

PS. This is not a very ugly duplication, as each implementation could be different in some ways. For example, Application class lacks onDestroy event, so implementation of Hideable interface should be different there.

EDIT


Improved above suggestion by adding generics.

Upvotes: 0

DroidAks
DroidAks

Reputation: 327

If you want to track whether the app is in foreground or not. This might be the best way. Check for the states of your app by yourself using Activity.onPause, Activity.onResume methods. Store "visibility" status in some other class. Now implementat your own Application class as:

public class MyApplication extends Application 
{

    public static boolean isActivityVisible()
    {
       return activityVisible;
    }  

    public static void activityResumed() 
    {
        activityVisible = true;
    }

    public static void activityPaused() 
    {
        activityVisible = false;
    }

    private static boolean activityVisible;
    }

Now add onResume() and onPause() in every activity

We can use AndroidLifecycleCallbacks to track whether the app is currently visible to user or not. AndroidLifecycleCallbacks were added in API level 14. Hope it helps you.

@Override
protected void onResume() {
super.onResume();
MyApplication.activityResumed();
}

@Override
protected void onPause() {
super.onPause();
MyApplication.activityPaused();
}

Also add in your manifest following code.

<application
android:name="your.app.package.MyApplication"
android:icon="@drawable/icon"
android:label="@string/app_name" >

Upvotes: 1

Related Questions