Wie überprüfe ich, ob die Aktivität im Vordergrund oder im sichtbaren Hintergrund ist?

104

Ich habe einen Begrüßungsbildschirm auf einem Timer. Mein Problem ist, dass ich vor finish()meiner Aktivität überprüfen muss, ob die nächste Aktivität gestartet wurde, da ein Systemdialogfeld angezeigt wird und ich nur möchte finish(). Sobald der Benutzer eine Option aus dem Dialogfeld ausgewählt hat?

Ich weiß, dass es viele Fragen gibt, wie Sie feststellen können, ob Ihre Aktivität im Vordergrund steht, aber ich weiß nicht, ob dies auch Dialogfelder über der Aktivität zulässt.

Hier ist das Problem, das Rot ist meine Aktivität, die im Hintergrund ist, während der Dialog im Vordergrund steht:

Das Rot ist meine Aktivität im Hintergrund, während der Dialog im Vordergrund steht

BEARBEITEN: Ich habe versucht, es einfach nicht zu verwenden, finish()aber dann kann meine Aktivität in dem Stapel von Anwendungen wiederhergestellt werden, den ich vermeiden möchte.

Nick
quelle
Kann
jarmod
Zur Verdeutlichung möchten Sie eine Absichtsauswahl starten und warten, bis Ihre App beendet ist (), bis der Benutzer auf eine der Auswahlmöglichkeiten getippt hat. Es hört sich so an, als ob Sie Intent.createChooser () und startActivityForResult () gefolgt von finish () benötigen, wenn das Ergebnis empfangen wird.
Alanv
Mögliches Duplikat von Überprüfen, ob eine Android-Anwendung im Hintergrund ausgeführt wird
Douglas Nassif Roma Junior
ProcessLifecycleOwner ist die neueste Lösung
SR

Antworten:

189

Dies wird als richtige Lösung empfohlen :

Die richtige Lösung (Credits gehen an Dan, CommonsWare und NeTeInStEiN) Verfolgen Sie die Sichtbarkeit Ihrer Anwendung mithilfe der Methoden Activity.onPause, Activity.onResume selbst. Speichern Sie den Status "Sichtbarkeit" in einer anderen Klasse. Eine gute Wahl ist Ihre eigene Implementierung der Anwendung oder eines Dienstes (es gibt auch einige Variationen dieser Lösung, wenn Sie die Sichtbarkeit der Aktivitäten des Dienstes überprüfen möchten).

Beispiel Implementieren Sie eine benutzerdefinierte Anwendungsklasse (beachten Sie die statische Methode isActivityVisible ()):

public class MyApplication extends Application {

  public static boolean isActivityVisible() {
    return activityVisible;
  }  

  public static void activityResumed() {
    activityVisible = true;
  }

  public static void activityPaused() {
    activityVisible = false;
  }

  private static boolean activityVisible;
}

Registrieren Sie Ihre Anwendungsklasse in AndroidManifest.xml:

<application
    android:name="your.app.package.MyApplication"
    android:icon="@drawable/icon"
    android:label="@string/app_name" >

Fügen Sie jeder Aktivität im Projekt onPause und onResume hinzu (Sie können einen gemeinsamen Vorfahren für Ihre Aktivitäten erstellen, wenn Sie möchten, aber wenn Ihre Aktivität bereits von MapActivity / ListActivity usw. erweitert wurde, müssen Sie Folgendes weiterhin manuell schreiben). ::

@Override
protected void onResume() {
  super.onResume();
  MyApplication.activityResumed();
}

@Override
protected void onPause() {
  super.onPause();
  MyApplication.activityPaused();
}

In Ihrer finish()Methode möchten Sie isActivityVisible()überprüfen, ob die Aktivität sichtbar ist oder nicht. Dort können Sie auch prüfen, ob der Benutzer eine Option ausgewählt hat oder nicht. Fahren Sie fort, wenn beide Bedingungen erfüllt sind.

Die Quelle erwähnt auch zwei falsche Lösungen ... also vermeiden Sie das.

Quelle: Stackoverflow

