Android: como verifico se a atividade está em execução?

152

Existe alguma maneira simples de determinar se uma determinada atividade está ativa ou não? Quero fazer certas coisas, dependendo de qual atividade está ativa. por exemplo:

if(activityrunning == activity1)
//do this
else if (activityrunning == activity2)
//do something else
user560571
fonte
Para verificar se uma atividade está sendo executado ou não você pode passar por esta resposta: stackoverflow.com/a/39079627/4531507
Rahul Sharma

Respostas:

227

Você pode usar uma staticvariável dentro da atividade.

class MyActivity extends Activity {
     static boolean active = false;

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

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

O único problema é que, se você usá-lo em duas atividades que se vinculam, onStopo primeiro é chamado às vezes onStartno segundo. Então, ambos podem ser verdadeiros brevemente.

Dependendo do que você está tentando fazer (atualize a atividade atual de um serviço?). Você pode simplesmente registrar um ouvinte estático no serviço no seu onStartmétodo de atividade e , em seguida, o ouvinte correto estará disponível quando seu serviço desejar atualizar a interface do usuário.

siliconeagle
fonte
5
Alguém apontou isso para mim que ... A preferência compartilhada deve ser preferida a uma variável estática devido a problemas de vazamento de memória.
perfil completo de Ayush Goyal
13
E se houver atividades diferentes da mesma classe em execução? E se você estender MyActivitycom MyChildactivitye quiser verificar se a criança está ativa?
Mister Smith
2
Dependendo da sua definição de "execução", convém alterar o estado da variável em onResume e onPause ....
G. Blake Meike
5
Esta solução não é uma boa solução. Digamos que sua Atividade chame um Fragmento, por exemplo, o fragmento estará sobre a Atividade, mas a Atividade não chamará onPause, e se você fechar o fragmento onStop, onStart ou qualquer outro método de ciclo de vida também não será chamado. A melhor solução é verificar em sua classe Application a visibilidade conforme descrito aqui: stackoverflow.com/questions/18038399/…
portfoliobuilder
6
Se você recomendar estática, você recebe um -1 de mim
Matei Suica
52

Sei que esse problema é bastante antigo, mas acho que ainda vale a pena compartilhar minha solução, pois pode ser útil para outras pessoas.

Esta solução não estava disponível antes do lançamento do Android Architecture Components.

A atividade é pelo menos parcialmente visível

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

A atividade está em primeiro plano

getLifecycle().getCurrentState().isAtLeast(RESUMED)
malinjir
fonte
3
getLifecycle (). getCurrentState (). isAtLeast (Lifecycle.State.RESUMED)
Radhey
43

Eu acho mais claro assim:

  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;
    }
Xenione
fonte
2
Eu tento evitar criar variáveis ​​temporárias antes de um loop 'for'; para (tarefa RunningTaskInfo: ActivityManager.getRunningTasks (Integer.MAX_VALUE)) {... #
mikebabcock 31/12
Como posso chamar essa função?
Behzad
1
como sempre, é um método que você pode chamar dentro de sua classe como uma 'função'. Você precisa de um exemplo?
Xenione
10
De developer.android.com/reference/android/app/… "Isso nunca deve ser usado para a lógica principal de um aplicativo, como decidir entre comportamentos diferentes com base nas informações encontradas aqui. Esses usos não são suportados e provavelmente serão interrompidos no futuro."
joe_deniable
15
No nível 21 da API (Android 5.0 Lollipop), este método foi preterido.
AxeEffect
30

Uma opção sem usar nenhuma variável auxiliar é:

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

onde a atividade é fe: this ou getActivity ().

O valor retornado por essa expressão muda em onStart () / onStop (), que são os eventos que iniciam / param de mostrar o layout da atividade no telefone.

GaRRaPeTa
fonte
16
por que não usar apenas Activity#getWindow().getDecorView().isShown()?
Gianluca P.
24

Usei o método MyActivity.class e getCanonicalName e obtive resposta.

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;
}
mahyar
fonte
1
Como mencionado anteriormente, pode não ser uma boa ideia usá- getRunningTasks()lo, pois foi reprovado: androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/…
Vitalii Dmitriev
21

Maneira muito melhor do que usar uma variável estática e seguir o POO

Shared Preferencespode ser usado para compartilhar variáveis ​​com outros activitiese serviços de umapplication

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

    }
}

Use preferências compartilhadas. Ele possui as informações mais confiáveis ​​do estado, menos problemas de troca / destruição de aplicativos, economiza a solicitação de mais uma permissão e nos dá mais controle para decidir quando nossa atividade é realmente a mais alta. veja detalhes aqui abd aqui também

