Wie kann ich feststellen, ob die Android-App im Vordergrund ausgeführt wird?

83

Ich mache eine Statusleisten-Benachrichtigung in meiner Android-App, die von c2dm ausgelöst wird. Ich möchte die Benachrichtigung nicht anzeigen, wenn die App ausgeführt wird. Wie stellen Sie fest, ob die App ausgeführt wird und im Vordergrund steht?

Andrew Thomas
quelle
Es ist eine ähnliche Frage ... obwohl ich bei onStart / onStop ein Flag ausprobiert hatte und es nicht funktionierte. Ich verstehe immer noch nicht den Unterschied zwischen Stopp / Start und Pause / Wiederaufnahme.
Andrew Thomas
1
Sie sollten diese Lösung verwenden: stackoverflow.com/questions/3667022/…
Informatic0re
Seit API 16 gibt es einen einfacheren Weg mit ActivityManager.getMyMemoryState
Juozas Kontvainis
Seit der Support Library Version 26 müssen Sie ProcessLifecycleOwner nur noch abfragen, wann immer Sie möchten. Überprüfen Sie stackoverflow.com/a/52678290/6600000
Keivan Esbati

Antworten:

54

Machen Sie eine globale Variable wie private boolean mIsInForegroundMode;und weisen Sie einen falseWert in onPause()und einen trueWert in zu onResume().

Beispielcode:

private boolean mIsInForegroundMode;

@Override
protected void onPause() {
    super.onPause();
    mIsInForegroundMode = false;
}

@Override
protected void onResume() {
    super.onResume();
    mIsInForegroundMode = true;
}

// Some function.
public boolean isInForeground() {
    return mIsInForegroundMode;
}
Wroclai
quelle
2
@ MurVotema: Ja, das ist es. Es steht uns jedoch frei, diese Variable weiterzugeben, z. B. an Einstellungen oder eine Datenbank, wenn eine Änderung stattfindet.
Wroclai
19
@Shelly Aber Ihre Variable würde viel Wahr / Falsch / Wahr werden, während Sie durch Aktivitäten innerhalb derselben App wechseln. Dies bedeutet, dass Sie eine Hysterese haben müssen, um wirklich zu erkennen, wenn Ihre App den Vordergrund verliert.
Radu
10
Dies ist nicht die beste Lösung. Überprüfen Sie die @ Gadenkan-Lösung unten.
Felipe Lima
Es funktioniert für einfache Szenarien, aber wenn Sie ein onActivityResult () für Ihre Aktivität haben, werden die Dinge kompliziert. Ich möchte einen Hintergrunddienst nur dann ausführen, wenn alle Aktivitäten meiner App im Hintergrund sind und diese Lösung oben nicht ausreichend ist.
Josh
1
@Tima Wenn Sie es für alle Aktivitäten verfügbar machen möchten, können Sie eine neue MyOwnActivity-AppCompatActivity erstellen. Überschreiben Sie dann in MyOwnActivity sowohl onResume () als auch onPause (), und erweitern Sie zuletzt alle Ihre App-Aktivitäten von MyOwnActivity aus AppCompatActivity. Problem gelöst. ;; )
Elliotching
112

Alternativ können Sie anhand der Methode überprüfen, ActivityManagerwelche Aufgaben ausgeführt werden getRunningTasks. Überprüfen Sie dann mit der ersten Aufgabe (Aufgabe im Vordergrund) in der zurückgegebenen Liste der Aufgaben, ob es sich um Ihre Aufgabe handelt.
Hier ist das Codebeispiel:

public Notification buildNotification(String arg0, Map<String, String> arg1) {

    ActivityManager activityManager = (ActivityManager) appContext.getSystemService(Context.ACTIVITY_SERVICE);
    List<RunningTaskInfo> services = activityManager
            .getRunningTasks(Integer.MAX_VALUE);
    boolean isActivityFound = false;

    if (services.get(0).topActivity.getPackageName().toString()
            .equalsIgnoreCase(appContext.getPackageName().toString())) {
        isActivityFound = true;
    }

    if (isActivityFound) {
        return null;
    } else {
        // write your code to build a notification.
        // return the notification you built here
    }

}