Aber ich bin keine Wrapper-Klasse
quelle
Es gibt einen kleinen Moment zwischen
Ziel-
28
Das funktioniert nicht zuverlässig. Möglicherweise haben Sie die folgende Situation: Fortsetzen A Fortsetzen B Pause A. Jetzt ist activityVisible falsch, während die Anwendung sichtbar ist. Vielleicht verwenden Sie einen Sichtbarkeitszähler: sichtbaresCounter ++ in onResume und sichtbaresCounter - in onPause.
Joris Weimar
4
Einverstanden mit Joris Weimar, dass dies keine narrensichere Lösung ist. Ein Szenario ist , wenn der Benutzer nach unten gezogen , das Benachrichtigungsfeld, dann weder das onPause, onStopnoch das onResumeEreignis aufgerufen wird. Was machen Sie dann, wenn keines dieser Ereignisse ausgelöst wird?!
1
Tatsächlich funktioniert auch keine der anderen Antworten zu 100%.
2
Wenn die App mehr als eine Aktivität hat, funktioniert dieses Schema nicht. Mindestens durch Zähler ersetzen
ruX
70

Wenn Sie auf API-Level 14 oder höher abzielen, können Sie android.app.Application.ActivityLifecycleCallbacks verwenden

public class MyApplication extends Application implements ActivityLifecycleCallbacks {
    private static boolean isInterestingActivityVisible;

    @Override
    public void onCreate() {
        super.onCreate();

        // Register to be notified of activity state changes
        registerActivityLifecycleCallbacks(this);
        ....
    }

    public boolean isInterestingActivityVisible() {
        return isInterestingActivityVisible;
    }

    @Override
    public void onActivityResumed(Activity activity) {
        if (activity instanceof MyInterestingActivity) {
             isInterestingActivityVisible = true;
        }
    }

    @Override
    public void onActivityStopped(Activity activity) {
        if (activity instanceof MyInterestingActivity) {
             isInterestingActivityVisible = false;
        }
    }

    // Other state change callback stubs
    ....
}
Silbermaus
quelle
18
Sie können dies auch in den regulären Rückrufen zum Aktivitätslebenszyklus (onResume (), onStop ()) tun, würde ich sagen.
Daniel Wilson
5
@ DanielWilson Ich denke, es geht nicht darum, ein System zu bauen, um etwas zu tun, wo es bereits existiert. IMHO sollte dies die akzeptierte Antwort sein.
Jeffrey Blattman
26

UPD : aktualisiert auf Status Lifecycle.State.RESUMED. Danke an @htafoya dafür.

Im Jahr 2019 können Sie mithilfe einer neuen Support-Bibliothek 28+oder AndroidX einfach Folgendes verwenden:

val isActivityInForeground = activity.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)

Sie können mehr in der Dokumentation lesen, um zu verstehen, was unter der Haube passiert ist.

Alex Misiulia
quelle
2
Nicht wirklich, wahrscheinlich ist es besser zu platzieren activity.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED) oder zu starten. INITIALIZEDgarantiert nicht, dass es im Vordergrund ist.
Htafoya
11

Activity :: hasWindowFocus () gibt Ihnen den Booleschen Wert zurück, den Sie benötigen.

public class ActivityForegroundChecker extends TimerTask
{
    private static final long FOREGROUND_CHECK_PERIOD = 5000;
    private static final long FIRST_DELAY             = 3000;

    private Activity m_activity;
    private Timer    m_timer;

    public ActivityForegroundChecker (Activity p_activity)
    {
        m_activity = p_activity;
    }

    @Override
    public void run()
    {
        if (m_activity.hasWindowFocus() == true) {
            // Activity is on foreground
            return;
        }
        // Activity is on background.
    }

    public void start ()
    {
        if (m_timer != null) {
            return;
        }
        m_timer = new Timer();
        m_timer.schedule(this, FIRST_DELAY, FOREGROUND_CHECK_PERIOD);
    }

    public void stop ()
    {
        if (m_timer == null) {
            return;
        }
        m_timer.cancel();
        m_timer.purge();
        m_timer = null;
    }
}