Zar E Ahmer
fonte
Obrigado. Mas o onResume também é necessário, mano?
1
Depende do que você entende por ativo. De acordo com meu código, Activity está na pilha e está ativo. E se você deseja manipular visível ou não, então você pode usar onResume
Zar E Ahmer
19
Isso quebra quando a atividade é morto sem chamaronStop()
Marcel Bro
3
O que acontece se o aplicativo falhar?
UcMedia 18/04
1
Esta é uma "solução" muito perigosa.
Firzen 4/09/19
9

Este é um código para verificar se um serviço específico está sendo executado. Tenho certeza de que ele pode funcionar para uma atividade também desde que você altere getRunningServices com getRunningAppProcesses () ou getRunningTasks (). Dê uma olhada aqui http://developer.android.com/reference/android/app/ActivityManager.html#getRunningAppProcesses ()

Altere Constants.PACKAGE e Constants.BACKGROUND_SERVICE_CLASS de acordo

    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;

}
kkudi
fonte
1
Mas lembre-se de que o link fornecido indica "este método é destinado apenas para depuração ou criação de uma interface de usuário de gerenciamento de processos voltada para o usuário".
joe_deniable
getRunningTasks agora está obsoleto.
Adi
5

Existe uma maneira muito mais fácil do que tudo acima e essa abordagem não requer o uso do android.permission.GET_TASKSmanifesto, ou tem o problema de condições de corrida ou vazamento de memória apontado na resposta aceita.

  1. Faça uma variável estática na atividade principal. Estático permite que outras atividades recebam os dados de outra atividade. onPause()definir esta variável falsa , onResumee onCreate()definir esta variável verdadeira .

    private static boolean mainActivityIsOpen;
  2. Atribua getters e setters dessa variável.

    public static boolean mainActivityIsOpen() {
        return mainActivityIsOpen;
    }
    
    public static void mainActivityIsOpen(boolean mainActivityIsOpen) {
        DayView.mainActivityIsOpen = mainActivityIsOpen;
    }
  3. E depois de outra atividade ou serviço

    if (MainActivity.mainActivityIsOpen() == false)
    {
                    //do something
    }
    else if(MainActivity.mainActivityIsOpen() == true)
    {//or just else. . . ( or else if, does't matter)
            //do something
    }
coolcool1994
fonte
3
Você está dizendo que usar métodos de acessador é melhor do que usar variáveis ​​estáticas públicas brutas?
IgorGanapolsky
1
Em Java, é melhor usar setters e getters para manter suas variáveis ​​privadas. No entanto, acredito que no Android é comum variáveis de acesso públicos diretamente ...
Stephen
11
Não faz sentido ter um levantador público, pois o estado da atividade deve ser tratado apenas pela própria atividade. Você deve seguir as convenções de nomenclatura java: isActivityOpen seria um método getter correto. Também usar se booleano == true for redundante. Além disso, delegar a gestão do estado à atividade é a melhor abordagem.
Lisandro #
8
é por isso que u deve ter assistido seus cursos com mais diligência @coolcool;)
Jerec TheSith
1
E se você tiver várias instâncias da atividade em execução?
precisa saber é o seguinte
5
if(!activity.isFinishing() && !activity.isDestroyed())

Dos documentos oficiais:

Atividade # isFinishing ()

Verifique se esta atividade está em processo de finalização, porque você chamou finish () ou se alguém solicitou a conclusão. Isso é frequentemente usado em onPause () para determinar se a atividade está simplesmente pausando ou terminando completamente.

Atividade # isDestroyed ()

Retorna true se a chamada final onDestroy () tiver sido feita na Activity, portanto, esta instância está morta.

Codelicious
fonte
4

obrigado kkudi! Consegui adaptar sua resposta para trabalhar em uma atividade ... eis o que funcionou no meu aplicativo ..

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

este exemplo fornecerá um valor verdadeiro ou falso se topActivity corresponder ao que o usuário está fazendo. Portanto, se a atividade que você está verificando não está sendo exibida (ou seja, está na Pausa), você não terá uma correspondência. Além disso, para fazer isso, você precisa adicionar a permissão ao seu manifesto.

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

Eu espero que isso tenha sido útil!

alyon2002
fonte
1
Esta permissão de uso foi preterida no nível 21. da API. Developer.android.com/reference/android/…
Guy West
2
A votação anterior foi reduzida para acessar as atividades principais (serviços [i] .topActivity) e reduzimos o nível Q da API. Abaixo, isso não funcionará.
Debasish Ghosh 28/01
4

Eu acho que a resposta aceita é uma maneira terrível de lidar com isso.

Não sei qual é o caso de uso, mas considere um método protegido na classe base

@protected
void doSomething() {
}

e substitua-o na classe derivada.

