Wie bekomme ich den aktuellen Vordergrundaktivitätskontext in Android?

171

Immer wenn meine Sendung ausgeführt wird, möchte ich eine Warnung für die Vordergrundaktivität anzeigen.

Deepali
quelle
von wo aus Sie den Kontext der Aktivität erhalten möchten. Ist dies Ihre App-Aktivität oder eine andere Anwendung.
AAnkit
Dies ist eine App-Aktivität. Ich habe die Codierung des Alarmdialogs für die Funktion onreceive () des Broadcastempfängers durchgeführt.
Deepali
eine App-Aktivität! Ist das deine App? und warum willst du das, aus irgendeinem Grund, kann es eine Alternative dafür geben
AAnkit
Ich möchte eine Warnung für meine Vordergrundaktivität anzeigen. Ist dies eine andere Möglichkeit, um eine Warnung für eine Vordergrundaktivität ohne Kontext anzuzeigen?
Deepali
1
Wenn Sie nur COntext als Parameter erhalten, können Sie context.getApplicationContext ()
AAnkit

Antworten:

39

Zu wissen , dass Activitymanager verwaltet Aktivität , so können wir Informationen aus gewinnen Activitymanager . Wir bekommen den aktuellen Vordergrund, in dem Aktivität ausgeführt wird

ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
ComponentName cn = am.getRunningTasks(1).get(0).topActivity;

UPDATE 2018/10/03
getRunningTasks () ist DEPRECATED. siehe die Lösungen unten.

Diese Methode wurde in API-Level 21 nicht mehr unterstützt. Ab Build.VERSION_CODES.LOLLIPOP 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.

KAlO2
quelle
16
glaube nicht Martin, aus der SDK-Hilfe von getRunningTasks "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"
ruhalde
3
Anscheinend unterstützt dies nur eine begrenzte Teilmenge der laufenden Aufgaben in Android 5 / Lollipop.
Sam
7
In der Dokumentation zu ActivityManager.getRunningTasks () heißt es: "Diese Methode wurde in API-Version 21 nicht mehr unterstützt."
Markshep
210

( Hinweis: In API 14 wurde eine offizielle API hinzugefügt: Siehe diese Antwort https://stackoverflow.com/a/29786451/119733 )

VERWENDEN SIE KEINE VORHERIGE (waqas716) Antwort.

Aufgrund des statischen Verweises auf die Aktivität tritt ein Speicherverlustproblem auf. Weitere Informationen finden Sie unter folgendem Link: http://android-developers.blogspot.fr/2009/01/avoiding-memory-leaks.html

Um dies zu vermeiden, sollten Sie Aktivitätsreferenzen verwalten. Fügen Sie den Namen der Anwendung in die Manifestdatei ein:

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

Ihre Anwendungsklasse:

  public class MyApp extends Application {
        public void onCreate() {
              super.onCreate();
        }

        private Activity mCurrentActivity = null;
        public Activity getCurrentActivity(){
              return mCurrentActivity;
        }
        public void setCurrentActivity(Activity mCurrentActivity){
              this.mCurrentActivity = mCurrentActivity;
        }
  }

Erstellen Sie eine neue Aktivität:

public class MyBaseActivity extends Activity {
    protected MyApp mMyApp;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mMyApp = (MyApp)this.getApplicationContext();
    }
    protected void onResume() {
        super.onResume();
        mMyApp.setCurrentActivity(this);
    }
    protected void onPause() {
        clearReferences();
        super.onPause();
    }
    protected void onDestroy() {        
        clearReferences();
        super.onDestroy();
    }

    private void clearReferences(){
        Activity currActivity = mMyApp.getCurrentActivity();
        if (this.equals(currActivity))
            mMyApp.setCurrentActivity(null);
    }
}

Anstatt jetzt die Aktivitätsklasse für Ihre Aktivitäten zu erweitern, erweitern Sie einfach MyBaseActivity. Jetzt können Sie Ihre aktuelle Aktivität wie folgt aus der Anwendung oder dem Aktivitätskontext abrufen:

Activity currentActivity = ((MyApp)context.getApplicationContext()).getCurrentActivity();
gezdy
quelle
9
Sie könnten einfach WeakReference verwenden und das gleiche Ergebnis mit weniger Code erzielen.
Nacho Coloma
5
@Nacho Ich würde niemals empfehlen, WeakReferencesin Android zu verwenden. Der GC sammelt sie schneller als Sie denken.
rekire
4
@MaximKorobov Ja, es ist möglich, wenn Sie finish () von onCreate () aus aufrufen, wenn Sie Ihre Aktivität nur zum Starten einer anderen Aktivität verwenden und diese stoppen. In diesem Szenario werden onPause () und onStoo () übersprungen. Siehe die untere Anmerkung von: developer.android.com/training/basics/activity-lifecycle/…
Rodrigo Leitão
2
@rekire @NachoColoma Die Verwendung von WeakReferencewird für das Caching nicht empfohlen. Dies ist kein Caching. Dies ist der mCurrentActivityWille, der nur dann einen Verweis darauf hat, wenn er lebt, sodass der WeakReferenceWille niemals gesammelt wird, solange er Activityoben ist. Was @NachoColoma jedoch vorschlägt, ist falsch, da das WeakReferencemöglicherweise immer noch auf eine nicht wieder aufgenommene Aktivität (nicht aktiv / nicht oben) verweist, wenn die Variable nicht gelöscht wird!
TWiStErRob
14
Ab Android API Level 14 sollte es möglich sein, diese zu verwenden Application .ActivityLifecycleCallbacks, was zentraler wäre und Sie müssten bei all Ihren Aktivitäten keinen Verwaltungscode hinzufügen. Siehe auch developer.android.com/reference/android/app/…
Filou
68

Ich erweitere die Antwort von @ gezdy.

Anstatt sich bei jeder Aktivität Applicationbei der manuellen Codierung "registrieren" zu müssen , können wir seit Stufe 14 die folgende API verwenden, um einen ähnlichen Zweck mit weniger manueller Codierung zu erreichen.

public void registerActivityLifecycleCallbacks (Application.ActivityLifecycleCallbacks callback)

http://developer.android.com/reference/android/app/Application.html#registerActivityLifecycleCallbacks%28android.app.Application.ActivityLifecycleCallbacks%29

In Application.ActivityLifecycleCallbackskönnen Sie bekommen, was daran Activity"befestigt" oder "losgelöst" ist Application.

Diese Technik ist jedoch erst seit API-Level 14 verfügbar.

Cheok Yan Cheng
quelle
1
Was ist mit all den anderen Antworten los? Dies ist eindeutig eine API für diesen Zweck. Vielen Dank, Cheok Yan Cheng
Michael Bushe
2
@MichaelBushe - 2012, als die anderen Antworten geschrieben wurden, war abhängig von API-Level 14 nicht auf jedem Gerät etwas zu finden, da die API erst kürzlich veröffentlicht wurde (Oktober 2011).
ToolmakerSteve
4
Es wurde eine Antwort gefunden, die zeigt, wie dieser Ansatz verwendet wird: stackoverflow.com/a/11082332/199364 Der Vorteil besteht darin, dass an den Aktivitäten selbst nichts unternommen werden muss . Der Code befindet sich alle in Ihrer benutzerdefinierten Rückrufklasse. Sie erstellen einfach eine Klasse implements Application.ActivityLifecycleCallbacks, und fügen die Methoden hinzu, um dies zu implementieren. Geben Sie dann im Konstruktor dieser Klasse (oder in onCreate oder init oder einer anderen Methode, die ausgeführt wird, wenn die Instanz aktiv / bereit wird) getApplication().registerActivityLifecycleCallbacks(this);die letzte Zeile ein.
ToolmakerSteve
Ich denke, Ihre Antwort ist am besten
Burulangtu
2
gute Antwort. Der einzige Nachteil ist, dass Sie die Aktivität noch an einem Ort speichern müssen, wenn Sie Ihre Klasse nach der aktuellen Aktivität abfragen müssen. Sie müssen also weiterhin Speicherverluste vermeiden und die Referenz auf Null setzen.
Raphael C
56

Update 2 : Hierzu wurde eine offizielle API hinzugefügt. Verwenden Sie stattdessen ActivityLifecycleCallbacks .

AKTUALISIEREN:

Wie von @gezdy gezeigt, und ich bin dafür dankbar. Setzen Sie den Verweis für die aktuelle Aktivität ebenfalls auf null , anstatt ihn nur bei jedem onResume zu aktualisieren. Setzen Sie ihn bei onDestroy jeder Aktivität auf null, um Speicherverlustprobleme zu vermeiden.