Vergessen Sie nicht, die GET_TASKSBerechtigung in die Datei manifest.xml einzufügen, um die getRunningTasks()Methode im obigen Code ausführen zu können:

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

p / s: Wenn Sie auf diese Weise zustimmen, beachten Sie bitte, dass diese Erlaubnis jetzt veraltet ist.

Gadenkan
quelle
24
Wenn Sie diesen Code verwenden möchten, vergessen Sie nicht, <used-allow android: name = "android.permission.GET_TASKS" /> hinzuzufügen
Lakshmanan
13
Nitpicks: Das Aufrufen toString()eines von zurückgegebenen Strings getPackageName()ist redundant. Da wir nur an der ersten Aufgabe interessiert sind, die von zurückgegeben wird getRunningTasks(), können wir 1stattdessen bestehen Integer.MAX_VALUE.
Jonik
14
Hinweis: Diese Methode ist nur zum Debuggen und Präsentieren von Benutzeroberflächen für die Aufgabenverwaltung vorgesehen. Dies sollte niemals für die Kernlogik in einer Anwendung verwendet werden, z. B. für die Entscheidung zwischen verschiedenen Verhaltensweisen basierend auf den hier enthaltenen Informationen. Solche Verwendungen werden nicht unterstützt und werden wahrscheinlich in Zukunft nicht mehr verwendet. Wenn beispielsweise mehrere Anwendungen gleichzeitig aktiv ausgeführt werden können, sind Annahmen über die Bedeutung der Daten hier für Zwecke des Kontrollflusses falsch.
Informatic0re
5
Leider ist getRunningTasks () seit Android L (API 20) veraltet. Ab L steht diese Methode nicht mehr für Anwendungen von Drittanbietern zur Verfügung: Durch die Einführung dokumentenzentrierter Neuerungen können Personeninformationen an den Anrufer weitergegeben werden. Aus Gründen der Abwärtskompatibilität wird immer noch eine kleine Teilmenge seiner Daten zurückgegeben: zumindest die eigenen Aufgaben des Anrufers und möglicherweise einige andere Aufgaben wie "Home", von denen bekannt ist, dass sie nicht vertraulich sind.
Sam Lu
2
Vermutlich, wenn nur die Aufgaben des Anrufers angezeigt werden, liegt die erste Aufgabe und Hauptaktivität immer bei Ihnen, was bedeutet, dass dies immer einen echten Post-Lollipop zurückgibt.
Mike Holler
46

Dies ist ein ziemlich alter Beitrag, aber immer noch ziemlich relevant. Die oben akzeptierte Lösung funktioniert möglicherweise, ist aber falsch. Wie Dianne Hackborn schrieb:

Diese APIs sind nicht für Anwendungen gedacht, auf denen der UI-Fluss basiert, sondern um dem Benutzer beispielsweise die ausgeführten Apps oder einen Task-Manager oder dergleichen anzuzeigen.

Ja, für diese Dinge wird eine Liste gespeichert. Es ist jedoch in einem anderen Prozess deaktiviert, der von Threads verwaltet wird, die getrennt von Ihren ausgeführt werden, und nicht etwas, auf das Sie zählen können, wenn Sie (a) rechtzeitig die richtige Entscheidung treffen oder (b) bei Ihrer Rückkehr ein konsistentes Bild haben. Außerdem wird die Entscheidung darüber, zu welcher "nächsten" Aktivität Sie gehen möchten, immer an dem Punkt getroffen, an dem der Wechsel stattfinden soll, und erst an genau diesem Punkt (an dem der Aktivitätsstatus kurz gesperrt wird, um den Wechsel durchzuführen) treffen wir weiß eigentlich dafür was das nächste sein wird.

Und die Implementierung und das globale Verhalten hier können in Zukunft nicht garantiert gleich bleiben.

Die richtige Lösung besteht darin, Folgendes zu implementieren: ActivityLifeCycleCallbacks .

