检查android应用程序是否在前台?

时间:2011-12-13 13:23:43

标签: android

我为这个问题找了很多答案。但这都是关于单一活动的。如何检查整个应用程序是否在前台运行?

15 个答案:

答案 0 :(得分:109)

我不明白你想要什么,但你可以通过ActivityManager.getRunningAppProcesses()电话检测当前的前台/后台应用程序。

类似的东西,

class ForegroundCheckTask extends AsyncTask<Context, Void, Boolean> {

  @Override
  protected Boolean doInBackground(Context... params) {
    final Context context = params[0].getApplicationContext();
    return isAppOnForeground(context);
  }

  private boolean isAppOnForeground(Context context) {
    ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
    if (appProcesses == null) {
      return false;
    }
    final String packageName = context.getPackageName();
    for (RunningAppProcessInfo appProcess : appProcesses) {
      if (appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) {
        return true;
      }
    }
    return false;
  }
}

// Use like this:
boolean foregroud = new ForegroundCheckTask().execute(context).get();

如果我误解了,也请告诉我。

更新:请查看此问题Determining the current foreground application from a background task or service了解更多信息..

谢谢..

答案 1 :(得分:38)

@ user370305的答案容易出错且Android操作系统开发人员不鼓励(查看https://groups.google.com/forum/#!msg/android-developers/zH-2bovZSLg/L2YM8Z1N-HwJ

有一种更简单的方法:

在所有活动扩展的 BaseActivity

protected static boolean isVisible = false;

@Override
public void onResume() {
   super.onResume();
   setVisible(true);
}

@Override
public void onPause() {
    super.onPause();
    setVisible(false);
}

每当您需要检查您的任何应用程序活动是否在前台时,请检查 isVisible();

要了解此方法,请查看并排活动生命周期的答案:Activity side-by-side lifecycle

答案 2 :(得分:33)

我迄今为止发现的最新且未被弃用的方式如下:

@Override
public boolean foregrounded() {
    ActivityManager.RunningAppProcessInfo appProcessInfo = new ActivityManager.RunningAppProcessInfo();
    ActivityManager.getMyMemoryState(appProcessInfo);
    return (appProcessInfo.importance == IMPORTANCE_FOREGROUND || appProcessInfo.importance == IMPORTANCE_VISIBLE)
}

仅适用于SDK 16 +。

修改

我从解决方案中删除了以下代码:

KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
// App is foreground, but screen is locked, so show notification
return km.inKeyguardRestrictedInputMode();

因为如果屏幕锁定,则不会收到通知。我看一下框架,目的并不完全清楚。我删除它。检查进程信息状态就足够了: - )

答案 3 :(得分:14)

借助新的Android生命周期扩展架构,我们可以轻松实现这一目标。

确保在build.gradle文件中提取此依赖项:

dependencies {
    implementation "android.arch.lifecycle:extensions:1.1.0"
}

然后在Application类中使用:

class ArchLifecycleApp : Application(), LifecycleObserver {

    override fun onCreate() {
        super.onCreate()
        ProcessLifecycleOwner.get().lifecycle.addObserver(this)
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun onAppBackgrounded() {
        Log.d("MyApp", "App in background")
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    fun onAppForegrounded() {
        Log.d("MyApp", "App in foreground")
    }
}

最后,使用以下命令更新AndroidManifest.xml文件

<application
    android:name=".ArchLifecycleApp"
    //Your extra code
    ....>
</application>

现在,每次Application转到Foreground或Background时,我们都会收到与声明的两个方法相关的Logs。

答案 4 :(得分:10)

我已尝试使用运行过程中的包过滤器。但这很奇怪。而不是那样,我尝试了新的解决方案,这完美。我已经多次检查并通过这个模块获得了完美的结果。

private int numRunningActivities = 0;

 public void onCreate() {
        super.onCreate();
this.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {

                @Override
                public void onActivityStarted(Activity activity) {
                    numRunningActivities++;
                    if (numRunningActivities == 1) {
                        LogUtils.d("APPLICATION", "APP IN FOREGROUND");
                    }

                }

                @Override
                public void onActivityStopped(Activity activity) {

                    numRunningActivities--;
                    if (numRunningActivities == 0) {
                       Log.e("", "App is in BACKGROUND") 
                    }
                }


                @Override
                public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
                }

                @Override
                public void onActivityResumed(Activity activity) {
                }

                @Override
                public void onActivityPaused(Activity activity) {
                }

                @Override
                public void onActivityDestroyed(Activity activity) {
                }

                @Override
                public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                }
            });
}