Vor einiger Zeit brauchte ich die gleiche Funktionalität und hier ist die Methode, wie ich dies erreicht habe. Überschreiben Sie bei jeder Aktivität diese Lebenszyklusmethoden.

@Override
protected void onResume() {
    super.onResume();
    appConstantsObj.setCurrentActivity(this);

}

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

@Override
protected void onDestroy() {        
   clearReferences();
   super.onDestroy();
}

private void clearReferences(){
          Activity currActivity = appConstantsObj.getCurrentActivity();
          if (this.equals(currActivity))
                appConstantsObj.setCurrentActivity(null);
}

Jetzt können Sie in Ihrer Broadcast-Klasse auf die aktuelle Aktivität zugreifen, um eine Warnung anzuzeigen.

Waqas
quelle
3
Diese Antwort sollte wirklich mehr Up-Votes erhalten, eine einfache Lösung, aber leistungsstark, wenn Sie Klassen haben, die Aktivitäten manipulieren müssen, aber keine Aktivitäten selbst sind.
Ryvianstyron
Es geht nur um eine statische Referenz Ihres Aktivitätsobjekts. Sie können es erstellen, wo immer Sie wollen :). Es spielt keine Rolle.
Waqas
Dies entspricht übrigens Ihrer vorherigen Antwort. Applicationwird nur einmal erstellt und niemals wie eine statische Variable gesammelt.
Zapl
1
Es wird Probleme mit hierarchischen Aktivitäten geben. Wenn Sie von einer untergeordneten Aktivität zur übergeordneten zurückkehren, gilt Folgendes: (1) wird als onPause des Kindes bezeichnet. (2) onResume der Eltern; (3) onDestroy des Kindes ==> Die aktuelle Aktivität ist null. Sie sollten einige Überprüfungen wie @gezdy in seinem Beispiel in der Methode clearReferences durchführen.
Kunst
4
@ waqas716 würde ich vorschlagen , den Zustand , in vereinfachen clearReferences()zu (this.equals(currActivity)).
NaXa
51

@lockwobr Danke für das Update

Dies funktioniert nicht 100% der Zeit in API-Version 16, wenn Sie den Code auf Github lesen, wurde die Funktion "currentActivityThread" in Kitkat geändert, daher möchte ich Version 19ish sagen, eine schwer zu vergleichende API-Version mit Releases in Github .

Der Zugriff auf den Strom Activityist sehr praktisch. Wäre es nicht schön, eine Statik zu haben?getActivity Methode die aktuelle Aktivität ohne unnötige Fragen zurückgibt?

Die ActivityKlasse ist sehr nützlich. Es bietet Zugriff auf den UI-Thread, die Ansichten, Ressourcen und vieles mehr der Anwendung. Zahlreiche Methoden erfordern a Context, aber wie bekommt man den Zeiger? Hier sind einige Möglichkeiten:

  • Verfolgen des Anwendungsstatus mithilfe überschriebener Lebenszyklusmethoden. Sie müssen die aktuelle Aktivität in einer statischen Variablen speichern und benötigen Zugriff auf den Code aller Aktivitäten.
  • Verfolgen des Anwendungsstatus mithilfe von Instrumentierung. Deklarieren Sie Instrumentation im Manifest, implementieren Sie es und verwenden Sie seine Methoden, um Aktivitätsänderungen zu verfolgen. Übergeben eines Aktivitätszeigers an Methoden und Klassen, die in Ihren Aktivitäten verwendet werden. Injizieren des Zeigers mithilfe einer der Code-Injection-Bibliotheken. Alle diese Ansätze sind ziemlich unpraktisch ; Glücklicherweise gibt es einen viel einfacheren Weg, um die aktuelle Aktivität zu erhalten.
  • Das System benötigt anscheinend Zugriff auf alle Aktivitäten ohne die oben genannten Probleme. Es gibt also höchstwahrscheinlich eine Möglichkeit, Aktivitäten nur mit statischen Aufrufen abzurufen. Ich habe viel Zeit damit verbracht, die Android-Quellen auf grepcode.com zu durchsuchen, und ich habe gefunden, wonach ich gesucht habe. Es gibt eine Klasse namens ActivityThread. Diese Klasse hat Zugriff auf alle Aktivitäten und, was noch besser ist, über eine statische Methode zum Abrufen des aktuellen Werts ActivityThread. Es gibt nur ein kleines Problem: Die Aktivitätsliste hat Paketzugriff.