Dies erfordert grundsätzlich eine Anwendungsklasse, und der Handler kann dort eingerichtet werden, um den Status Ihrer Aktivitäten in der App zu ermitteln.

Vinay
quelle
7
Hier ist ein Beispiel, wie man es benutzt baroqueworksdev.blogspot.com/2012/12/…
JK
2
Ich denke, dies ist die beste Lösung und wird wahrscheinlich in Zukunft nicht brechen. Ich frage mich, warum es nicht genug Stimmen bekommen hat.
Rohan Kandwal
2
Wenn Sie einen Beispielcode schreiben, erhalten Sie mehr Stimmen, da einige Leute die Antworten ohne Beispiel überspringen ... aber es ist die beste Lösung ...
Saman Salehi
Wie unterscheidet sich dies von der in der akzeptierten Antwort verwendeten Überschreibung onPauseund onResumeMethode?
Saitama
24

Wie Vinay sagt, ist die wahrscheinlich beste Lösung (um neuere Android-Versionen ab 14 zu unterstützen) die Verwendung ActivityLifecycleCallbacksin der ApplicationKlassenimplementierung.

package com.telcel.contenedor.appdelegate;

import android.app.Activity;
import android.app.Application.ActivityLifecycleCallbacks;
import android.os.Bundle;

/** Determines global app lifecycle states. 
 * 
 * The following is the reference of activities states:
 * 
 * The <b>visible</b> lifetime of an activity happens between a call to onStart()
 * until a corresponding call to onStop(). During this time the user can see the
 * activity on-screen, though it may not be in the foreground and interacting with 
 * the user. The onStart() and onStop() methods can be called multiple times, as 
 * the activity becomes visible and hidden to the user.
 * 
 * The <b>foreground</b> lifetime of an activity happens between a call to onResume()
 * until a corresponding call to onPause(). During this time the activity is in front
 * of all other activities and interacting with the user. An activity can frequently
 * go between the resumed and paused states -- for example when the device goes to
 * sleep, when an activity result is delivered, when a new intent is delivered -- 
 * so the code in these methods should be fairly lightweight. 
 * 
 * */
public class ApplicationLifecycleManager implements ActivityLifecycleCallbacks {

    /** Manages the state of opened vs closed activities, should be 0 or 1. 
     * It will be 2 if this value is checked between activity B onStart() and
     * activity A onStop().
     * It could be greater if the top activities are not fullscreen or have
     * transparent backgrounds.
     */
    private static int visibleActivityCount = 0;

    /** Manages the state of opened vs closed activities, should be 0 or 1
     * because only one can be in foreground at a time. It will be 2 if this 
     * value is checked between activity B onResume() and activity A onPause().
     */
    private static int foregroundActivityCount = 0;

    /** Returns true if app has foreground */
    public static boolean isAppInForeground(){
        return foregroundActivityCount > 0;
    }

    /** Returns true if any activity of app is visible (or device is sleep when
     * an activity was visible) */
    public static boolean isAppVisible(){
        return visibleActivityCount > 0;
    }

    public void onActivityCreated(Activity activity, Bundle bundle) {
    }

    public void onActivityDestroyed(Activity activity) {
    }

    public void onActivityResumed(Activity activity) {
        foregroundActivityCount ++;
    }

    public void onActivityPaused(Activity activity) {
        foregroundActivityCount --;
    }


    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
    }

    public void onActivityStarted(Activity activity) {
        visibleActivityCount ++;
    }

    public void onActivityStopped(Activity activity) {
        visibleActivityCount --;
    }
}

Und in der Anwendungsmethode onCreate():

registerActivityLifecycleCallbacks(new ApplicationLifecycleManager());

Dann ApplicationLifecycleManager.isAppVisible()oder ApplicationLifecycleManager.isAppInForeground()würde verwendet, um den gewünschten Zustand zu kennen.

htafoya
quelle
Es funktioniert nur mit isAppVisible (). Wenn Sie die App schließen, senden Sie sie in den Vordergrund, sie hat keine Auswirkung
AlwaysConfused
19

Seit API 16 können Sie dies folgendermaßen tun:

static boolean shouldShowNotification(Context context) {
    RunningAppProcessInfo myProcess = new RunningAppProcessInfo();
    ActivityManager.getMyMemoryState(myProcess);
    if (myProcess.importance != RunningAppProcessInfo.IMPORTANCE_FOREGROUND)
        return true;

    KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
    // app is in foreground, but if screen is locked show notification anyway
    return km.inKeyguardRestrictedInputMode();
}
Juozas Kontvainis
quelle
Effiziente Lösung. Danke :)
Md. Sajedul Karim
Sehr schöne Lösung. Keine Berechtigungen erforderlich.
user3144836
Genial! Ich habe die Aufgabenliste verwendet, aber dafür ist GET TASK erforderlich. Ich weiß das wirklich zu schätzen!
Hexagod
15

Zu Ihrer Information, wenn Sie eine Gadenkan-Lösung verwenden (was großartig ist !!), vergessen Sie nicht, diese hinzuzufügen

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

zum Manifest.

bertz94
quelle
9
In Android Lollipop ist diese Erlaubnis veraltet
Mussa
14

Leicht bereinigte Version der Gadenkan-Lösung . Setzen Sie es eine beliebige Aktivität oder vielleicht eine Basisklasse für alle Ihre Aktivitäten.

protected boolean isRunningInForeground() {
    ActivityManager manager = 
         (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningTaskInfo> tasks = manager.getRunningTasks(1);
    if (tasks.isEmpty()) {
        return false;
    }
    String topActivityName = tasks.get(0).topActivity.getPackageName();
    return topActivityName.equalsIgnoreCase(getPackageName());
}

Um anrufen zu können getRunningTasks(), müssen Sie Folgendes hinzufügen AndroidManifest.xml:

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

Beachten Sie jedoch, was ActivityManager.getRunningTasks() Javadoc sagt:

Hinweis: Diese Methode ist nur zum Debuggen und Präsentieren von Benutzeroberflächen für die Aufgabenverwaltung vorgesehen. Dies sollte niemals für die Kernlogik in einer Anwendung verwendet werden, z. B. für die Entscheidung zwischen verschiedenen Verhaltensweisen basierend auf den hier enthaltenen Informationen. Solche Verwendungen werden nicht unterstützt und werden wahrscheinlich in Zukunft nicht mehr verwendet.

Update (Februar 2015)

Beachten Sie, dass getRunningTasks()wurde in API - Ebene 21 ist veraltet !

Ab LOLLIPOPdiesem Zeitpunkt steht diese Methode nicht mehr für Anwendungen von Drittanbietern zur Verfügung: Durch die Einführung dokumentenzentrierter Neuerungen können Personeninformationen an den Anrufer weitergegeben werden. Aus Gründen der Abwärtskompatibilität wird immer noch eine kleine Teilmenge seiner Daten zurückgegeben: zumindest die eigenen Aufgaben des Anrufers und möglicherweise einige andere Aufgaben wie "Home", von denen bekannt ist, dass sie nicht vertraulich sind.

Was ich früher geschrieben habe, ist also noch relevanter:

In vielen Fällen können Sie wahrscheinlich eine bessere Lösung finden. Zum Beispiel etwas in onPause()und onResume()vielleicht in einer BaseActivity für alle Ihre Aktivitäten tun.

(In unserem Fall wollten wir nicht, dass eine Offline-Warnaktivität gestartet wird, wenn wir nicht im Vordergrund stehen. In BaseActivity melden onPause()wir uns einfach vom RxJava ab und warten auf das Signal Subscription"ging offline".)

Jonik
quelle
Können Sie bitte den von Ihnen verwendeten RxJava-Code posten? Ich möchte RxJava verwenden und ich möchte in diesem Moment nicht viel Zeit damit verbringen, RxJava zu lernen :(
MBH
@MBH: Die Verwendung von RxJava wird wahrscheinlich nicht sehr fruchtbar sein, ohne einige Zeit damit zu verbringen, sich mit den Grundkonzepten vertraut zu machen ... :-) Hier ist auf jeden Fall ein kleines Beispiel .
Jonik
9

Nach Gadenkans Antwort brauchte ich so etwas, damit ich feststellen konnte, ob meine App nicht im Vordergrund lief, aber ich brauchte etwas, das app-weit war und nicht das Setzen / Deaktivieren von Flags in meiner gesamten Anwendung erforderte.

Gadenkans Code hat den Nagel auf den Kopf getroffen, aber er war nicht in meinem eigenen Stil und hatte das Gefühl, dass er aufgeräumter sein könnte, also hat er sich in meiner App darauf reduziert.

if (!context.getPackageName().equalsIgnoreCase(((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE)).getRunningTasks(1).get(0).topActivity.getPackageName()))
{
// App is not in the foreground
}

(Randnotiz: Sie können einfach das! Entfernen, wenn der Scheck umgekehrt funktionieren soll.)

Obwohl Sie bei diesem Ansatz die GET_TASKSErlaubnis benötigen .

CrosseyeJack
quelle
3

Wenn Sie die Support-Bibliothek Version 26 starten , können Sie mit ProcessLifecycleOwner den aktuellen Status der App ermitteln. Fügen Sie ihn einfach zu Ihren Abhängigkeiten hinzu, wie hier beschrieben , zum Beispiel:

dependencies {
    def lifecycle_version = "1.1.1"

    // ViewModel and LiveData
    implementation "android.arch.lifecycle:extensions:$lifecycle_version"
    // alternatively - Lifecycles only (no ViewModel or LiveData).
    //     Support library depends on this lightweight import
    implementation "android.arch.lifecycle:runtime:$lifecycle_version"
    annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version" // use kapt for Kotlin
}

Jetzt können Sie abfragen, ProcessLifecycleOwnerwann immer Sie den App-Status überprüfen möchten. Um beispielsweise zu überprüfen, ob die App im Vordergrund ausgeführt wird, müssen Sie nur Folgendes tun:

 boolean isAppInForeground = ProcessLifecycleOwner.get().getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED);
 if(!isAppInForeground)
    //Show Notification in status bar
