【问题标题】:Android: how do I check if activity is running?Android:如何检查活动是否正在运行?
【发布时间】:2011-07-23 17:24:49
【问题描述】:

是否有任何简单的方法可以确定某个活动是否处于活动状态? 我想根据活动的活动来做某些事情。 例如:

if(activityrunning == activity1)
//do this
else if (activityrunning == activity2)
//do something else

【问题讨论】:

标签: android android-activity


【解决方案1】:

您可以在活动中使用static 变量。

class MyActivity extends Activity {
     static boolean active = false;

      @Override
      public void onStart() {
         super.onStart();
         active = true;
      } 

      @Override
      public void onStop() {
         super.onStop();
         active = false;
      }
}

唯一的问题是,如果你在两个相互链接的活动中使用它,那么第一个上的onStop 有时会在第二个onStart 之后调用。所以两者都可能是正确的。

取决于您要做什么(从服务更新当前活动?)。您可以在您的活动onStart 方法中的服务中注册一个静态侦听器,然后当您的服务想要更新 UI 时,正确的侦听器将可用。

【讨论】:

  • 有人向我指出,由于内存泄漏问题,Sharedpreference 应该优于静态变量。
  • 如果同一个班级有不同的活动在运行怎么办?如果您将MyActivity 扩展为MyChildactivity 并想检查孩子是否处于活动状态怎么办?
  • 根据您对“运行”的定义,您可能希望更改 onResume 和 onPause 中的变量状态....
  • 这个解决方案根本不是一个好的解决方案。假设您的 Activity 调用了 Fragment,例如,Fragment 将在 Activity 之上,但 Activity 不会调用 onPause,并且如果您关闭 Fragment,onStop、onStart 或任何其他生命周期方法也不会被调用。最好的解决方案是检查您的应用程序类的可见性,如下所述:stackoverflow.com/questions/18038399/…
  • 如果你推荐静态,你会得到我的 -1
【解决方案2】:

我意识到这个问题已经很老了,但我认为仍然值得分享我的解决方案,因为它可能对其他人有用。

在 Android 架构组件发布之前,此解决方案不可用。

活动至少部分可见

getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)

活动在前台

getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)

【讨论】:

  • getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)
【解决方案3】:

我觉得这样更清楚:

  public boolean isRunning(Context ctx) {
        ActivityManager activityManager = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);
        List<RunningTaskInfo> tasks = activityManager.getRunningTasks(Integer.MAX_VALUE);

        for (RunningTaskInfo task : tasks) {
            if (ctx.getPackageName().equalsIgnoreCase(task.baseActivity.getPackageName())) 
                return true;                                  
        }

        return false;
    }

【讨论】:

  • 我尽量避免在“for”循环之前创建临时变量; for (RunningTaskInfo 任务: ActivityManager.getRunningTasks(Integer.MAX_VALUE)) { ...
  • 这个函数怎么调用?
  • 像往常一样,是一种可以在类中作为“函数”调用的方法,你需要一个例子吗?
  • 来自developer.android.com/reference/android/app/… "这不应该用于应用程序中的核心逻辑,例如根据此处找到的信息来决定不同的行为。不支持这样的使用,并且可能会中断未来。”
  • 从 API 级别 21 (Android 5.0 Lollipop) 开始,此方法已被弃用。
【解决方案4】:

不使用任何辅助变量的选项是:

activity.getWindow().getDecorView().getRootView().isShown()

activity 是 f.e.:this 或 getActivity()。

此表达式返回的值在 onStart() / onStop() 中发生变化,它们是启动/停止显示手机上 Activity 布局的事件。

【讨论】:

  • 为什么不直接使用Activity#getWindow().getDecorView().isShown()
【解决方案5】:

我使用了 MyActivity.class 和 getCanonicalName 方法,我得到了答案。

protected Boolean isActivityRunning(Class activityClass)
{
        ActivityManager activityManager = (ActivityManager) getBaseContext().getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningTaskInfo> tasks = activityManager.getRunningTasks(Integer.MAX_VALUE);

        for (ActivityManager.RunningTaskInfo task : tasks) {
            if (activityClass.getCanonicalName().equalsIgnoreCase(task.baseActivity.getClassName()))
                return true;
        }

        return false;
}

【讨论】:

【解决方案6】:

比使用静态变量并遵循 OOP 更好的方法

Shared Preferences 可用于与其他activities 和来自一个application 的服务共享变量

    public class example extends Activity {

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

        // Store our shared preference
        SharedPreferences sp = getSharedPreferences("OURINFO", MODE_PRIVATE);
        Editor ed = sp.edit();
        ed.putBoolean("active", true);
        ed.commit();
    }

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

        // Store our shared preference
        SharedPreferences sp = getSharedPreferences("OURINFO", MODE_PRIVATE);
        Editor ed = sp.edit();
        ed.putBoolean("active", false);
        ed.commit();

    }
}