Hier ist eine Beispielklasse, mit der Sie die Sichtbarkeit Ihrer Aktivitäten von jedem Ort aus überprüfen können.

Denken Sie daran, dass das Ergebnis falsch ist , wenn Sie einen Dialog anzeigen , da der Dialog den Hauptfokus hat. Davon abgesehen ist es sehr praktisch und zuverlässiger als Lösungsvorschläge.

Burak Tag
quelle
1
Vielen Dank für die Änderung der Antwort @Burak Day, es ist jetzt tatsächlich eine Antwort
Nick
Dies funktioniert nicht. Ich würde lieber eine boolesche Eigenschaft in der Klasse verwenden, die in OnResume auf true und in OnPause () auf false gesetzt ist.
Chandler
@Chandler Was ist das genaue Problem, das Sie mit diesem Code haben? Auch welche Version?
Burak Day
@Chandler auch, was ist, wenn Sie keinen Zugriff auf Aktivitätslebenszyklusmethoden haben. Stellen Sie sich vor, Sie überprüfen nur die Sichtbarkeit der Aktivität in einer Bibliothek.
Burak Day
Das eigentliche Problem dieser Antwort ist, dass sie NICHT funktioniert. Activity.hasWindowFocus ist wahr und kann nicht garantieren, dass die Aktivität zwischen dem Status onResume und onPause liegt. Ich würde eher empfehlen, in dieser Aktivität eine bool isResumed-Eigenschaft hinzuzufügen, den Wert manuell festzulegen und eine get-Methode hinzuzufügen.
Chandler
10

Dies ist genau der Unterschied zwischen onPauseund den onStopEreignissen der Aktivität, wie in der Dokumentation zur Aktivitätsklasse beschrieben .

Wenn ich Sie richtig verstehe, möchten Sie finish()von Ihrer Aktivität aus anrufen, onStopum sie zu beenden. Siehe das angehängte Bild der Activity Lifecycle Demo App . So sieht es aus, wenn Aktivität B von Aktivität A gestartet wird. Die Reihenfolge der Ereignisse ist von unten nach oben, sodass Sie sehen können, dass Aktivität A onStopaufgerufen wird, nachdem Aktivität B onResumebereits aufgerufen wurde.

Demo zum Aktivitätslebenszyklus

Wenn ein Dialogfeld angezeigt wird, wird Ihre Aktivität im Hintergrund abgeblendet und nur onPauseaufgerufen.

Muzikant
quelle
7

Zwei mögliche Lösungen:

1) Aktivitätslebenszyklus-Rückrufe

Verwenden Sie eine Anwendung , die ActivityLifecycleCallbacks implementiert, und verwenden Sie sie, um die Lebenszyklusereignisse von Aktivitäten in Ihrer Anwendung zu verfolgen. Beachten Sie, dass ActivityLifecycleCallbacks für Android-API> = 14 sind. Für frühere Android-APIs müssen Sie es in all Ihren Aktivitäten selbst implementieren ;-)

Verwenden Sie die Anwendung, wenn Sie Status für Aktivitäten freigeben / speichern müssen.

2) Überprüfen Sie, ob Prozessinformationen ausgeführt werden

Mit dieser Klasse RunningAppProcessInfo können Sie den Status eines laufenden Prozesses überprüfen

Rufen Sie die Liste der laufenden Prozesse mit ActivityManager.getRunningAppProcesses () ab und filtern Sie die Ergebnisliste, um nach der gewünschten RunningAppProcessInfo zu suchen und ihre "Wichtigkeit" zu überprüfen.

avianey
quelle
3

Verwenden Sie die Zeitspanne zwischen Pause und Wiederaufnahme aus dem Hintergrund, um festzustellen, ob sie aus dem Hintergrund wach ist

In der benutzerdefinierten Anwendung

private static boolean isInBackground;
private static boolean isAwakeFromBackground;
private static final int backgroundAllowance = 10000;

public static void activityPaused() {
    isInBackground = true;
    final Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            if (isInBackground) {
                isAwakeFromBackground = true;
            }
        }
    }, backgroundAllowance);
    Log.v("activity status", "activityPaused");
}