答案 5 :(得分:9)

检查应用是在后台还是前台。如果应用程序处于后台,此方法将返回true。

首先将GET_TASKS权限添加到AndroidManifest.xml

<img id="button" class="faver fave0 tog" src="favscript/images/<?php echo in_array(3, $allFavIds) ? '1.jpg' : '0.jpg' ; ?>" onclick="" width="54" height="49">

答案 6 :(得分:3)

Android体系结构组件库您可以使用ProcessLifecycleOwner为onStart和onStop事件设置整个应用程序进程的侦听器。为此,请使应用程序类实现LifecycleObserver接口,并将onStop和onStart的一些注释添加到前台和后台方法中。

class ArchLifecycleApp : Application(), LifecycleObserver {

    override fun onCreate() {
        super.onCreate()
        ProcessLifecycleOwner.get().lifecycle.addObserver(this)
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun onAppBackgrounded() {
        Log.d("Awww", "App in background")
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    fun onAppForegrounded() {
        Log.d("Yeeey", "App in foreground")
    }

}

答案 7 :(得分:2)

我通过创建基本活动类找到了一个简单的解决方案,你必须扩展所有活动类:

public class BaseActivity extends ActionBarActivity {

@Override
protected void onResume() {
    ApplicationStateChecker.view_resumed(this);
    super.onResume();
}

@Override
protected void onStop() {
    ApplicationStateChecker.view_stopped(this);
    super.onStop();

}

@Override
protected void onPause() {
    ApplicationStateChecker.view_paused(this);
    super.onPause();

}

}

ApplicationStateChecker类:​​

public class ApplicationStateChecker {

private  static final String _pause_string = "paused";
private  static final String _resume_string = "resumed";

private static String _view_lastState;
private static boolean _from_background = true;

public static void view_paused(Activity activity){
    _view_lastState = _pause_string;
}

public static void view_stopped(Activity activity){

    if (  _view_lastState.equals(_pause_string) ){
        //if stop called and last event was pause then app is brought to background
        _from_background = true;
    }  //if

}

public static void view_resumed(Activity activity){

    if (  _from_background ) {
       //Do your stuff here , app is brought to foreground 

    }  //if

    _from_background = false;
    _view_lastState = _resume_string;
}

答案 8 :(得分:2)

cesards的答案是正确的,但仅适用于API&gt; 15.对于较低的API版本,我决定使用getRunningTasks()方法:

   private boolean isAppInForeground(Context context)
    {
        if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
        {
            ActivityManager am = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
            ActivityManager.RunningTaskInfo foregroundTaskInfo = am.getRunningTasks(1).get(0);
            String foregroundTaskPackageName = foregroundTaskInfo.topActivity.getPackageName();

            return foregroundTaskPackageName.toLowerCase().equals(context.getPackageName().toLowerCase());
        }
        else
        {
            ActivityManager.RunningAppProcessInfo appProcessInfo = new ActivityManager.RunningAppProcessInfo();
            ActivityManager.getMyMemoryState(appProcessInfo);
            if (appProcessInfo.importance == IMPORTANCE_FOREGROUND || appProcessInfo.importance == IMPORTANCE_VISIBLE)
            {
                return true;
            }

            KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
            // App is foreground, but screen is locked, so show notification
            return km.inKeyguardRestrictedInputMode();
        }
    }

请让我知道它是否适合所有人。

答案 9 :(得分:1)

此处没有全局回调,但对于每个活动,它都是onStop()。你不需要搞乱一个原子int。只需要一个包含已启动活动数的全局int,在每个活动中增加onStart()并在onStop()中递减它。

public class BaseActivity extends ActionBarActivity {
public static int count = 0;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}


@Override
protected void onStart() {
    super.onStart();
    count = count + 1;
    Log.d(TAG, "onStart" + count);
    if (count == 1) {

       Toast.makeText(getApplicationContext(), "online", Toast.LENGTH_SHORT).show();

    }

}



protected void onStop() {
    super.onStop();
    count = count - 1;
    if (count == 0) {

        Toast.makeText(getApplicationContext(), "offline", Toast.LENGTH_SHORT).show();

    }
}


}

答案 10 :(得分:1)

在Application类中尝试ActivityLifecycleCallbacks。

答案 11 :(得分:1)

以下是最新Android SDK的更新解决方案。

String PackageName = context.getPackageName();
        ActivityManager manager = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
        ComponentName componentInfo;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
        {
            List<ActivityManager.AppTask> tasks = manager.getAppTasks();
            componentInfo = tasks.get(0).getTaskInfo().topActivity;
        }
        else
        {
            List<ActivityManager.RunningTaskInfo> tasks = manager.getRunningTasks(1);
            componentInfo = tasks.get(0).topActivity;
        }

        if (componentInfo.getPackageName().equals(PackageName))
            return true;
        return false;

希望这有帮助,谢谢。

答案 12 :(得分:0)

基于 getRunningTasks()的解决方案都不适用于最近的Android版本, getRunningTasks()在API级别21中已弃用。即使它仍然使用它也会没有返回足够的信息来确定应用程序是否在前台。

而是扩展Application类并使用Application.ActivityLifecycleCallbacks来跟踪应用程序可见性状态。

public class MyApplication extends Application {
    static final String APP_STATE_FOREGROUND = "com.xxx.appstate.FOREGROUND";
    static final String APP_STATE_BACKGROUND = "com.xxx.appstate.BACKGROUND";
    private static int m_foreground = -1;
    private Handler m_handler = new Handler();
    private Runnable m_guard;

    public static boolean isForeground() {
        return m_foreground == 1;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {

            @Override
            public void onActivityCreated(Activity activity, Bundle bundle) {
            }

            @Override
            public void onActivityStarted(Activity activity) {
            }

            @Override
            public void onActivityResumed(Activity activity) {
                if(m_guard != null) {
                    m_handler.removeCallbacks(m_guard);
                    m_guard = null;
                }
                if(m_foreground == 1)
                    return;
                m_foreground = 1;
                sendBroadcast(new Intent(APP_STATE_FOREGROUND));
            }

            @Override
            public void onActivityPaused(Activity activity) {
                if(m_foreground == 0)
                    return;
                /*
                 * Use a 400ms guard to protect against jitter
                 * when switching between two activities
                 * in the same app
                 */
                m_guard = new Runnable() {
                    @Override
                    public void run() {
                        if(m_foreground == 1) {
                            m_foreground = 0;
                            sendBroadcast(new Intent(APP_STATE_BACKGROUND));
                        }
                    }
                };
                m_handler.postDelayed(m_guard, 400);
            }

            @Override
            public void onActivityStopped(Activity activity) {
            }

            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
            }

            @Override
            public void onActivityDestroyed(Activity activity) {
            }
        });
    }
}

