Android: Wie überprüfe ich, ob Aktivität ausgeführt wird?


152

Gibt es eine einfache Möglichkeit festzustellen, ob eine bestimmte Aktivität aktiv ist oder nicht? Ich möchte bestimmte Dinge tun, je nachdem welche Aktivität aktiv ist. z.B:

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

Um zu überprüfen, ob eine Aktivität ausgeführt wird oder nicht, können Sie diese Antwort durchgehen
Rahul Sharma

Antworten:


226

Sie können eine staticVariable innerhalb der Aktivität verwenden.

class MyActivity extends Activity {
     static boolean active = false;

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

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

Das einzige Problem ist, dass, wenn Sie es in zwei Aktivitäten verwenden, die miteinander verknüpft sind, onStopdie erste manchmal onStartin der zweiten aufgerufen wird . Beides könnte also kurz zutreffen.

Je nachdem, was Sie versuchen (aktuelle Aktivität von einem Dienst aktualisieren?). Sie können einfach einen statischen Listener im Dienst in Ihrer Aktivitätsmethode registrieren. onStartDann ist der richtige Listener verfügbar, wenn Ihr Dienst die Benutzeroberfläche aktualisieren möchte.


5
Jemand hat mich darauf hingewiesen, dass ... aufgrund von Speicherverlustproblemen eine gemeinsame Präferenz einer statischen Variablen vorgezogen werden sollte.
Ayush Goyal

13
Was ist, wenn verschiedene Aktivitäten derselben Klasse ausgeführt werden? Was passiert , wenn Sie erweitern MyActivitymit MyChildactivityund überprüfen möchten , ob das Kind aktiv ist?
Mister Smith

2
Abhängig von Ihrer Definition von "Ausführen" möchten Sie möglicherweise den Status der Variablen in onResume und onPause ändern ....
G. Blake Meike

5
Diese Lösung ist überhaupt keine gute Lösung. Nehmen wir an, Ihre Aktivität ruft ein Fragment auf. Das Fragment befindet sich beispielsweise über der Aktivität, die Aktivität ruft jedoch nicht onPause auf, und wenn Sie das Fragment onStop, onStart oder andere Lebenszyklusmethoden schließen, wird dies auch nicht aufgerufen. Die beste Lösung besteht darin, in Ihrer Anwendungsklasse die Sichtbarkeit wie hier beschrieben zu überprüfen: stackoverflow.com/questions/18038399/…
portfoliobuilder

6
Wenn Sie Statik empfehlen, erhalten Sie eine -1 von mir
Matei Suica

49

Mir ist klar, dass dieses Problem ziemlich alt ist, aber ich denke, es lohnt sich immer noch, meine Lösung zu teilen, da sie für andere nützlich sein könnte.

Diese Lösung war vor der Veröffentlichung von Android Architecture Components nicht verfügbar.

Aktivität ist zumindest teilweise sichtbar

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

Aktivität steht im Vordergrund

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

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

42

Ich denke so klarer:

  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
Ich versuche zu vermeiden, temporäre Variablen vor einer 'for'-Schleife zu erstellen. für (RunningTaskInfo Aufgabe: ActivityManager.getRunningTasks (Integer.MAX_VALUE)) {...
mikebabcock

Wie kann ich diese Funktion aufrufen?
Behzad

1
Benötigen Sie wie üblich eine Methode, die Sie in Ihrer Klasse als 'Funktion' aufrufen können? Benötigen Sie ein Beispiel?
Xenione

10
Von developer.android.com/reference/android/app/… "Dies sollte niemals für die Kernlogik in einer Anwendung verwendet werden, z. B. die Entscheidung zwischen verschiedenen Verhaltensweisen basierend auf den hier gefundenen Informationen. Solche Verwendungen werden nicht unterstützt und werden wahrscheinlich nicht funktionieren in der Zukunft."
Joe_deniable

15
Ab API-Level 21 (Android 5.0 Lollipop) ist diese Methode veraltet.
AxeEffect

29

Eine Option ohne Verwendung einer Hilfsvariablen ist:

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

wo Aktivität ist zB: this oder getActivity ().

Der von diesem Ausdruck zurückgegebene Wert ändert sich in onStart () / onStop (). Hierbei handelt es sich um Ereignisse, bei denen das Layout der Aktivität auf dem Telefon gestartet / gestoppt wird.


16
warum nicht jsut verwenden Activity#getWindow().getDecorView().isShown()?
Gianluca P.

24

Ich habe die Methoden MyActivity.class und getCanonicalName verwendet und eine Antwort erhalten.

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

1
Wie bereits erwähnt, ist es möglicherweise keine gute Idee, es zu verwenden, getRunningTasks()da es veraltet ist: androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/…
Vitalii Dmitriev

21

Weitaus besser als eine statische Variable zu verwenden und OOP zu folgen

Shared Preferenceskann verwendet werden, um Variablen mit anderen activitiesund Diensten von einem zu teilenapplication

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

    }
}