public static void activityResumed() {
    isInBackground = false;
    if(isAwakeFromBackground){
        // do something when awake from background
        Log.v("activity status", "isAwakeFromBackground");
    }
    isAwakeFromBackground = false;
    Log.v("activity status", "activityResumed");
}

In der BaseActivity-Klasse

@Override
protected void onResume() {
  super.onResume();
  MyApplication.activityResumed();
}

@Override
protected void onPause() {
  super.onPause();
  MyApplication.activityPaused();
}
Kit
quelle
3

Ich denke, ich habe eine bessere Lösung. Weil Sie einfach MyApplication.activityResumed () einbauen können; zu jeder Aktivität um eine Ausdehnung.

Zuerst müssen Sie erstellen (wie CyberneticTwerkGuruOrc)

public class MyApplication extends Application {

  public static boolean isActivityVisible() {
    return activityVisible;
  }  

  public static void activityResumed() {
    activityVisible = true;
  }

  public static void activityPaused() {
    activityVisible = false;
  }

  private static boolean activityVisible;
}

Als Nächstes müssen Sie die Anwendungsklasse zu AndroidManifest.xml hinzufügen

<application
    android:name="your.app.package.MyApplication"
    android:icon="@drawable/icon"
    android:label="@string/app_name" >

Erstellen Sie dann die Klasse ActivityBase

public class ActivityBase extends Activity {

    @Override
    protected void onPause() {
        super.onPause();
        MyApplication.activityPaused();
    }

    @Override
    protected void onResume() {
        super.onResume();
        MyApplication.activityResumed();
    }
}

Wenn Sie eine neue Aktivität erstellen, können Sie sie einfach um ActivityBase anstelle von Activity erweitern.

public class Main extends ActivityBase {
    @Override
    protected void onResume() {
        super.onResume();
    }

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

Für mich ist es eine bessere Methode, weil Sie sich nur an die Erweiterung durch ActivityBase erinnern müssen. Darüber hinaus können Sie Ihre Basisfunktion in Zukunft erweitern. In meinem Fall habe ich Empfänger für meinen Dienst und Warnungen zum Netzwerk in einer Klasse hinzugefügt.

Wenn Sie die Sichtbarkeit Ihrer App überprüfen möchten, können Sie einfach anrufen

MyApplication.isActivityVisible()
Eliasz Kubala
quelle
Was ist, wenn ich meine Aktivitäten benötige, um die AppCombatActivity zu erweitern?
Winklerrr
2

Dies kann durch eine effiziente Verwendung erreicht werden Application.ActivityLifecycleCallbacks erreicht werden

Nehmen wir zum Beispiel den Namen der Aktivitätsklasse als ProfilActivity, um herauszufinden, ob er sich im Vordergrund oder im Hintergrund befindet

Zuerst müssen wir unsere Anwendungsklasse durch Erweitern erstellen Anwendungsklasse

welche implementiert

Application.ActivityLifecycleCallbacks

Lassen Sie uns meine Anwendungsklasse wie folgt sein

Anwendungsklasse

public class AppController extends Application implements Application.ActivityLifecycleCallbacks {


private boolean activityInForeground;

@Override
public void onCreate() {
    super.onCreate();

//register ActivityLifecycleCallbacks  

    registerActivityLifecycleCallbacks(this);

}



public static boolean isActivityVisible() {
    return activityVisible;
}

public static void activityResumed() {
    activityVisible = true;
}

public static void activityPaused() {
    activityVisible = false;
}

private static boolean activityVisible;

@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {

}

@Override
public void onActivityStarted(Activity activity) {

}

@Override
public void onActivityResumed(Activity activity) {
    //Here you can add all Activity class you need to check whether its on screen or not

    activityInForeground = activity instanceof ProfileActivity;
}

@Override
public void onActivityPaused(Activity activity) {

}

@Override
public void onActivityStopped(Activity activity) {

}

@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

}

@Override
public void onActivityDestroyed(Activity activity) {

}

public boolean isActivityInForeground() {
    return activityInForeground;
}
}

In der obigen Klasse gibt es ein Override- Verfahren für ActivityResumed von ActivityLifecycleCallbacks

 @Override