使用400ms保护计时器可消除在同一应用程序中的活动之间切换时对背景状态的错误检测。可以使用以下方式随时查询后台/前台状态:

MyApplication.isForeground();

如果一个类对状态转换感兴趣,它也可以监听广播事件:

private static IntentFilter m_appStateFilter;

static {
    m_appStateFilter = new IntentFilter();
    m_appStateFilter.addAction(MyApplication.APP_STATE_FOREGROUND);
    m_appStateFilter.addAction(MyApplication.APP_STATE_BACKGROUND);
}

private BroadcastReceiver m_appStateReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (action.equals(MyApplication.APP_STATE_FOREGROUND)) {
            /* application entered foreground */
        } else if (action.equals(MyApplication.APP_STATE_BACKGROUND)) {
            /* application entered background */
        }
    }
};
registerReceiver(m_appStateReceiver, m_appStateFilter);

答案 13 :(得分:0)

以下解决方案适用于API级别14 +

Backgrounding ComponentCallbacks2 - 查看文档并不是100%清楚如何使用它。但是,仔细看看你会注意到onTrimMemory方法传入一个标志。这些标志通常与内存可用性有关,但我们关心的是TRIM_MEMORY_UI_HIDDEN。通过检查UI是否隐藏,我们可以假设应用程序现在处于后台。不完全明显,但应该有效。