Keivan Esbati
quelle
1
Das ist die richtige Antwort. Viele der anderen sollten als veraltet angesehen werden
11m0
1

Basierend auf den verschiedenen Antworten und Kommentaren finden Sie hier eine ausführlichere Version, die Sie einer Hilfsklasse hinzufügen können:

public static boolean isAppInForeground(Context context) {
  List<RunningTaskInfo> task =
      ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE))
          .getRunningTasks(1);
  if (task.isEmpty()) {
    return false;
  }
  return task
      .get(0)
      .topActivity
      .getPackageName()
      .equalsIgnoreCase(context.getPackageName());
}

Wie in anderen Antworten erwähnt, müssen Sie die folgende Berechtigung zu Ihrer hinzufügen AndroidManifest.xml.

<uses-permission android:name="android.permission.GET_TASKS"/>
Pierre-Antoine
quelle
In Android Lollipop ist diese Erlaubnis veraltet
Mussa
1

Ich möchte hinzufügen, dass eine sicherere Möglichkeit, dies zu tun, als zu überprüfen, ob sich Ihre App im Hintergrund befindet, bevor eine Benachrichtigung erstellt wird, darin besteht, den Broadcast-Empfänger onPause () bzw. onResume () zu deaktivieren und zu aktivieren.

Diese Methode gibt Ihnen mehr Kontrolle über die eigentliche Anwendungslogik und wird sich in Zukunft wahrscheinlich nicht ändern.

@Override
protected void onPause() {
    unregisterReceiver(mHandleMessageReceiver);
    super.onPause();
}

@Override
protected void onResume() {
    super.onResume();
    registerReceiver(mHandleMessageReceiver, new IntentFilter(DISPLAY_MESSAGE_ACTION));
}
d4c0d312
quelle
1

Ich habe eine einfachere und genauere Möglichkeit gefunden, um zu überprüfen, ob sich die Anwendung im Vordergrund oder im Hintergrund befindet, indem ich die Aktivitäten einem Booleschen Wert zugeordnet habe.

Überprüfen Sie das komplette Wesentliche hier