Einfach durch Reflektion zu lösen:

public static Activity getActivity() {
    Class activityThreadClass = Class.forName("android.app.ActivityThread");
    Object activityThread = activityThreadClass.getMethod("currentActivityThread").invoke(null);
    Field activitiesField = activityThreadClass.getDeclaredField("mActivities");
    activitiesField.setAccessible(true);

    Map<Object, Object> activities = (Map<Object, Object>) activitiesField.get(activityThread);
    if (activities == null)
        return null;

    for (Object activityRecord : activities.values()) {
        Class activityRecordClass = activityRecord.getClass();
        Field pausedField = activityRecordClass.getDeclaredField("paused");
        pausedField.setAccessible(true);
        if (!pausedField.getBoolean(activityRecord)) {
            Field activityField = activityRecordClass.getDeclaredField("activity");
            activityField.setAccessible(true);
            Activity activity = (Activity) activityField.get(activityRecord);
            return activity;
        }
    }

    return null;
}

Eine solche Methode kann überall in der App verwendet werden und ist viel bequemer als alle genannten Ansätze. Außerdem scheint es nicht so unsicher zu sein, wie es aussieht. Es werden keine neuen potenziellen Lecks oder Nullzeiger eingeführt.

Das obige Code-Snippet enthält keine Ausnahmebehandlung und geht naiv davon aus, dass die erste ausgeführte Aktivität die ist, nach der wir suchen. Möglicherweise möchten Sie einige zusätzliche Überprüfungen hinzufügen.

Blogeintrag

AZ_
quelle
2
In Kitkat und höher ist mActivities nicht HashMap, sondern ArrayMap. Daher müssen Sie diese Zeile ändern: HashMap activity = (HashMap) activityField.get (activityThread); um so auszusehen: ArrayMap activity = (ArrayMap) activityField.get (activityThread);
Palejandro
7
@Palejandro für die Unterstützung beider API-Ebenen (über 18 und unter) sollte Mapstattdessen die Schnittstelle HashMapoder verwendet werden ArrayMap. Ich habe die Antwort @AZ_ bearbeitet.
Yuriy Kolbasinskiy
2
Dies funktioniert nicht 100% der Zeit in API- Version 16 , wenn Sie den Code auf Github lesen, wurde die Funktion "currentActivityThread" in Kitkat geändert, daher möchte ich Version 19ish sagen , eine schwer zu vergleichende API-Version mit Releases in Github .
Lockwobr
@lockwobr danke, Lösung mit
Ihrem
2
Der Zugriff auf interne APIs über Reflection wird nicht unterstützt und funktioniert möglicherweise nicht auf allen Geräten oder in Zukunft.
Pei
9

Ich habe das Folgende in Kotlin gemacht

  1. Anwendungsklasse erstellen
  2. Bearbeiten Sie die Anwendungsklasse wie folgt

    class FTApplication: MultiDexApplication() {
    override fun attachBaseContext(base: Context?) {
        super.attachBaseContext(base)
        MultiDex.install(this)
    }
    
    init {
        instance = this
    }
    
    val mFTActivityLifecycleCallbacks = FTActivityLifecycleCallbacks()
    
    override fun onCreate() {
        super.onCreate()
    
        registerActivityLifecycleCallbacks(mFTActivityLifecycleCallbacks)
    }
    
    companion object {
        private var instance: FTApplication? = null
    
        fun currentActivity(): Activity? {
    
            return instance!!.mFTActivityLifecycleCallbacks.currentActivity
        }
    }
    
     }
  3. Erstellen Sie die ActivityLifecycleCallbacks-Klasse

    class FTActivityLifecycleCallbacks: Application.ActivityLifecycleCallbacks {
    
    var currentActivity: Activity? = null
    
    override fun onActivityPaused(activity: Activity?) {
        currentActivity = activity
    }
    
    override fun onActivityResumed(activity: Activity?) {
        currentActivity = activity
    }
    
    override fun onActivityStarted(activity: Activity?) {
        currentActivity = activity
    }
    
    override fun onActivityDestroyed(activity: Activity?) {
    }
    
    override fun onActivitySaveInstanceState(activity: Activity?, outState: Bundle?) {
    }
    
    override fun onActivityStopped(activity: Activity?) {
    }
    
    override fun onActivityCreated(activity: Activity?, savedInstanceState: Bundle?) {
        currentActivity = activity
    }
    
    }
  4. Sie können es jetzt in jeder Klasse verwenden, indem Sie Folgendes aufrufen: FTApplication.currentActivity()

