How can I tell if Android app is running in the fo

2019-01-03 02:02发布

I am doing a status bar notification in my android app that is triggered by c2dm. I don't want to display the notification if the app is running. How do you determine if the app is running and is in the foreground?

18条回答
Luminary・发光体
2楼-- · 2019-01-03 02:13

Here's the code for nice simple solution described above by @user2690455 . Although it looks a bit verbose, you'll see overall it's actually quite light-weight

In my case we also use AppCompatActivity, so I had to have 2 base classes.

public class BaseActivity extends Activity {

    /**
     * Let field be set only in base class
     * All callers must use accessors,
     * and then it's not up to them to manage state.
     *
     * Making it static since ..
     * 1. It needs to be used across two base classes
     * 2. It's a singleton state in the app
     */
    private static boolean IS_APP_IN_BACKGROUND = false;

    @Override
    protected void onResume() {
        super.onResume();

        BaseActivity.onResumeAppTracking(this);

        BaseActivity.setAppInBackgroundFalse();
    }

    @Override
    protected void onStop() {
        super.onStop();

        BaseActivity.setAppInBackgroundTrue();
    }

    @Override
    protected void onPause() {
        super.onPause();

        BaseActivity.setAppInBackgroundFalse();
    }

    protected static void onResumeAppTracking(Activity activity) {

        if (BaseActivity.isAppInBackground()) {

            // do requirements for returning app to foreground
        }

    }

    protected static void setAppInBackgroundFalse() {

        IS_APP_IN_BACKGROUND = false;
    }

    protected static void setAppInBackgroundTrue() {

        IS_APP_IN_BACKGROUND = true;
    }

    protected static boolean isAppInBackground() {

        return IS_APP_IN_BACKGROUND;
    }
}
查看更多
倾城 Initia
3楼-- · 2019-01-03 02:14

I found a more simpler and accurate way to check if the application is in foreground or background by mapping the activities to boolean.

Check the complete gist here

查看更多
狗以群分
4楼-- · 2019-01-03 02:16

Alternately, you can check with the ActivityManager what tasks are running by getRunningTasks method. Then check with the first task(task in the foreground) in the returned List of tasks, if it is your task.
Here is the code example:

public Notification buildNotification(String arg0, Map<String, String> arg1) {

    ActivityManager activityManager = (ActivityManager) appContext.getSystemService(Context.ACTIVITY_SERVICE);
    List<RunningTaskInfo> services = activityManager
            .getRunningTasks(Integer.MAX_VALUE);
    boolean isActivityFound = false;

    if (services.get(0).topActivity.getPackageName().toString()
            .equalsIgnoreCase(appContext.getPackageName().toString())) {
        isActivityFound = true;
    }

    if (isActivityFound) {
        return null;
    } else {
        // write your code to build a notification.
        // return the notification you built here
    }

}

And don't forget to add the GET_TASKS permission in the manifest.xml file in order to be able to run getRunningTasks() method in the above code:

<uses-permission android:name="android.permission.GET_TASKS" />

p/s : If agree this way, please to note that this permission now is deprecated.

查看更多
一纸荒年 Trace。
5楼-- · 2019-01-03 02:16

This is a pretty old post but still quite relevant. The above accepted solution may work but is wrong. As Dianne Hackborn wrote:

These APIs are not there for applications to base their UI flow on, but to do things like show the user the running apps, or a task manager, or such.

Yes there is a list kept in memory for these things. However, it is off in another process, managed by threads running separately from yours, and not something you can count on (a) seeing in time to make the correct decision or (b) have a consistent picture by the time you return. Plus the decision about what the "next" activity to go to is always done at the point where the switch is to happen, and it is not until that exact point (where the activity state is briefly locked down to do the switch) that we actually know for such what the next thing will be.

And the implementation and global behavior here is not guaranteed to remain the same in the future.

The correct solution is to implement : ActivityLifeCycleCallbacks.

This basically needs an Application Class and the handler can be set in there to identify the state of your activities in the app.

查看更多
Ridiculous、
6楼-- · 2019-01-03 02:21

FYI, if you use Gadenkan solution (which is great!!) don't forget to add

<uses-permission android:name="android.permission.GET_TASKS" />

to the manifest.

查看更多
冷血范
7楼-- · 2019-01-03 02:24

The previous approaches mentioned here are not optimal. The task based approach requires a permission that might not be desired and "Boolean" approach is prone to concurrent modification mess ups.

The approach I use and which (I believe) works quite well in most cases:

Have a "MainApplication" class to track activity count in AtomicInteger:

import android.app.Application;

import java.util.concurrent.atomic.AtomicInteger;

public class MainApplication extends Application {
    static class ActivityCounter {
        private static AtomicInteger ACTIVITY_COUNT = new AtomicInteger(0);

        public static boolean isAppActive() {
            return ACTIVITY_COUNT.get() > 0;
        }

        public static void activityStarted() {
            ACTIVITY_COUNT.incrementAndGet();
        }

        public static void activityStopped() {
            ACTIVITY_COUNT.decrementAndGet();
        }
    }
}

And create a base Activity class that other activities would extend:

import android.app.Activity;
import android.support.annotation.CallSuper;

public class TestActivity extends Activity {
    @Override
    @CallSuper
    protected void onStart() {
        MainApplication.ActivityCounter.activityStarted();
        super.onStart();
    }

    @Override
    @CallSuper
    protected void onStop() {
        MainApplication.ActivityCounter.activityStopped();
        super.onStop();
    }
}
查看更多
登录 后发表回答