Mipreamble
quelle
1

Hier ist der Code für eine schöne einfache Lösung, die oben von @ user2690455 beschrieben wurde. Obwohl es ein bisschen ausführlich aussieht, werden Sie sehen, dass es insgesamt ziemlich leicht ist

In meinem Fall verwenden wir auch AppCompatActivity, daher musste ich 2 Basisklassen haben.

public class BaseActivity extends Activity {

    /**
     * Let field be set only in base class
     * All callers must use accessors,
     * and then it's not up to them to manage state.
     *
     * Making it static since ..
     * 1. It needs to be used across two base classes
     * 2. It's a singleton state in the app
     */
    private static boolean IS_APP_IN_BACKGROUND = false;

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

        BaseActivity.onResumeAppTracking(this);

        BaseActivity.setAppInBackgroundFalse();
    }

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

        BaseActivity.setAppInBackgroundTrue();
    }

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

        BaseActivity.setAppInBackgroundFalse();
    }

    protected static void onResumeAppTracking(Activity activity) {

        if (BaseActivity.isAppInBackground()) {

            // do requirements for returning app to foreground
        }

    }

    protected static void setAppInBackgroundFalse() {

        IS_APP_IN_BACKGROUND = false;
    }

    protected static void setAppInBackgroundTrue() {

        IS_APP_IN_BACKGROUND = true;
    }

    protected static boolean isAppInBackground() {

        return IS_APP_IN_BACKGROUND;
    }
}
Gene Bo
quelle
1

Dies ist nur dann nützlich, wenn Sie eine Aktion ausführen möchten, sobald Ihre Aktivität beginnt, und wenn Sie überprüfen möchten, ob sich die App im Vordergrund oder im Hintergrund befindet.

Anstatt Activity Manager zu verwenden, gibt es einen einfachen Trick, den Sie über Code ausführen können. Wenn Sie den Aktivitätszyklus genau beobachten, ist der Fluss zwischen zwei Aktivitäten und Vordergrund zu Hintergrund wie folgt. Angenommen, A und B sind zwei Aktivitäten.

Beim Übergang von A nach B: 1. onPause () von A heißt 2. onResume () von B heißt 3. onStop () von A wird aufgerufen, wenn B vollständig wieder aufgenommen wird

Wenn die App in den Hintergrund tritt: 1. onPause () von A wird aufgerufen 2. onStop () von A wird aufgerufen

Sie können Ihr Hintergrundereignis erkennen, indem Sie einfach ein Flag in die Aktivität setzen.

Erstellen Sie eine abstrakte Aktivität und erweitern Sie sie von Ihren anderen Aktivitäten, sodass Sie den Code für alle anderen Aktivitäten nicht kopieren und einfügen müssen, wo immer Sie ein Hintergrundereignis benötigen.

In abstrakten Aktivitäten erstellen Flag isAppInBackground.

In der onCreate () -Methode: isAppInBackground = false;

In der onPause () -Methode: isAppInBackground = false;

In der onStop () -Methode: isAppInBackground = true;

Sie müssen nur in onResume () einchecken, ob isAppInBackground wahr ist. n Nachdem Sie Ihr Flag überprüft haben, setzen Sie erneut isAppInBackground = false

Beim Übergang zwischen zwei Aktivitäten wird onSTop () von first immer wieder aufgerufen, nachdem die zweite Aktivität wieder aufgenommen wurde. Das Flag ist niemals wahr. Wenn sich die App im Hintergrund befindet, wird onStop () der Aktivität unmittelbar nach onPause aufgerufen, und daher ist das Flag true, wenn Sie öffnen die App später.

Bei diesem Ansatz gibt es jedoch noch ein weiteres Szenario. Wenn einer Ihrer App-Bildschirme bereits geöffnet ist und Sie das Handy in den Leerlauf versetzen, wechselt das Handy nach einiger Zeit in den Ruhemodus. Wenn Sie das Handy entsperren, wird es beim Hintergrundereignis behandelt.

Ankita
quelle
1

Hier ist eine Methode, die ich verwende (und die unterstützende Methode):