Rashad.Z
quelle
5

getCurrentActivity () befindet sich auch in ReactContextBaseJavaModule.
(Da diese Frage ursprünglich gestellt wurde, haben viele Android-Apps auch eine ReactNative-Komponente - eine Hybrid-App.)

Die Klasse ReactContext in ReactNative verfügt über die gesamte Logik zur Aufrechterhaltung von mCurrentActivity, die in getCurrentActivity () zurückgegeben wird.

Hinweis: Ich wünschte, getCurrentActivity () wäre in der Android-Anwendungsklasse implementiert.

朱梅寧
quelle
In einigen Fällen ist dieser Kontext von ReactContextBaseJavaModule null. Wissen Sie warum?
Moxor
4

Ich konnte keine Lösung finden, mit der unser Team zufrieden wäre, also haben wir unsere eigene gerollt. Wir verwenden ActivityLifecycleCallbacks, um die aktuellen Aktivitäten zu verfolgen und sie dann über einen Dienst verfügbar zu machen. Weitere Details finden Sie hier: https://stackoverflow.com/a/38650587/10793

Muxa
quelle
2

Aus Gründen der Abwärtskompatibilität:

ComponentName cn;
ActivityManager am = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
    cn = am.getAppTasks().get(0).getTaskInfo().topActivity;
} else {
    //noinspection deprecation
    cn = am.getRunningTasks(1).get(0).topActivity;
}
Martin Zeitler
quelle
4
Dies beantwortet die Frage IMO nicht, es sei denn, es gibt eine Möglichkeit, von ComponentName zur aktuellen Instanz der Aktivität zu gelangen.
Nasch
@nasch man kann behalten und ein WeakReferenceHandle von einer ApplicationKlasse bekommen - während das ComponentNameerforderlich ist, um festzustellen, ob das Gewünschte ganz Activityoben auf der Liste der laufenden Aufgaben steht. Und wenn dies die Frage nicht vollständig beantwortet, wird die akzeptierte Antwort auch nicht vollständig beantwortet.
Martin Zeitler
Ich stimme zu, die akzeptierte Antwort beantwortet die Frage auch nicht vollständig.
Nasch
1
topActivityist nur von Android Q
Eugen Martynov
1

Persönlich habe ich getan, wie "Cheok Yan Cheng" sagte, aber ich habe eine "Liste" verwendet, um einen "Backstack" aller meiner Aktivitäten zu haben.

Wenn Sie überprüfen möchten, welche Aktivität aktuell ist, müssen Sie nur die letzte Aktivitätsklasse in der Liste abrufen.

Erstellen Sie eine Anwendung, die "Anwendung" erweitert, und führen Sie folgende Schritte aus:

public class MyApplication extends Application implements Application.ActivityLifecycleCallbacks,
EndSyncReceiver.IEndSyncCallback {

private List<Class> mActivitiesBackStack;
private EndSyncReceiver mReceiver;
    private Merlin mMerlin;
    private boolean isMerlinBound;
    private boolean isReceiverRegistered;

@Override
    public void onCreate() {
        super.onCreate();
        [....]
RealmHelper.initInstance();
        initMyMerlin();
        bindMerlin();
        initEndSyncReceiver();
        mActivitiesBackStack = new ArrayList<>();
    }

/* START Override ActivityLifecycleCallbacks Methods */
    @Override
    public void onActivityCreated(Activity activity, Bundle bundle) {
        mActivitiesBackStack.add(activity.getClass());
    }

    @Override
    public void onActivityStarted(Activity activity) {
        if(!isMerlinBound){
            bindMerlin();
        }
        if(!isReceiverRegistered){
            registerEndSyncReceiver();
        }
    }

    @Override
    public void onActivityResumed(Activity activity) {

    }

    @Override
    public void onActivityPaused(Activity activity) {

    }

    @Override
    public void onActivityStopped(Activity activity) {
        if(!AppUtils.isAppOnForeground(this)){
            if(isMerlinBound) {
                unbindMerlin();
            }
            if(isReceiverRegistered){
                unregisterReceiver(mReceiver);
            }
            if(RealmHelper.getInstance() != null){
                RealmHelper.getInstance().close();
                RealmHelper.getInstance().logRealmInstanceCount("AppInBackground");
                RealmHelper.setMyInstance(null);
            }
        }
    }

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

    }

    @Override
    public void onActivityDestroyed(Activity activity) {
        if(mActivitiesBackStack.contains(activity.getClass())){
            mActivitiesBackStack.remove(activity.getClass());
        }
    }
    /* END Override ActivityLifecycleCallbacks Methods */