Verwenden Sie gemeinsame Einstellungen. Es verfügt über die zuverlässigsten Statusinformationen, weniger Probleme beim Wechseln / Zerstören von Anwendungen, erspart uns die Anforderung einer weiteren Erlaubnis und gibt uns mehr Kontrolle darüber, wann unsere Aktivität tatsächlich die oberste ist. siehe Details bitte hier abd hier auch


Vielen Dank. Aber braucht onResume auch Bruder?

1
Es hängt davon ab, was Sie unter aktiv verstehen. Gemäß meinem Code befindet sich die Aktivität im Stapel und ist dann aktiv. Und wenn Sie sichtbar behandeln wollen oder nicht, dann können Sie onResume
Zar E Ahmer

19
Dies bricht ab, wenn die Aktivität ohne Anruf beendet wirdonStop()
Marcel Bro

3
Was passiert, wenn die App abstürzt?
ucMedia

1
Dies ist eine sehr gefährliche "Lösung".
Firzen

9

Dies ist ein Code zum Überprüfen, ob ein bestimmter Dienst ausgeführt wird. Ich bin mir ziemlich sicher, dass es auch für eine Aktivität funktionieren kann, solange Sie getRunningServices mit getRunningAppProcesses () oder getRunningTasks () ändern. Schauen Sie hier http://developer.android.com/reference/android/app/ActivityManager.html#getRunningAppProcesses ()

Ändern Sie Constants.PACKAGE und Constants.BACKGROUND_SERVICE_CLASS entsprechend

    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;

}

1
Beachten Sie jedoch, dass der von Ihnen bereitgestellte Link besagt, dass "diese Methode nur zum Debuggen oder Erstellen einer benutzerbezogenen Prozessverwaltungs-Benutzeroberfläche vorgesehen ist".
Joe_deniable

getRunningTasks ist jetzt veraltet.
Adi

5

Es gibt einen viel einfacheren Weg als alles oben Genannte, und dieser Ansatz erfordert nicht die Verwendung android.permission.GET_TASKSim Manifest oder das Problem der Rennbedingungen oder Speicherlecks, auf das in der akzeptierten Antwort hingewiesen wird.

  1. Erstellen Sie in der Hauptaktivität eine STATIC-Variable. Mit Static können andere Aktivitäten die Daten einer anderen Aktivität empfangen. onPause()setzen Sie diese Variable falsch , onResumeund onCreate()setzen Sie diese Variable wahr .

    private static boolean mainActivityIsOpen;
  2. Weisen Sie Getter und Setter dieser Variablen zu.

    public static boolean mainActivityIsOpen() {
        return mainActivityIsOpen;
    }
    
    public static void mainActivityIsOpen(boolean mainActivityIsOpen) {
        DayView.mainActivityIsOpen = mainActivityIsOpen;
    }
  3. Und dann von einer anderen Aktivität oder einem anderen Dienst

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

3
Wollen Sie damit sagen, dass die Verwendung von Accessor-Methoden besser ist als die Verwendung von statischen Rohvariablen?
IgorGanapolsky