public void onActivityResumed(Activity activity) {
    //Here you can add all Activity class you need to check whether its on screen or not

    activityInForeground = activity instanceof ProfileActivity;
}

Wenn alle Aktivitätsinstanzen gefunden werden, die derzeit auf dem Bildschirm angezeigt werden, überprüfen Sie einfach mit der oben beschriebenen Methode, ob Ihre Aktivität auf dem Bildschirm angezeigt wird oder nicht.

Registrieren Sie Ihre Anwendungsklasse in manifest.xml

<application
    android:name=".AppController" />

Um das Wetter zu überprüfen, ist die Aktivität Vordergrund oder Hintergrund gemäß der obigen Lösung. Rufen Sie die folgende Methode an den Stellen auf, die Sie überprüfen müssen

AppController applicationControl = (AppController) getApplicationContext();
    if(applicationControl.isActivityInForeground()){
     Log.d("TAG","Activity is in foreground")
    }
    else
    {
      Log.d("TAG","Activity is in background")
    }
Ramz
quelle
1

Wenn Sie wissen möchten, ob eine Aktivität Ihrer App auf dem Bildschirm sichtbar ist, können Sie Folgendes tun:

public class MyAppActivityCallbacks implements Application.ActivityLifecycleCallbacks {
private Set<Class<Activity>> visibleActivities = new HashSet<>();

@Override
public void onActivityResumed(Activity activity) {
    visibleActivities.add((Class<Activity>) activity.getClass());
}

@Override
public void onActivityStopped(Activity activity) {
     visibleActivities.remove(activity.getClass());
}

public boolean isAnyActivityVisible() {
    return !visibleActivities.isEmpty();
}

@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}

@Override
public void onActivityStarted(Activity activity) {}

@Override
public void onActivityPaused(Activity activity) {}

@Override
public void onActivityDestroyed(Activity activity) {}

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

Erstellen Sie einfach einen Singleton dieser Klasse und legen Sie ihn in Ihrer Anwendungsinstanz wie folgt fest:

class App extends Application{
     @Override
     public void onCreate() {
         registerActivityLifecycleCallbacks(myAppActivityCallbacks);
     }
}

Dann können Sie die isAnyActivityVisible () -Methode Ihrer MyAppActivityCallbacks-Instanz überall verwenden!

Vasil Stolyarchuk
quelle
0

Haben Sie versucht, nicht finish aufzurufen und "android: noHistory =" true "in das Manifest aufzunehmen? Dadurch wird verhindert, dass die Aktivität in den Stapel verschoben wird.

shaish
quelle
0

Ich muss sagen, dass Ihr Workflow nicht normal für Android ist. In Android müssen Sie nichtfinish() Ihre Aktivität wenn Sie eine andere Aktivität von Intent aus öffnen möchten. Aus praktischen Gründen kann der Benutzer mit Android die Zurück-Taste verwenden, um von der Aktivität zurückzukehren, die Sie für Ihre App geöffnet haben.

Lassen Sie das System einfach Ihre Aktivität stoppen und speichern Sie alles, was Sie benötigen, wenn Ihre Aktivität zurückgerufen wird.

Owen Zhao
quelle
Ich weiß wirklich nicht, warum dies herabgestuft wird. Zumindest einen Kommentar als Grund zu geben, ist das, was ich will.
Owen Zhao
3
"buu das ist nicht der android" weg Antworten sind lästig und beantworten die gestellte Frage überhaupt nicht. Darüber hinaus gibt es gültige Gründe, um () zu beenden. - Zum Beispiel ist es denkbar, dass es keinen Zweck hat, darauf zurückzugreifen, sobald die Aktion stattgefunden hat. Mit anderen Worten, denkst du, sie haben zum Spaß finish () da reingelegt? Es ist genau das, was der Fragesteller vermeiden wollte
Lassi Kinnunen
0

Speichern Sie eine Flagge, wenn Sie angehalten oder fortgesetzt werden. Wenn Sie wieder aufgenommen werden, bedeutet dies, dass Sie im Vordergrund stehen

boolean  isResumed = false;