/* START Override IEndSyncCallback Methods */
    @Override
    public void onEndSync(Intent intent) {
        Constants.SyncType syncType = null;
        if(intent.hasExtra(Constants.INTENT_DATA_SYNC_TYPE)){
            syncType = (Constants.SyncType) intent.getSerializableExtra(Constants.INTENT_DATA_SYNC_TYPE);
        }
        if(syncType != null){
            checkSyncType(syncType);
        }
    }
    /* END IEndSyncCallback Methods */

private void checkSyncType(Constants.SyncType){
    [...]
    if( mActivitiesBackStack.contains(ActivityClass.class) ){
         doOperation()     }
}

}

In meinem Fall habe ich "Application.ActivityLifecycleCallbacks" verwendet, um:

  • Merlin-Instanz binden / binden (wird verwendet, um ein Ereignis abzurufen, wenn die App die Verbindung verliert oder eine Verbindung herstellt, z. B. wenn Sie mobile Daten schließen oder wenn Sie sie öffnen). Dies ist nützlich, nachdem die Absichtsaktion "OnConnectivityChanged" deaktiviert wurde. Weitere Informationen zu MERLIN finden Sie unter: MERLIN INFO LINK

  • Schließen Sie meine letzte Realm-Instanz, wenn die Anwendung geschlossen wird. Ich werde es in einer BaseActivity initiieren, die von allen anderen Aktivitäten erweitert wird und über eine private RealmHelper-Instanz verfügt. Weitere Informationen zu REALM finden Sie unter: REALM INFO LINK Zum Beispiel habe ich eine statische "RealmHelper" -Instanz in meiner "RealmHelper" -Klasse, die in meiner Anwendung "onCreate" instanziiert wird. Ich habe einen Synchronisationsdienst, in dem ich einen neuen "RealmHelper" erstelle, da Realm "Thread-verknüpft" ist und eine Realm-Instanz nicht in einem anderen Thread funktionieren kann. Um der Realm-Dokumentation "Sie müssen alle geöffneten Realm-Instanzen schließen, um Systemressourcenlecks zu vermeiden" zu folgen, habe ich "Application.ActivityLifecycleCallbacks" verwendet, wie Sie sehen können.

  • Schließlich habe ich einen Empfänger, der ausgelöst wird, wenn ich die Synchronisierung meiner Anwendung abgeschlossen habe. Wenn die Synchronisierung beendet ist, wird die Methode "IEndSyncCallback" "onEndSync" aufgerufen, in der ich nachschaue, ob ich eine bestimmte Aktivitätsklasse in meiner ActivitiesBackStack-Liste habe, weil ich sie benötige um die Daten in der Ansicht zu aktualisieren, wenn die Synchronisierung sie aktualisiert hat und ich nach der App-Synchronisierung möglicherweise andere Vorgänge ausführen muss.

Das ist alles, hoffe das ist hilfreich. Bis später :)

Z3R0
quelle
-1

Die Antwort von waqas716 ist gut. Ich habe eine Problemumgehung für einen bestimmten Fall erstellt, die weniger Code und Wartung erfordert.

Ich habe eine bestimmte Problemumgehung gefunden, indem eine statische Methode eine Ansicht von der Aktivität abgerufen hat, von der ich vermute, dass sie im Vordergrund steht. Sie können alle Aktivitäten durchlaufen und prüfen, ob Sie möchten oder den Aktivitätsnamen aus Martins Antwort erhalten

ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
ComponentName cn = am.getRunningTasks(1).get(0).topActivity; 