1
In Java ist es besser, Setter und Getter zu verwenden, um Ihre Variablen privat zu halten. Ich glaube jedoch, dass es in Android üblich ist, direkt auf öffentliche Variablen zuzugreifen ...
Stephen

11
Es macht keinen Sinn, einen öffentlichen Setter zu haben, da der Aktivitätsstatus nur von der Aktivität selbst behandelt werden sollte. Sie sollten sich an die Java-Namenskonventionen halten: isActivityOpen wäre eine korrekte Getter-Methode. Auch die Verwendung von if boolean == true ist redundant. Außerdem ist die Delegation der staatlichen Verwaltung an die Aktivität der beste Ansatz.
Lisandro

8
Aus diesem Grund hättest du deine Kurse sorgfältiger besuchen sollen @coolcool;)
Jerec TheSith

1
Und was ist, wenn mehrere Instanzen der Aktivität ausgeführt werden?
Nickmartens1980

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

Aus den offiziellen Dokumenten:

Aktivität # isFinishing ()

Überprüfen Sie, ob diese Aktivität gerade beendet wird, entweder weil Sie finish () aufgerufen haben oder weil jemand anderes die Beendigung angefordert hat. Dies wird häufig in onPause () verwendet, um festzustellen, ob die Aktivität einfach angehalten oder vollständig beendet wird.

Aktivität # isDestroyed ()

Gibt true zurück, wenn der letzte Aufruf von onDestroy () für die Aktivität erfolgt ist, sodass diese Instanz jetzt tot ist.


4

danke kkudi! Ich konnte Ihre Antwort an die Arbeit für eine Aktivität anpassen. Hier ist, was in meiner App funktioniert hat.

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

In diesem Beispiel erhalten Sie ein Richtig oder Falsch, wenn die topActivity mit dem übereinstimmt, was der Benutzer tut. Wenn also die Aktivität, nach der Sie suchen, nicht angezeigt wird (dh onPause ist), erhalten Sie keine Übereinstimmung. Dazu müssen Sie Ihrem Manifest die Berechtigung hinzufügen.

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

Ich hoffe das war hilfreich!


1
Diese Verwendungsberechtigung wurde in API Level 21 veraltet. Developer.android.com/reference/android/…
Guy West

2
Stimmen Sie die Antwort ab, da Sie auf die Hauptaktivität (services [i] .topActivity) zugreifen möchten. Wir min API-Ebene Q. Unten, die nicht funktioniert.
Debasish Ghosh

4

Ich denke, die akzeptierte Antwort ist eine schreckliche Art, damit umzugehen.

Ich weiß nicht, was der Anwendungsfall ist, aber bitte ziehen Sie eine geschützte Methode in der Basisklasse in Betracht

@protected
void doSomething() {
}

und überschreiben Sie es in der abgeleiteten Klasse.

Wenn das Ereignis eintritt, rufen Sie diese Methode einfach in der Basisklasse auf. Die richtige 'aktive' Klasse wird dann damit umgehen. Die Klasse selbst kann dann prüfen, ob dies nicht der Fall ist Paused().

Besser noch, verwenden Sie einen Eventbus wie den von GreenRobot , Square , aber dieser ist veraltet und schlägt die Verwendung von RxJava vor


2

Ich habe einen Scheck benutzt if (!a.isFinishing())und er scheint zu tun, was ich brauche. aist die Aktivitätsinstanz. Ist das falsch Warum hat das niemand versucht?


2

wie wäre es mit activity.isFinishing()


Es ist keine gute Lösung, da isFinishing anzeigt, ob sich die Aktivität in einem Prozess des Tötens befindet.
VelocityPulse

2

ActivityLifecycleCallbacks ist eine großartige Möglichkeit, alle Aktivitäten in App zu verfolgen:

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

Erweitern Sie die Anwendungsklasse und geben Sie ihre Referenz in der Android Manifest-Datei an:

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

Überprüfen Sie irgendwo von Aktivität den Status einer anderen Aktivität:

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


1

