Android:如何检查活动是否正在运行?

时间:2011-03-27 01:21:17

标签: android android-activity

是否有任何简单的方法来确定某项活动是否有效? 我想根据哪些活动是活跃的来做某些事情。 例如:

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

26 个答案:

答案 0 :(得分:209)

您可以在活动中使用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时,正确的侦听器将可用。

答案 1 :(得分:39)

我认为更清楚:

  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;
    }

答案 2 :(得分:23)

比使用静态变量并遵循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 here abd here also

答案 3 :(得分:20)

我使用了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;
}

答案 4 :(得分:20)

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

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

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

此表达式返回的值在onStart()/ onStop()中更改,这些事件是启动/停止显示手机上活动布局的事件。

答案 5 :(得分:9)

这是用于检查特定服务是否正在运行的代码。只要您使用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;

}

答案 6 :(得分:6)

谢谢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"/>

我希望这有用!

答案 7 :(得分:4)

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

此解决方案在发布Android体系结构组件之前不可用。

活动至少部分可见

getLifecycle().getCurrentState().isAtLeast(STARTED)

活动处于前台

getLifecycle().getCurrentState().isAtLeast(RESUMED)

答案 8 :(得分:4)

我认为接受的答案是处理这个问题的可怕方法。

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

@protected
void doSomething() {
}

并在派生类中覆盖它。

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

更好的是,使用GreenRobot'sSquare's等事件总线,但不推荐使用该事件总线并建议使用RxJava

答案 9 :(得分:3)

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

  1. 在主Activity中创建一个STATIC变量。 Static允许其他活动从另一个活动接收数据。 onPause()设置此变量 false onResumeonCreate()设置此变量 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
    }
    

答案 10 :(得分:2)

if(!activity.isFinishing() && !activity.isDestroyed())

答案 11 :(得分:2)

activity.isFinishing()

怎么样?

答案 12 :(得分:2)

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

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

ActivityState:

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;
}
}

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

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
        }
    }
}

从活动中的任何地方Ckeck获取其他活动的状态:

parent.children.where('id > ?', start_row)

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

答案 13 :(得分:1)

如果要检查活动是否在后排堆栈中,请遵循以下步骤。 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
    }

答案 14 :(得分:1)

您尝试过吗。

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

答案 15 :(得分:1)

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

答案 16 :(得分:1)

除了the accepted answer之外,如果您有多个活动实例,则可以使用计数器:

class MyActivity extends Activity {

     static int activeInstances = 0;

     static boolean isActive() {
        return (activeInstance > 0)
     }

      @Override
      public void onStart() {
         super.onStart();
         activeInstances++;
      } 

      @Override
      public void onStop() {
         super.onStop();
         activeInstances--;
      }
}

答案 17 :(得分:1)

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

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

答案 18 :(得分:1)

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

答案 19 :(得分:1)

不确定这是“做事”的“正确”方式 如果没有API方法来解决(或)问题而不是你应该想一点,也许你做错了什么并阅读更多文档等等。
(据我所知,静态变量在android中是一种常见的错误方式。因为它可以起作用,但肯定会出现无法工作的情况[例如,在生产中,在百万台设备上]。) 在你的情况下,我建议认为为什么你需要知道另一个活动是否还活着吗?你可以为结果启动另一个活动来获得它的功能。或者你可以派出类来获得它的功能等等 最诚挚的问候。

答案 20 :(得分:0)

我使用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;
}

答案 21 :(得分:0)

public static boolean isActivityActive(Activity activity) {
    return !activity.isFinishing() &&
            (SDK_INT < JELLY_BEAN_MR1 || !activity.isDestroyed());
}

答案 22 :(得分:0)

我知道这个问题很老,答案很多,带有各种优点和缺点。我对此的看法是,为什么不推出自己的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。

答案 23 :(得分:0)

使用isActivity变量检查活动是否有效。

private boolean activityState = true;

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

然后检查

if(activityState){
//add your code
}

答案 24 :(得分:0)

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

@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(); 
            } 
    }

答案 25 :(得分:-1)

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

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();
}

这对我来说很有效,同时可以进行多个活动。