@Override
public void onPause() {
  super.onPause();    
  isResumed = false;
}

@Override
public void onResume() {
  super.onResume();    
  isResumed = true;
}

private void finishIfForeground() {
  if (isResumed) {
    finish();
  }
}
yoah
quelle
0

Eine mögliche Lösung könnte darin bestehen, ein Flag zu setzen, während der Systemdialog angezeigt wird, und dann in der onStop-Methode des Aktivitätslebenszyklus zu überprüfen, ob das Flag vorhanden ist. Wenn dies der Fall ist, beenden Sie die Aktivität.

Wenn der Systemdialog beispielsweise durch einen Knopfdruck ausgelöst wird, sieht der Listener onclick möglicherweise so aus

private OnClickListener btnClickListener = new OnClickListener() {

    @Override
    public void onClick(View v) {           
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_SEND);
        intent.setType("text/plain");
        CheckActivity.this.startActivity(Intent.createChooser(intent, "Complete action using"));
        checkFlag = true;  //flag used to check

    }
};

und bei Unterbrechung der Aktivität:

@Override
protected void onStop() {
    if(checkFlag){
        finish();
    }
    super.onStop();
}
Diya
quelle
0

Warum nicht dafür Sendungen verwenden? Die zweite Aktivität (die aktiv sein muss) kann eine lokale Sendung wie folgt senden:

//put this in onCreate(..) or any other lifecycle method that suits you best
//notice the string sent to the intent, it will be used to register a receiver!
Intent result = new Intent("broadcast identifier");
result.putString("some message");//this is optional
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(result);

Schreiben Sie dann einen einfachen Empfänger innerhalb der Splash-Aktivität:

//this goes on the class level (like a class/instance variable, not in a method) of your splash activity:
private BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        //kill activity here!!!
        //mission accomplished!
    }
};

und registrieren Sie Ihren neuen Empfänger beim LocalBroadcastManager, um die Sendung Ihrer zweiten Aktivität anzuhören:

//notice the string sent to the intent filter, this is where you tell the BroadcastManager which broadcasts you want to listen to!
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(receiver, new IntentFilter("broadcast identifier"));

HINWEIS: Sie können eine Konstante oder eine Zeichenfolgenressource für die Zeichenfolge "Broadcast-ID" verwenden.


quelle
Für mehr Sicherheit und Effizienz verwenden Sie LocalBroadcastManagerhier
Alexander Farber
0

Wenn Sie finish()nur verwenden, um zu vermeiden, dass eine neue App im Stapel (Aufgabe) Ihrer App gestartet wird, können Sie Intent.FLAG_ACTIVITY_NEW_TASKbeim Starten einer neuen Anwendung das Flag verwenden und überhaupt nicht aufrufen finish(). Laut Dokumentation ist dies das Flag, das zum Implementieren eines Verhaltens im "Launcher" -Stil verwendet werden soll.

// just add this line before you start an activity
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
sergej shafarenka
quelle
0

Verwenden Sie diese Methoden innerhalb eines Activity.

isDestroyed()

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

isFinishing()

Hinzugefügt in API 1
Ü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.


Aus der Dokumentation zu Speicherlecks

Ein häufiger Fehler AsyncTaskbesteht darin, einen starken Verweis auf den Host Activity(oder Fragment) zu erfassen :

class MyActivity extends Activity {
  private AsyncTask<Void, Void, Void> myTask = new AsyncTask<Void, Void, Void>() {
    // Don't do this! Inner classes implicitly keep a pointer to their
    // parent, which in this case is the Activity!
  }
}

Dies ist ein Problem, da AsyncTaskes die Eltern leicht überleben kannActivity , z. B. wenn eine Konfigurationsänderung während der Ausführung der Aufgabe .

Der richtige Weg, dies zu tun, besteht darin, Ihre Aufgabe zu einer staticKlasse zu machen , die das übergeordnete Element nicht erfasst und einen schwachen Verweis auf den Host enthält Activity:

class MyActivity extends Activity {
  static class MyTask extends AsyncTask<Void, Void, Void> {
    // Weak references will still allow the Activity to be garbage-collected
    private final WeakReference<MyActivity> weakActivity;

