我查看了很多关于这个问题的答案,但它们都只涉及单个活动。如何检查整个应用程序是否在前台运行?
我查看了很多关于这个问题的答案,但它们都只涉及单个活动。如何检查整个应用程序是否在前台运行?
我不明白您想要什么,但是您可以使用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();
如果我理解有误,请告诉我。
更新:查看此SO问题Determining the current foreground application from a background task or service了解更多信息。
谢谢。
2020年10月更新:在本文中查看基于生命周期扩展的解决方案。这种方法似乎有效,更加优雅和现代。
到目前为止,我发现最整洁且未被弃用的方法如下:
@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();
因为这会导致在屏幕锁定时无法收到通知。我查看了框架,发现其目的并不是完全清晰的。我建议将其移除。检查进程信息状态已足够 :-)
@user370305的答案容易出错,而且被 Android OS 开发者不推荐使用(请查看https://groups.google.com/forum/#!msg/android-developers/zH-2bovZSLg/L2YM8Z1N-HwJ)
更为简单的方法是:
在所有 Activity 继承的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
通过新的Android Architecture的Lifecycle extensions,我们可以非常容易地实现这一点。
只需确保在您的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>
现在,每当应用程序进入前台或后台,我们都会接收到与声明的两种方法相关联的日志。
更新:@OnLifecycleEvent
已被弃用
@OnLifecycleEvent注释需要使用代码生成或反射,这应该避免使用。改用DefaultLifecycleObserver或LifecycleEventObserver。有关更多信息,请参见此示例
ArchLifecycleApp
的onCreate
函数中检查它是否在前台。 - android developer使用Android架构组件库,您可以使用ProcessLifecycleOwner
设置整个应用程序进程的onStart
和onStop
事件的监听器。为此,请使您的应用程序类实现LifecycleObserver
接口,并将一些注释添加到前台和后台方法的onStart
和onStop
。
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")
}
}
implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"
作为依赖项。 - Vít Kapitola我已经尝试使用运行进程的包过滤器,但那很奇怪。相反,我尝试了新的解决方案,这个完美地工作了。我检查了很多次,并通过此模块获得了完美的结果。
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) {
}
});
}
检查应用程序是否在后台或前台。如果应用程序在后台,此方法将返回true。
首先,在AndroidManifest.xml文件中添加GET_TASKS权限。
private boolean isAppIsInBackground(Context context) {
boolean isInBackground = true;
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH) {
List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) {
if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
for (String activeProcess : processInfo.pkgList) {
if (activeProcess.equals(context.getPackageName())) {
isInBackground = false;
}
}
}
}
} else {
List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
ComponentName componentInfo = taskInfo.get(0).topActivity;
if (componentInfo.getPackageName().equals(context.getPackageName())) {
isInBackground = false;
}
}
return isInBackground;
}
没有全局回调函数,但对于每个活动(activity),它是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();
}
}
}
我发现了一个简单的解决方法,通过创建一个基础活动类,您必须从这个类扩展所有的活动类:
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;
}
Application
并且实现Application.ActivityLifecycleCallbacks
接口的MainApplication
类。https://developer.android.com/reference/android/app/Application.ActivityLifecycleCallbacks - Pierrecesards的回答是正确的,但只适用于API版本>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();
}
}
请告诉我这是否适用于您所有人。