Ich bin mir nicht sicher, ob es ein "richtiger" Weg ist, "Dinge zu tun".
Wenn es keinen API-Weg gibt, um die (oder eine) Frage zu lösen, als Sie sich ein wenig überlegen sollten, machen Sie vielleicht etwas falsch und lesen stattdessen mehr Dokumente usw.
(Wie ich verstanden habe, sind statische Variablen in Android ein häufig falscher Weg. Natürlich es könnte funktionieren, aber es wird definitiv Fälle geben, in denen es nicht funktioniert (zum Beispiel in der Produktion auf Millionen Geräten).
Genau in Ihrem Fall schlage ich vor zu überlegen, warum Sie wissen müssen, ob eine andere Aktivität aktiv ist. Sie können eine andere Aktivität starten, damit das Ergebnis ihre Funktionalität erhält. Oder Sie können die Klasse ableiten, um ihre Funktionalität zu erhalten, und so weiter.
Freundliche Grüße.


1

Wenn Sie am Lebenszyklusstatus der spezifischen Instanz der Aktivität interessiert sind, sieht die Lösung von siliconeagle korrekt aus, außer dass die neue "aktive" Variable eine Instanzvariable und keine statische sein sollte.


1

Verwenden Sie eine bestellte Sendung. Siehe http://android-developers.blogspot.nl/2011/01/processing-ordered-broadcasts.html

Registrieren Sie in Ihrer Aktivität einen Empfänger in onStart und heben Sie die Registrierung in onStop auf. Wenn ein Dienst beispielsweise etwas verarbeiten muss, das die Aktivität möglicherweise besser ausführen kann, senden Sie eine bestellte Sendung vom Dienst (mit einem Standardhandler im Dienst selbst). Sie können jetzt in der Aktivität antworten, wenn sie ausgeführt wird. Der Dienst kann die Ergebnisdaten überprüfen, um festzustellen, ob die Übertragung verarbeitet wurde, und gegebenenfalls geeignete Maßnahmen ergreifen.


1

Wenn Sie mehrere Instanzen der Aktivität haben, können Sie zusätzlich zur akzeptierten Antwort stattdessen einen Zähler verwenden:

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

fehlende "s" und "; (Semikolon)" in der Rückleitung.
Ali_dev

1

Hast du es versucht..

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

0

Mit dem folgenden Code wurde eine einfache Problemumgehung gefunden

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

0

Verwenden Sie die Variable isActivity, um zu überprüfen, ob die Aktivität aktiv ist oder nicht.

private boolean activityState = true;

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

Dann überprüfe

if(activityState){
//add your code
}

0

Wenn Sie überprüfen möchten, ob sich die Aktivität im Backstack befindet, führen Sie einfach die nächsten Schritte aus. 1. Deklarierte eine ArrayList in Ihrer Anwendungsklasse [Die Anwendungsklasse ist in Ihrer Hauptfestdatei im Anwendungs-Tag definiert]

private ArrayList<Class> runningActivities = new ArrayList<>();
  1. Fügen Sie die folgenden öffentlichen Methoden hinzu, um auf diese Liste zuzugreifen und sie zu ändern.

    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. Überschreiben Sie in Ihrer BaseActivity, in der alle Aktivitäten sie erweitern, die Methoden onCreate und onDestroy, damit Sie Aktivitäten wie folgt zum Backstack hinzufügen und daraus entfernen können.

    @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. Wenn Sie abschließend überprüfen möchten, ob sich die Aktivität im Backstack befindet oder nicht, rufen Sie einfach diese Funktion isActivityInBackStack auf.

Beispiel: Ich möchte überprüfen, ob sich die HomeActivity im Backstack befindet oder nicht:

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

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

-1

Dies funktioniert, wenn Sie nicht die gleiche Aktivität im Vordergrund haben. Wenn Sie von der Benachrichtigung öffnen, funktioniert nicht, habe ich einige Anpassungen vorgenommen und kam mit diesem:

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

Das funktioniert bei mir, wenn mehrere Aktivitäten gleichzeitig geöffnet sind.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.