    MyTask(MyActivity myActivity) {
      this.weakActivity = new WeakReference<>(myActivity);
    }

    @Override
    public Void doInBackground(Void... params) {
      // do async stuff here
    }

    @Override
    public void onPostExecute(Void result) {
      // Re-acquire a strong reference to the activity, and verify
      // that it still exists and is active.
      MyActivity activity = weakActivity.get();
      if (activity == null
          || activity.isFinishing()
          || activity.isDestroyed()) {
        // activity is no longer valid, don't do anything!
        return;
      }

      // The activity is still valid, do main-thread stuff here
    }
  }
}
Sanket Berde
quelle
0

Hier ist eine Lösung mit ApplicationKlasse.

public class AppSingleton extends Application implements Application.ActivityLifecycleCallbacks {

private WeakReference<Context> foregroundActivity;


@Override
public void onActivityResumed(Activity activity) {
    foregroundActivity=new WeakReference<Context>(activity);
}

@Override
public void onActivityPaused(Activity activity) {
    String class_name_activity=activity.getClass().getCanonicalName();
    if (foregroundActivity != null && 
            foregroundActivity.get().getClass().getCanonicalName().equals(class_name_activity)) {
        foregroundActivity = null;
    }
}

//............................

public boolean isOnForeground(@NonNull Context activity_cntxt) {
    return isOnForeground(activity_cntxt.getClass().getCanonicalName());
}

public boolean isOnForeground(@NonNull String activity_canonical_name) {
    if (foregroundActivity != null && foregroundActivity.get() != null) {
        return foregroundActivity.get().getClass().getCanonicalName().equals(activity_canonical_name);
    }
    return false;
}
}

Sie können es einfach wie folgt verwenden:

((AppSingleton)context.getApplicationContext()).isOnForeground(context_activity);

Wenn Sie einen Verweis auf die erforderliche Aktivität haben oder den kanonischen Namen der Aktivität verwenden, können Sie herausfinden, ob sie im Vordergrund steht oder nicht. Diese Lösung ist möglicherweise nicht kinderleicht. Daher sind Ihre Kommentare sehr willkommen.

TMtech
quelle
0

Ich weiß nicht, warum niemand über sharedPreferences für Aktivität A gesprochen hat und eine SharedPreference wie diese festgelegt hat (zum Beispiel in onPause ()):

SharedPreferences pref = context.getSharedPreferences(SHARED_PREF, 0);
SharedPreferences.Editor editor = pref.edit();
editor.putBoolean("is_activity_paused_a", true);
editor.commit();

Ich denke, dies ist der zuverlässige Weg, um Aktivitäten sichtbar zu machen.

HZDI
quelle
0

Wäre Activity.onWindowFocusChanged(boolean hasFocus)hier nützlich? Das, plus ein Klasse-Level - Flag, so etwas wie , isFocuseddassonWindowFocusChanged Sätze, wäre eine einfache Möglichkeit, an einem beliebigen Stelle in Ihrer Tätigkeit zu sagen , wenn es fokussiert ist oder nicht. Nach dem Lesen der Dokumente sieht es so aus, als würde es in jeder Situation, in der sich die Aktivität nicht direkt im physischen "Vordergrund" befindet, richtig "false" setzen, z. B. wenn ein Dialogfeld angezeigt oder die Benachrichtigungsleiste heruntergezogen wird.

Beispiel:

boolean isFocused;
@Override
void onWindowFocusChanged (boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    isFocused = hasFocus;
}

void someMethod() {
    if (isFocused) {
        // The activity is the foremost object on the screen
    } else {
        // The activity is obscured or otherwise not visible
    }
}
InsanityOnABun
quelle
0

Wenn Sie EventBus verwenden , wird es als Methode aufgerufen hasSubscriberForEvent, mit der überprüft werden kann, ob ein Activityfokussiert ist.

Kris B.
quelle
-3

Früher mochte ich,

wenn die Aktivität nicht im Vordergrund steht

getIntent ()

wird null zurückgeben. : = P.

Jacob Abraham
quelle