private boolean checkIfAppIsRunningInForeground() {
    ActivityManager activityManager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
    for(ActivityManager.RunningAppProcessInfo appProcessInfo : activityManager.getRunningAppProcesses()) {
        if(appProcessInfo.processName.contains(this.getPackageName())) {
            return checkIfAppIsRunningInForegroundByAppImportance(appProcessInfo.importance);
        }
    }
    return false;
}

private boolean checkIfAppIsRunningInForegroundByAppImportance(int appImportance) {
    switch (appImportance) {
        //user is aware of app
        case ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND:
        case ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE:
            return true;
        //user is not aware of app
        case ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND:
        case ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY:
        case ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE:
        case ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE:
        default:
            return false;
    }
}
Droide Chris
quelle
Es sieht so aus, als hätte ich für eine Lösung gestimmt, die vor zwei Jahren veröffentlicht wurde. Diese Methode funktioniert nach verschiedenen Sicherheitsupdates in Android nicht mehr.
Droid Chris
0

Hierfür gibt es keinen globalen Rückruf, aber für jede Aktivität ist es onStop (). Sie müssen sich nicht mit einem atomaren Int anlegen. Haben Sie einfach ein globales int mit der Anzahl der gestarteten Aktivitäten, inkrementieren Sie es in jeder Aktivität in onStart () und dekrementieren Sie es in onStop ().

Folgen Sie diesem

Kishan Vaghela
quelle
0
     public static boolean isAppRunning(Context context) {

 // check with the first task(task in the foreground)
 // in the returned list of tasks

   ActivityManager activityManager = (ActivityManager)
   context.getSystemService(Context.ACTIVITY_SERVICE);
 List<RunningTaskInfo> services =
 activityManager.getRunningTasks(Integer.MAX_VALUE);
     if
     (services.get(0).topActivity.getPackageName().toString().equalsIgnoreCase(context.getPackageName().toString()))
     {
     return true;
     }
     return false;
     }
Ashish Soni
quelle
getRunningTasks ist keine Option mehr - das neuere Sicherheitsmodell macht dies größtenteils nutzlos und ist veraltet.
Tony Maro
@AnaghHegde Sehen Sie sich die Antwort von Gadenkan an, indem Sie die Liste der laufenden Aktivitäten aus dem System ziehen.
Tony Maro
0

Die hier genannten bisherigen Ansätze sind nicht optimal. Der aufgabenbasierte Ansatz erfordert eine Berechtigung, die möglicherweise nicht erwünscht ist, und der "Boolesche" Ansatz ist anfällig für gleichzeitige Änderungsfehler.

Der Ansatz, den ich verwende und der (glaube ich) in den meisten Fällen recht gut funktioniert:

Verwenden Sie eine "MainApplication" -Klasse, um die Anzahl der Aktivitäten in AtomicInteger zu verfolgen :

import android.app.Application;

import java.util.concurrent.atomic.AtomicInteger;

public class MainApplication extends Application {
    static class ActivityCounter {
        private static AtomicInteger ACTIVITY_COUNT = new AtomicInteger(0);

        public static boolean isAppActive() {
            return ACTIVITY_COUNT.get() > 0;
        }

        public static void activityStarted() {
            ACTIVITY_COUNT.incrementAndGet();
        }

        public static void activityStopped() {
            ACTIVITY_COUNT.decrementAndGet();
        }
    }
}

Und erstellen Sie eine Basis-Aktivitätsklasse, die andere Aktivitäten erweitern würden:

import android.app.Activity;
import android.support.annotation.CallSuper;

public class TestActivity extends Activity {
    @Override
    @CallSuper
    protected void onStart() {
        MainApplication.ActivityCounter.activityStarted();
        super.onStart();
    }

    @Override
    @CallSuper
    protected void onStop() {
        MainApplication.ActivityCounter.activityStopped();
        super.onStop();
    }
}
Tadas Šubonis
quelle
Okay ... aber erwägen Sie die Verwendung von ACTIVITY_COUNT.decrementAndGet (); in activityStopped ().
ChrisCarneiro