Quando o evento ocorrer, basta chamar esse método na classe base. A classe 'ativa' correta irá lidar com isso então. A própria classe pode então verificar se não está Paused().

Melhor ainda, use um barramento de eventos como o GreenRobot , o Square , mas esse está obsoleto e sugere o uso do RxJava

Garoto
fonte
2

Eu usei um cheque if (!a.isFinishing())e parece fazer o que eu preciso. aé a instância da atividade. Isso está incorreto? Por que ninguém tentou isso?

lxknvlk
fonte
2

A respeito activity.isFinishing()

Ambareesh B
fonte
Não é uma boa solução, pois é possível concluir se há alguma atividade em um processo de matança.
VelocityPulse
2

ActivityLifecycleCallbacks é uma ótima maneira de acompanhar todas as atividades no 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;
}
}

ActivityState:

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

Estenda a classe Application e forneça sua referência no arquivo 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;
}
}

Verifique em qualquer lugar da Atividade o status de outra atividade:

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

Suyash Gupta
fonte
1

Não tenho certeza se é uma maneira "adequada" de "fazer as coisas".
Se não há nenhuma maneira API para resolver o (ou a) pergunta que você deve pensar um pouco, talvez você está fazendo algo errado e leia mais docs vez etc.
(Como eu entendi variáveis estáticas é uma forma comumente errado no android. De causa poderia funcionar, mas definitivamente haverá casos em que não funcionará [por exemplo, na produção, em milhões de dispositivos]).
Exatamente no seu caso, sugiro pensar por que você precisa saber se outra atividade está viva? ... você pode iniciar outra atividade para obter a funcionalidade. Ou você pode derivar a classe para obter sua funcionalidade e assim por diante.
Cumprimentos.

user2399321
fonte
1

Se você estiver interessado no estado do ciclo de vida da instância específica da atividade, a solução siliconeagle parece correta, exceto que a nova variável "ativa" deve ser uma variável de instância, e não estática.

Jonathan Taylor
fonte
1

Use uma transmissão ordenada. Consulte http://android-developers.blogspot.nl/2011/01/processing-ordered-broadcasts.html

Em sua atividade, registre um receptor no onStart, cancele o registro no onStop. Agora, quando, por exemplo, um serviço precisar lidar com algo que a atividade possa executar melhor, envie uma transmissão ordenada a partir do serviço (com um manipulador padrão no próprio serviço). Agora você pode responder na atividade quando ela estiver em execução. O serviço pode verificar os dados do resultado para ver se a transmissão foi manipulada e se não tomar as medidas apropriadas.

nickmartens1980
fonte
1

Além da resposta aceita , se você tiver várias instâncias da atividade, poderá usar um contador:

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--;
      }
}
james_alvarez
fonte
faltando "s" e "; (ponto e vírgula)" na linha de retorno.
Ali_dev
1

Você tentou..

    if (getActivity() instanceof NameOfYourActivity){
        //Do something
    }
E.Mathew
fonte
0

Foi encontrada uma solução fácil com o seguinte código

@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(); 
            } 
    }
Varun Bhatia
fonte
0

Use a variável isActivity para verificar se a atividade está ativa ou não.

private boolean activityState = true;

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

Então verifique

if(activityState){
//add your code
}
Faran Tariq
fonte
0

Se você quiser verificar se a atividade está na pilha de trás, siga as próximas etapas. 1. Declarou um ArrayList na sua classe Application [A classe Application é definida no seu arquivo principal na tag do aplicativo]

private ArrayList<Class> runningActivities = new ArrayList<>();
  1. E adicione os seguintes métodos públicos para acessar e modificar esta lista.

    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. Na BaseActivity, onde todas as atividades a estendem, substitua os métodos onCreate e onDestroy para que você possa adicionar e remover atividades da pilha traseira como a seguir.

    @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. Por fim, se você deseja verificar se a atividade está na pilha de trás ou não, basta chamar esta função comoActivityInBackStack.

Ex: desejo verificar se o HomeActivity está na pilha de trás ou não:

if (((MyApplicationClass) 
getApplication()).isActivityInBackStack(HomeActivity.class)) {
       // Activity is in the back stack
    } else {
       // Activity is not in the back stack
    }
Hagar Magdy
fonte
0
public static boolean isActivityActive(Activity activity) {
    return !activity.isFinishing() &&
            (SDK_INT < JELLY_BEAN_MR1 || !activity.isDestroyed());
}
Ahamadullah Saikat
fonte
-1

Este trabalho se você não tiver a mesma atividade em primeiro plano. Se você abrir a partir da notificação, não funcione, fiz alguns ajustes e viemos com isso:

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

Isso funciona para mim com várias atividades abertas ao mesmo tempo.

Simão Coutinho
fonte