使用共享偏好。它拥有最可靠的状态信息,更少的应用程序切换/销毁问题,让我们不必再请求另一个权限,并且它让我们有更多的控制权来决定我们的活动何时实际上是最顶层的。见details hereabdhere also

【讨论】:

  • 谢谢。但是兄弟也需要 onResume 吗?
  • 这取决于你对active的理解。根据我的代码,活动在堆栈中然后它是活动的。如果你想处理可见或不可见,那么你可以使用 onResume
  • 在没有调用 onStop() 的情况下杀死活动时会中断
  • 如果应用崩溃会怎样?
  • 这是一个非常危险的“解决方案”。
【解决方案7】:

这是用于检查特定服务是否正在运行的代码。只要您使用 getRunningAppProcesses() 或 getRunningTasks() 更改 getRunningServices,我相当确定它也可以用于活动。看看这里http://developer.android.com/reference/android/app/ActivityManager.html#getRunningAppProcesses()

相应地更改 Constants.PACKAGE 和 Constants.BACKGROUND_SERVICE_CLASS

    public static boolean isServiceRunning(Context context) {

    Log.i(TAG, "Checking if service is running");

    ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);

    List<RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);

    boolean isServiceFound = false;

    for (int i = 0; i < services.size(); i++) {

        if (Constants.PACKAGE.equals(services.get(i).service.getPackageName())){

            if (Constants.BACKGROUND_SERVICE_CLASS.equals(services.get(i).service.getClassName())){
                isServiceFound = true;
            }
        }
    }

    Log.i(TAG, "Service was" + (isServiceFound ? "" : " not") + " running");

    return isServiceFound;

}

【讨论】:

  • 但请记住,您提供的链接指出“此方法仅用于调试或构建面向用户的流程管理 UI。”
  • getRunningTasks 现已弃用。
【解决方案8】:
if(!activity.isFinishing() && !activity.isDestroyed())

来自官方文档:

Activity#isFinishing()

检查此活动是否正在完成,或者是因为您在其上调用了finish(),或者其他人已请求它完成。这通常用于 onPause() 来确定活动是简单暂停还是完全结束。

Activity#isDestroyed()

如果对 Activity 进行了最后的 onDestroy() 调用,则返回 true,因此该实例现在已死。