前景化 ActivityLifecycleCallbacks - 我们可以通过覆盖onActivityResumed和跟踪当前应用程序状态(前景/背景)来检测前景。

创建将由自定义Application类实现的接口

interface LifecycleDelegate {
    fun onAppBackgrounded()
    fun onAppForegrounded()
}

创建一个将实现ActivityLifecycleCallbacks和ComponentCallbacks2并覆盖onActivityResumed和onTrimMemory方法的类

// Take an instance of our lifecycleHandler as a constructor parameter
class AppLifecycleHandler(private val lifecycleDelegate: LifecycleDelegate) 
: Application.ActivityLifecycleCallbacks, ComponentCallbacks2 // <-- Implement these 
  {
private var appInForeground = false

      // Override from Application.ActivityLifecycleCallbacks
    override fun onActivityResumed(p0: Activity?) {
       if (!appInForeground) {
          appInForeground = true
          lifecycleDelegate.onAppForegrounded()
       }
    }

      // Override from ComponentCallbacks2
    override fun onTrimMemory(level: Int) { 
       if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
       // lifecycleDelegate instance was passed in on the constructor
          lifecycleDelegate.onAppBackgrounded()
       }
    }
}

现在我们需要做的就是让我们的自定义Application类实现我们的LifecycleDelegate接口并注册。

class App : Application(), LifeCycleDelegate {

    override fun onCreate() {
        super.onCreate()
        val lifeCycleHandler = AppLifecycleHandler(this)
        registerLifecycleHandler(lifeCycleHandler)
    }

    override fun onAppBackgrounded() {
        Log.d("Awww", "App in background")
    }

    override fun onAppForegrounded() {
        Log.d("Yeeey", "App in foreground")
    }

    private fun registerLifecycleHandler(lifeCycleHandler: AppLifecycleHandler) {
        registerActivityLifecycleCallbacks(lifeCycleHandler)
        registerComponentCallbacks(lifeCycleHandler)
    }

}

在Manifest中设置CustomApplicationClass

<application
        android:name=".App"

答案 14 :(得分:0)

在Android 19中,您可以在Application类的onCreate()中注册应用程序生命周期回调,如下所示:

@Override
public void onCreate() {
    super.onCreate();
    registerActivityLifecycleCallbacks(new AppLifecycleCallback());
}

AppLifecycleCallback如下所示:

class AppLifecycleCallback implements Application.ActivityLifecycleCallbacks {
    private int numStarted = 0;

    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {

    }

    @Override
    public void onActivityStarted(Activity activity) {
        if (numStarted == 0) {
           //app went to foreground
        }
        numStarted++;
    }

    @Override
    public void onActivityResumed(Activity activity) {

    }

    @Override
    public void onActivityPaused(Activity activity) {

    }

    @Override
    public void onActivityStopped(Activity activity) {
        numStarted--;
        if (numStarted == 0) {
            // app went to background
        }
    }

    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

    }

    @Override
    public void onActivityDestroyed(Activity activity) {

    }
}