Ich überprüfe dann, ob die Ansicht nicht null ist und erhalte den Kontext über getContext ().

View v = SuspectedActivity.get_view();

if(v != null)
{
    // an example for using this context for something not 
    // permissible in global application context. 
    v.getContext().startActivity(new Intent("rubberduck.com.activities.SomeOtherActivity"));
}
Badeente
quelle
Ich suche hier nach einem ähnlichen Problem stackoverflow.com/questions/22788289/… Wie erhalten wir "SuspectedActivity"? Ist das native API?
Stella
2
ABER aus den Dokumenten für getRunningTasks: "Note: this method is only intended for debugging and presenting task management user interfaces. This should never be used for core logic in an application, ..." in developer.android.com/reference/android/app/…
ToolmakerSteve
3
In der Dokumentation zu ActivityManager.getRunningTasks () heißt es jetzt "Diese Methode wurde in API-Level 21 nicht mehr unterstützt".
Markshep
-2

Ich mag keine der anderen Antworten. Der ActivityManager ist nicht dazu gedacht, die aktuelle Aktivität abzurufen. Super Classing und je nach onDestroy ist auch fragil und nicht das beste Design.

Ehrlich gesagt ist das Beste, was ich bisher gefunden habe, nur eine Aufzählung in meiner Anwendung beizubehalten, die festgelegt wird, wenn eine Aktivität erstellt wird.

Eine andere Empfehlung könnte sein, wenn möglich nur die Verwendung mehrerer Aktivitäten zu scheuen. Dies kann entweder mit Fragmenten oder in meinen bevorzugten benutzerdefinierten Ansichten erfolgen.

Stevebot
quelle
1
eine Aufzählung? Wie hilft das beim Auffinden der aktuellen Vordergrundaktivitätsinstanz?
ToolmakerSteve
"Super Classing und abhängig von onDestroy ist auch fragil" Wie ist das fragil?
ToolmakerSteve
-3

Eine ziemlich einfache Lösung besteht darin, eine Singleton-Manager-Klasse zu erstellen, in der Sie einen Verweis auf eine oder mehrere Aktivitäten oder auf alles andere speichern können, auf das Sie in der gesamten App zugreifen möchten.

Anruf UberManager.getInstance().setMainActivity( activity ); onCreate der Hauptaktivität auf.

Anruf UberManager.getInstance().getMainActivity(); irgendwo in Ihrer App an, um sie abzurufen. (Ich verwende dies, um Toast von einem Nicht-UI-Thread verwenden zu können.)

Stellen Sie sicher, dass Sie einen Anruf hinzufügen, UberManager.getInstance().cleanup();wenn Ihre App zerstört wird.

import android.app.Activity;

public class UberManager
{
    private static UberManager instance = new UberManager();

    private Activity mainActivity = null;

    private UberManager()
    {

    }

    public static UberManager getInstance()
    {
        return instance;
    }

    public void setMainActivity( Activity mainActivity )
    {
        this.mainActivity = mainActivity;
    }

    public Activity getMainActivity()
    {
        return mainActivity;
    }

    public void cleanup()
    {
        mainActivity = null;
    }
}
MukRaker
quelle
Dies ist aufdringlich und erfordert Änderungen bei allen Aktivitäten. Die Antwort von AZ_ ist viel besser, da es vollständig lokalisiert und eigenständig ist, ohne dass andere Änderungen in der Codebasis erforderlich sind.
Markshep
-7

Ich bin ungefähr 3 Jahre zu spät, aber ich werde es trotzdem beantworten, falls jemand dies so findet wie ich.

Ich habe das gelöst, indem ich einfach folgendes benutzt habe:

    if (getIntent().toString().contains("MainActivity")) {
        // Do stuff if the current activity is MainActivity
    }

Beachten Sie, dass "getIntent (). ToString ()" eine Reihe anderer Texte enthält, z. B. Ihren Paketnamen und alle Absichtsfilter für Ihre Aktivität. Technisch überprüfen wir die aktuelle Absicht, nicht die Aktivität, aber das Ergebnis ist das gleiche. Verwenden Sie einfach zB Log.d ("test", getIntent (). ToString ()); wenn Sie den gesamten Text sehen möchten. Diese Lösung ist etwas hackig, aber in Ihrem Code ist sie viel sauberer und die Funktionalität ist dieselbe.

Simon Hyll
quelle