【讨论】:

    【解决方案9】:

    感谢 kkudi!我能够调整您的答案以适用于某项活动......这就是我的应用程序中的工作......

    public boolean isServiceRunning() { 
    
    ActivityManager activityManager = (ActivityManager)Monitor.this.getSystemService (Context.ACTIVITY_SERVICE); 
        List<RunningTaskInfo> services = activityManager.getRunningTasks(Integer.MAX_VALUE); 
        isServiceFound = false; 
        for (int i = 0; i < services.size(); i++) { 
            if (services.get(i).topActivity.toString().equalsIgnoreCase("ComponentInfo{com.lyo.AutoMessage/com.lyo.AutoMessage.TextLogList}")) {
                isServiceFound = true;
            }
        } 
        return isServiceFound; 
    } 
    

    如果 topActivity 与用户正在执行的操作相匹配,此示例将为您提供 true 或 false。因此,如果您检查的活动未显示(即 onPause),那么您将不会得到匹配。此外,要执行此操作,您需要将权限添加到清单中。..

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

    希望对您有所帮助!

    【讨论】:

    • 此使用权限在 API 级别 21 中已弃用。developer.android.com/reference/android/…
    • 否决答案,因为要访问顶级活动(services[i].topActivity),我们最低 API 级别 Q 。低于该级别将不起作用。
    【解决方案10】:

    有一种比上述方法更简单的方法,这种方法不需要在清单中使用android.permission.GET_TASKS,也不需要在接受的答案中指出竞争条件或内存泄漏的问题。

    1. 在主 Activity 中创建一个 STATIC 变量。静态允许其他活动从另一个活动接收数据。 onPause() 设置此变量falseonResumeonCreate() 设置此变量true

      private static boolean mainActivityIsOpen;
      
    2. 分配这个变量的getter和setter。

      public static boolean mainActivityIsOpen() {
          return mainActivityIsOpen;
      }
      
      public static void mainActivityIsOpen(boolean mainActivityIsOpen) {
          DayView.mainActivityIsOpen = mainActivityIsOpen;
      }
      
    3. 然后来自另一个活动或服务

      if (MainActivity.mainActivityIsOpen() == false)
      {
                      //do something
      }
      else if(MainActivity.mainActivityIsOpen() == true)
      {//or just else. . . ( or else if, does't matter)
              //do something
      }
      

    【讨论】:

    • 你是说使用访问器方法比使用原始公共静态变量更好?
    • 在 Java 中最好使用 setter 和 getter 来保持变量的私有性。但是,我相信在 Android 中直接访问公共变量是很常见的......
    • 拥有一个公共设置器是没有意义的,因为活动状态应该只由活动本身处理。您应该坚持使用 java 命名约定: isActivityOpen 将是一个正确的 getter 方法。也使用 if boolean == true 是多余的。除此之外,将状态管理委托给 Activity 是最好的方法。
    • 这就是为什么你应该更加努力地参加你的课程@coolcool ;)
    • 如果您有多个正在运行的活动实例怎么办?
    【解决方案11】:

    我认为接受的答案是一种糟糕的处理方式。

    我不知道用例是什么,但请考虑基类中的受保护方法

    @protected
    void doSomething() {
    }
    

    并在派生类中覆盖它。

    当事件发生时,只需在基类中调用该方法即可。然后正确的“活动”类将处理它。然后类本身可以检查它是否不是Paused()

    更好的是,使用GreenRobot'sSquare's 之类的事件总线,但该总线已被弃用,建议使用RxJava

    【讨论】:

      【解决方案12】:

      你试过了吗..

          if (getActivity() instanceof NameOfYourActivity){
              //Do something
          }
      

      【讨论】:

      • 这个可以用在Fragment上,不能用在Activity中
      【解决方案13】:

      我使用了支票if (!a.isFinishing()),它似乎可以满足我的需要。 a 是活动实例。这是不正确的吗?为什么没有人尝试这个?

      【讨论】:

        【解决方案14】:

        activity.isFinishing()

        【讨论】:

        • 这不是一个好的解决方案,因为 isFinishing 指示是否有活动处于杀戮过程中。
        【解决方案15】:

        ActivityLifecycleCallbacks 是跟踪 App 中所有活动的好方法:

        public class BaseActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
        
        private ActivityState homeState, contentState;
        
        @Override
        public void onActivityCreated(Activity activity, Bundle bundle) {
            if (activity instanceof HomeActivityv2) {
                homeState = ActivityState.CREATED;
            } else if (activity instanceof ContentDisplayActivity) {
                contentState = ActivityState.CREATED;
            }
        }
        
        @Override
        public void onActivityStarted(Activity activity) {
            if (activity instanceof HomeActivityv2) {
                homeState = ActivityState.STARTED;
            } else if (activity instanceof ContentDisplayActivity) {
                contentState = ActivityState.STARTED;
            }
        }
        
        @Override
        public void onActivityResumed(Activity activity) {
            if (activity instanceof HomeActivityv2) {
                homeState = ActivityState.RESUMED;
            } else if (activity instanceof ContentDisplayActivity) {
                contentState = ActivityState.RESUMED;
            }
        }
        
        @Override
        public void onActivityPaused(Activity activity) {
            if (activity instanceof HomeActivityv2) {
                homeState = ActivityState.PAUSED;
            } else if (activity instanceof ContentDisplayActivity) {
                contentState = ActivityState.PAUSED;
            }
        }
        
        @Override
        public void onActivityStopped(Activity activity) {
            if (activity instanceof HomeActivityv2) {
                homeState = ActivityState.STOPPED;
            } else if (activity instanceof ContentDisplayActivity) {
                contentState = ActivityState.STOPPED;
            }
        }
        
        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
        }
        
        @Override
        public void onActivityDestroyed(Activity activity) {
            if (activity instanceof HomeActivityv2) {
                homeState = ActivityState.DESTROYED;
            } else if (activity instanceof ContentDisplayActivity) {
                contentState = ActivityState.DESTROYED;
            }
        }
        
        public ActivityState getHomeState() {
            return homeState;
        }
        
        public ActivityState getContentState() {
            return contentState;
        }
        }
        

        活动状态:

        public enum ActivityState {
            CREATED, STARTED, RESUMED, PAUSED, STOPPED, DESTROYED;
        }
        

        扩展 Application 类并在 Android Manifest 文件中提供其引用:

        import android.app.Application;
        
        public final class BaseApplication extends Application {
        private BaseActivityLifecycleCallbacks baseALC;
        
        @Override
        public void onCreate() {
            super.onCreate();
            baseALC = new BaseActivityLifecycleCallbacks();
            this.registerActivityLifecycleCallbacks(baseALC);
        
        }
        
        public BaseActivityLifecycleCallbacks getBaseALC() {
            return baseALC;
        }
        }
        

        从 Activity 的任何位置检查其他 Activity 的状态:

        private void checkAndLaunchHomeScreen() {
            Application application = getApplication();
            if (application instanceof BaseApplication) {
                BaseApplication baseApplication = (BaseApplication) application;
                if (baseApplication.getBaseALC().getHomeState() == null || baseApplication.getBaseALC().getHomeState() == ActivityState.DESTROYED) {
                    //Do anything you want
                }
            }
        }
        

        https://developer.android.com/reference/android/app/Application.ActivityLifecycleCallbacks.html

        【讨论】:

          【解决方案16】:

          不确定这是“做事”的“正确”方式。
          如果没有 API 方法可以解决(或一个)问题而不是您应该考虑的问题,那么您可能做错了什么并改为阅读更多文档等。
          (据我了解,静态变量在 android 中是一种常见的错误方式。它当然可以工作,但肯定会有它无法工作的情况[例如,在生产中,在百万台设备上])。
          正是在您的情况下,我建议您考虑为什么您需要知道另一个活动是否还活着?...您可以启动另一个活动以获得结果以获取其功能。或者您可以派生类以获取其功能等等。
          最好的问候。

          【讨论】:

            【解决方案17】:

            如果您对活动的特定实例的生命周期状态感兴趣,siliconeagle 的解决方案看起来是正确的,只是新的“活动”变量应该是实例变量,而不是静态变量。

            【讨论】:

              【解决方案18】:

              使用有序广播。见http://android-developers.blogspot.nl/2011/01/processing-ordered-broadcasts.html

              在您的活动中,在 onStart 中注册一个接收器,在 onStop 中取消注册。现在,例如,当一个服务需要处理一些活动可能能够做得更好的事情时,从服务发送一个有序的广播(在服务本身带有一个默认处理程序)。您现在可以在活动运行时对其进行响应。服务可以检查结果数据以查看广播是否被处理,如果没有采取适当的措施。

              【讨论】:

                【解决方案19】:

                除了the accepted answer,如果你有多个activity的实例,你可以使用一个计数器来代替处理多个实例:

                class MyActivity extends Activity {
                
                     static int activeInstances = 0;
                
                     static boolean isActive() {
                        return (activeInstances > 0);
                     }
                
                      @Override
                      public void onStart() {
                         super.onStart();
                         activeInstances++;
                      } 
                
                      @Override
                      public void onStop() {
                         super.onStop();
                         activeInstances--;
                      }
                }
                

                【讨论】:

                • 返回行中缺少“s”和“;(分号)”。
                【解决方案20】:
                public static boolean isActivityActive(Activity activity) {
                   if (null != activity)
                      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
                         return !activity.isFinishing() && !activity.isDestroyed();
                      else return !activity.isFinishing();
                   return false;
                }
                

                【讨论】:

                  【解决方案21】:

                  使用以下代码找到了一个简单的解决方法

                  @Override 
                  protected void onCreate(Bundle savedInstanceState) { 
                              super.onCreate(savedInstanceState); 
                              if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) { 
                                  // Activity is being brought to front and not being  created again, 
                                  // Thus finishing this activity will bring the last viewed activity to foreground
                                  finish(); 
                              } 
                      }
                  

                  【讨论】:

                    【解决方案22】:

                    使用 isActivity 变量检查活动是否处于活动状态。

                    private boolean activityState = true;
                    
                     @Override
                    protected void onDestroy() {
                        super.onDestroy();
                        activityState = false;
                    }
                    

                    然后检查

                    if(activityState){
                    //add your code
                    }
                    

                    【讨论】:

                      【解决方案23】:

                      如果您想检查活动是否在后台堆栈中,只需执行以下步骤即可。 1. 在你的Application类中声明一个ArrayList [Application类在你的mainfest文件中的application标签中定义]

                      private ArrayList<Class> runningActivities = new ArrayList<>();
                      
                      1. 并添加以下公共方法来访问和修改此列表。

                        public void addActivityToRunningActivityies (Class cls) {
                        if (!runningActivities.contains(cls)) runningActivities.add(cls);
                        }
                        
                        public void removeActivityFromRunningActivities (Class cls) {
                        if (runningActivities.contains(cls)) runningActivities.remove(cls);
                        }
                        
                        public boolean isActivityInBackStack (Class cls) {
                        return runningActivities.contains(cls);
                        }
                        
                      2. 在所有活动都扩展它的 BaseActivity 中,重写 onCreate 和 onDestroy 方法,以便您可以按以下方式从后台堆栈添加和删除活动。

                        @Override
                        protected void onCreate(@Nullable Bundle savedInstanceState) {
                        super.onCreate(savedInstanceState);
                        
                        ((MyApplicationClass)getApplication()).addActivityToRunningActivityies
                        (this.getClass());
                        }
                        
                        @Override
                        protected void onDestroy() {
                        super.onDestroy();
                        
                        ((MyApplicationClass)getApplication()).removeActivityFromRunningActivities
                        (this.getClass());
                        }
                        
                      3. 最后,如果要检查活动是否在后台堆栈中,只需调用此函数 isActivityInBackStack。

                      例如:我想检查 HomeActivity 是否在后栈中:

                      if (((MyApplicationClass) 
                      getApplication()).isActivityInBackStack(HomeActivity.class)) {
                             // Activity is in the back stack
                          } else {
                             // Activity is not in the back stack
                          }
                      

                      【讨论】:

                        【解决方案24】:

                        我使用了 task.topActivity 而不是 task.baseActivity,它对我来说很好。

                           protected Boolean isNotificationActivityRunning() {
                            ActivityManager activityManager = (ActivityManager) getBaseContext().getSystemService(Context.ACTIVITY_SERVICE);
                            List<ActivityManager.RunningTaskInfo> tasks = activityManager.getRunningTasks(Integer.MAX_VALUE);
                        
                            for (ActivityManager.RunningTaskInfo task : tasks) {
                                if (task.topActivity.getClassName().equals(NotificationsActivity.class.getCanonicalName()))
                                    return true;
                            }
                        
                            return false;
                        }
                        

                        【讨论】:

                          【解决方案25】:

                          我知道这个问题很老,而且有很多不同的答案,有各种优点和缺点。我的看法是,为什么不推出自己的 IPC 实施。

                          class IPC {
                          
                              companion object {
                                  private val appContext : Context by lazy { /*genericApplicationContext*/ }
                          
                                  fun initIPC(process: String){
                                      var file : File? = null
                                      file = File(appContext.cacheDir.absolutePath + "/$process")
                                      var output : OutputStream? = null
                                      try {
                                          output = FileOutputStream(file!!)
                                          output.write(0)
                                      } finally {
                                          output?.close()
                                      }
                                  }
                          
                                  fun destroyIPC(process: String){
                                      var file : File? = null
                                      file = File(appContext.cacheDir.absolutePath + "/$process")
                                      file.delete()
                                  }
                          
                                  fun checkForIPC(process: String) : Boolean {
                                      var file : File? = null
                                      file = File(appContext.cacheDir.absolutePath + "/$process")
                                      if(file.exists()) return true
                                      return false
                                  }
                              }
                          
                          }
                          

                          这允许您在启动活动之前创建文件,然后在关闭启动的活动时关闭“进程/文件”。如果您的“进程活动”在后台,这允许您检查后台线程或当前活动,以查看文件是否仍然打开,表明活动处于活动状态。在我的情况下,我连续调用一个外部 API,但需要对调用进行速率限制,因此使用它来确保一次只有一个活动在调用 API。

                          【讨论】:

                            【解决方案26】:

                            如果您在前台没有相同的活动,则此工作。 如果您从通知中打开不起作用,我会进行一些调整并附带以下内容:

                            public static boolean ativo = false;
                            public static int counter = 0;
                            
                            @Override
                            protected void onCreate(Bundle savedInstanceState) {
                                super.onCreate(savedInstanceState);
                                ...
                                counter++;
                            }
                            
                            @Override
                            protected void onStart() {
                                super.onStart();
                                ativo = true;
                            }
                            
                            @Override
                            protected void onStop() {
                                super.onStop();
                                if (counter==1) ativo = false;
                            }
                            
                            @Override
                            protected void onDestroy() {
                                counter--;
                                super.onDestroy();
                            }
                            

                            这对我来说适用于同时打开多个活动。

                            【讨论】:

                              猜你喜欢
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 2011-05-19
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 2022-12-03
                              相关资源
                              最近更新 更多