Comment obtenir le contexte actuel de l'activité au premier plan dans Android?

171

Chaque fois que ma diffusion est exécutée, je souhaite afficher une alerte sur l'activité au premier plan.

Deepali
la source
d'où vous souhaitez obtenir le contexte de l'activité. Est-ce que ce sera l'activité de votre application ou une autre application.
AAnkit
ceci est une activité d'application. J'ai fait le codage des dialogues d'alerte sur la fonction Broadcastreceiver onreceive ().
Deepali
une activité d'application! est-ce votre application ?? et pourquoi voulez-vous cela, pour une raison quelconque, peut-il y avoir une alternative pour la même chose
AAnkit
Je souhaite afficher une alerte sur mon activité au premier plan.
Deepali
1
dans onreceive only u get COntext comme paramètre, vous pouvez dire context.getApplicationContext ()
AAnkit

Réponses:

39

Sachant qu'ActivityManager gère Activity , nous pouvons donc obtenir des informations d' ActivityManager . Nous obtenons l'activité courante de premier plan en cours d'exécution par

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

MISE À JOUR 2018/10/03
getRunningTasks () est obsolète. voir les solutions ci-dessous.

Cette méthode était obsolète au niveau de l'API 21. Depuis Build.VERSION_CODES.LOLLIPOP, cette méthode n'est plus disponible pour les applications tierces: l'introduction de recents centrés sur le document signifie qu'elle peut divulguer des informations sur la personne à l'appelant. Pour des raisons de compatibilité ascendante, il renverra toujours un petit sous-ensemble de ses données: au moins les propres tâches de l'appelant, et éventuellement d'autres tâches telles que la maison qui sont connues pour ne pas être sensibles.

KAlO2
la source
16
Je ne pense pas Martin, de l'aide du SDK de getRunningTasks "Remarque: cette méthode est uniquement destinée au débogage et à la présentation des interfaces utilisateur de gestion des tâches. Cela ne doit jamais être utilisé pour la logique de base d'une application"
ruhalde
3
Apparemment, cela ne prend en charge qu'un sous-ensemble limité de tâches en cours d'exécution dans Android 5 / Lollipop.
Sam
7
La documentation d' ActivityManager.getRunningTasks () indique "Cette méthode est obsolète au niveau d'API 21".
markshep
210

( Remarque: une API officielle a été ajoutée dans l'API 14: voir cette réponse https://stackoverflow.com/a/29786451/119733 )

N'UTILISEZ PAS LA RÉPONSE PRÉCÉDENTE (waqas716).

Vous aurez un problème de fuite de mémoire, en raison de la référence statique à l'activité. Pour plus de détails, voir le lien suivant http://android-developers.blogspot.fr/2009/01/avoiding-memory-leaks.html

Pour éviter cela, vous devez gérer les références d'activités. Ajoutez le nom de l'application dans le fichier manifeste:

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

Votre classe d'application:

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

Créez une nouvelle activité:

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

Donc, maintenant, au lieu d'étendre la classe Activity pour vos activités, étendez simplement MyBaseActivity. Maintenant, vous pouvez obtenir votre activité actuelle à partir d'un contexte d'application ou d'activité comme celui-ci:

Activity currentActivity = ((MyApp)context.getApplicationContext()).getCurrentActivity();
gezdy
la source
9
Vous pouvez simplement utiliser WeakReference et obtenir le même résultat avec moins de code.
Nacho Coloma
5
@Nacho Je ne recommanderais jamais d'utiliser WeakReferencesdans Android le GC les recueille plus rapidement que vous ne le pensez.
rekire le
4
@MaximKorobov Oui, c'est possible si vous appelez finish () depuis onCreate (), si vous utilisez votre activité juste pour lancer une autre activité et arrêter celle-ci. Dans ce scénario, il saute onPause () et onStoo (). Voir la note du bas de: developer.android.com/training/basics/activity-lifecycle/…
Rodrigo Leitão
2
@rekire @NachoColoma L'utilisation de WeakReferencen'est pas conseillée pour la mise en cache, ce n'est pas de la mise en cache, c'est-à-dire mCurrentActivityqu'elle n'aura une référence que lorsqu'elle est vivante, donc le WeakReferencene sera jamais collecté tant que le Activityest en haut. Cependant, ce que @NachoColoma suggère est faux car il WeakReferencepeut toujours faire référence à une activité non reprise (pas en vie / pas en haut) si la variable n'est pas effacée!
TWiStErRob
14
À partir du niveau 14 de l'API Android, il devrait être possible d'utiliser Application .ActivityLifecycleCallbacks, ce qui serait plus central et vous n'auriez pas à ajouter de code de gestion dans toutes vos activités. Voir aussi developer.android.com/reference/android/app/…
Filou
68

Je développe en haut de la réponse de @ gezdy.

Dans toutes les activités, au lieu d'avoir à "s'enregistrer" Applicationavec un codage manuel, nous pouvons utiliser l'API suivante depuis le niveau 14, pour nous aider à atteindre un objectif similaire avec moins de codage manuel.

public void registerActivityLifecycleCallbacks (Application.ActivityLifecycleCallbacks callback)

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

Dans Application.ActivityLifecycleCallbacks, vous pouvez obtenir ce qui Activityest "attaché" ou "détaché" à celui-ci Application.

Cependant, cette technique n'est disponible qu'à partir du niveau d'API 14.

Cheok Yan Cheng
la source
1
Que se passe-t-il avec toutes les autres réponses? Il s'agit clairement d'une API conçue à cet effet. Merci, Cheok Yan Cheng
Michael Bushe
2
@MichaelBushe - en 2012, lorsque les autres réponses ont été écrites, selon le niveau d'API 14, il n'était pas nécessaire de s'appuyer sur tous les appareils, étant donné que l'API n'avait été publiée que récemment (octobre 2011).
ToolmakerSteve
4
J'ai trouvé une réponse montrant comment utiliser cette approche: stackoverflow.com/a/11082332/199364 L'avantage est que rien ne doit être fait pour les activités elles-mêmes ; le code est entièrement dans votre classe de rappel personnalisée. Vous créez simplement une classe implements Application.ActivityLifecycleCallbackset ajoutez les méthodes pour l'implémenter. Ensuite, dans le constructeur de cette classe (ou onCreate ou init ou une autre méthode qui s'exécute lorsque l'instance devient active / prête), mettez getApplication().registerActivityLifecycleCallbacks(this);en dernière ligne.
ToolmakerSteve
Je pense que votre réponse est la meilleure
burulangtu
2
très bonne réponse. le seul inconvénient est que vous devez toujours enregistrer l'activité à un endroit si vous devez interroger votre classe pour l'activité en cours. vous devez donc toujours éviter les fuites de mémoire et annuler la référence.
Raphael C
56

Mise à jour 2 : Une API officielle a été ajoutée pour cela, veuillez utiliser ActivityLifecycleCallbacks à la place.

METTRE À JOUR:

Comme l'a souligné @gezdy, et j'en suis reconnaissant. définissez la référence sur null également pour l'activité actuelle, au lieu de mettre à jour uniquement sur chaque onResume, définissez-la sur null sur le onDestroy de chaque activité pour éviter les problèmes de fuite de mémoire.

Il y a quelque temps, j'avais besoin de la même fonctionnalité et voici la méthode pour y parvenir. Dans chacune de vos activités, remplacez ces méthodes de cycle de vie.

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

Maintenant, dans votre classe de diffusion, vous pouvez accéder à l'activité actuelle pour afficher une alerte à ce sujet.

Waqas
la source
3
Cette réponse devrait vraiment obtenir plus de votes positifs, une solution simple, mais puissante lorsque vous avez des classes qui ont besoin de manipuler des activités, mais ne sont pas des activités elles-mêmes.
ryvianstyron
Il s'agit simplement d'une référence statique de votre objet d'activité. Vous pouvez le créer où vous voulez :). Cela n'a pas d'importance.
Waqas
C'est d'ailleurs l'équivalent de votre réponse précédente. Applicationest créé une seule fois et jamais garbage collecté exactement comme une variable statique.
zapl
1
Il y aura des problèmes avec les activités hiérarchiques. Lorsque vous revenez d'une activité enfant à l'activité parentale: (1) est appelée onPause enfant; (2) onResume du parent; (3) child onDestroy ==> l'activité actuelle sera nulle. Vous devriez faire des vérifications comme @gezdy dans son exemple dans la méthode clearReferences.
Arts
4
@ waqas716 Je vous suggère de simplifier la condition clearReferences()de (this.equals(currActivity)).
naXa
51

@lockwobr Merci pour la mise à jour

Cela ne fonctionne pas 100% du temps dans la version 16 de l'API, si vous lisez le code sur github, la fonction "currentActivityThread" a été modifiée dans Kitkat, donc je veux dire la version 19ish, un peu difficile à faire correspondre la version de l'API aux versions de github .

Avoir accès au courant Activityest très pratique. Ne serait-il pas bien d'avoir une getActivityméthode statique renvoyant l'activité actuelle sans questions inutiles?

Le Activitycours est très utile. Il donne accès au thread d'interface utilisateur de l'application, aux vues, aux ressources et bien d'autres. De nombreuses méthodes nécessitent un Context, mais comment obtenir le pointeur? Voici quelques moyens:

  • Suivi de l'état de l'application à l'aide de méthodes de cycle de vie remplacées. Vous devez stocker l'activité en cours dans une variable statique et vous devez accéder au code de toutes les activités.
  • Suivi de l'état de l'application à l'aide de l'instrumentation. Déclarez l'instrumentation dans le manifeste, implémentez-la et utilisez ses méthodes pour suivre les changements d'activité. Passer un pointeur d'activité aux méthodes et classes utilisées dans vos activités. Injection du pointeur à l'aide de l'une des bibliothèques d'injection de code. Toutes ces approches sont plutôt peu pratiques ; Heureusement, il existe un moyen beaucoup plus simple d'obtenir l'activité actuelle.
  • Il semble que le système ait besoin d'accéder à toutes les activités sans les problèmes mentionnés ci-dessus. Il existe donc très probablement un moyen d'obtenir des activités en utilisant uniquement des appels statiques. J'ai passé beaucoup de temps à fouiller dans les sources Android sur grepcode.com, et j'ai trouvé ce que je cherchais. Il y a une classe appelée ActivityThread. Cette classe a accès à toutes les activités et, ce qui est encore mieux, dispose d'une méthode statique pour obtenir le courant ActivityThread. Il n'y a qu'un seul petit problème: la liste des activités a accès aux packages.

Facile à résoudre par réflexion:

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

Une telle méthode peut être utilisée n'importe où dans l'application et elle est beaucoup plus pratique que toutes les approches mentionnées. De plus, il semble que ce ne soit pas aussi dangereux qu'il en a l'air. Il n'introduit aucune nouvelle fuite potentielle ou pointeur nul.

L'extrait de code ci-dessus ne gère pas les exceptions et suppose naïvement que la première activité en cours d'exécution est celle que nous recherchons. Vous voudrez peut-être ajouter des vérifications supplémentaires.

Article de blog

AZ_
la source
2
dans Kitkat et au-dessus, mActivities n'est pas HashMap, mais ArrayMap, vous devez donc changer cette ligne: HashMap activities = (HashMap) activitiesField.get (activityThread); pour ressembler à ceci: ArrayMap activities = (ArrayMap) activitiesField.get (activityThread);
Palejandro
7
@Palejandro pour prendre en charge les deux niveaux d'API (au-dessus de 18 et en dessous), il devrait utiliser l' Mapinterface à la place HashMapou ArrayMap. J'ai édité la réponse @AZ_.
Yuriy Kolbasinskiy
2
Cela ne fonctionne pas 100% du temps dans la version 16 de l' API , si vous lisez le code sur github, la fonction "currentActivityThread" a été modifiée dans Kitkat, donc je veux dire la version 19ish , un peu difficile à faire correspondre la version de l'API aux versions de github .
lockwobr
@lockwobr merci, solution mise à jour avec votre commentaire
:)
2
L'accès aux API internes via la réflexion n'est pas pris en charge et peut ne pas fonctionner sur tous les appareils ou à l'avenir.
Pei
9

J'ai fait ce qui suit à Kotlin

  1. Créer une classe d'application
  2. Modifiez la classe d'application comme suit

    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. Créer la classe ActivityLifecycleCallbacks

    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. vous pouvez maintenant l'utiliser dans n'importe quelle classe en appelant ce qui suit: FTApplication.currentActivity()

Rashad.Z
la source
5

getCurrentActivity () est également dans ReactContextBaseJavaModule.
(Depuis que cette question a été initialement posée, de nombreuses applications Android ont également un composant ReactNative - application hybride.)

La classe ReactContext dans ReactNative a l'ensemble de la logique pour maintenir mCurrentActivity qui est retournée dans getCurrentActivity ().

Remarque: je souhaite que getCurrentActivity () soit implémenté dans la classe Application Android.

朱梅寧
la source
dans certains cas, ce contexte de ReactContextBaseJavaModule est nul, savez-vous pourquoi?
Moxor
4

Je n'ai pas trouvé de solution qui plairait à notre équipe, alors nous avons lancé la nôtre. Nous utilisons ActivityLifecycleCallbackspour garder une trace de l'activité actuelle, puis l'exposer via un service. Plus de détails ici: https://stackoverflow.com/a/38650587/10793

Muxa
la source
2

Pour une compatibilité descendante:

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
la source
4
Sauf s'il existe un moyen de passer de ComponentName à l'instance actuelle de l'activité, cela ne répond pas à la question IMO.
nasch
@nasch on peut garder et obtenir un WeakReferencehandle d'une Applicationclasse - alors que le ComponentNameest nécessaire pour déterminer si le désiré Activityest en haut de la liste des tâches en cours. Et si cela ne répond pas complètement à la question, la réponse acceptée non plus.
Martin Zeitler le
Je suis d'accord, la réponse acceptée ne répond pas non plus complètement à la question.
nasch
1
topActivityest disponible uniquement à partir d'Android Q
Eugen Martynov
1

Personnellement, j'ai fait ce que "Cheok Yan Cheng" a dit, mais j'ai utilisé une "Liste" pour avoir un "Backstack" de toutes mes activités.

Si vous voulez vérifier quelle est l'activité actuelle, il vous suffit d'obtenir la dernière classe d'activité de la liste.

Créez une application qui étend "Application" et procédez comme suit:

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

}

Dans mon cas, j'ai utilisé "Application.ActivityLifecycleCallbacks" pour:

  • Bind / Unbind Merlin Instance (utilisé pour obtenir un événement lorsque l'application perd ou obtient une connexion, par exemple lorsque vous fermez des données mobiles ou lorsque vous l'ouvrez). Il est utile après la désactivation de l'action d'intention «OnConnectivityChanged». Pour plus d'informations sur MERLIN, voir: MERLIN INFO LINK

  • Fermez ma dernière instance de royaume lorsque l'application est fermée; Je vais l'initier dans une BaseActivity qui est étendue de toutes les autres activités et qui a une instance RealmHelper privée. Pour plus d'informations sur REALM voir: REALM INFO LINK Par exemple, j'ai une instance statique "RealmHelper" dans ma classe "RealmHelper" qui est instanciée dans mon application "onCreate". J'ai un service de synchronisation dans lequel je crée un nouveau "RealmHelper" parce que Realm est "Thread-Linked" et qu'une instance de Realm ne peut pas fonctionner dans un Thread différent. Donc, afin de suivre la documentation de Realm "Vous devez fermer toutes les instances de Realm ouvertes pour éviter les fuites de ressources système", pour accomplir cela, j'ai utilisé les "Application.ActivityLifecycleCallbacks" comme vous pouvez le voir.

  • Enfin, j'ai un récepteur qui se déclenche lorsque je termine la synchronisation de mon application, puis lorsque la synchronisation se termine, il appelle la méthode "IEndSyncCallback" "onEndSync" dans laquelle je regarde si j'ai une classe d'activité spécifique dans ma liste ActivitiesBackStack car j'ai besoin pour mettre à jour les données de la vue si la synchronisation les a mises à jour et que je pourrais avoir besoin d'effectuer d'autres opérations après la synchronisation de l'application.

C'est tout, j'espère que cela vous sera utile. A plus :)

Z3R0
la source
-1

La réponse de waqas716 est bonne. J'ai créé une solution de contournement pour un cas spécifique nécessitant moins de code et de maintenance.

J'ai trouvé un travail spécifique en demandant à une méthode statique de récupérer une vue de l'activité que je soupçonne d'être au premier plan. Vous pouvez parcourir toutes les activités et vérifier si vous le souhaitez ou obtenir le nom de l'activité à partir de la réponse de Martin

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

Je vérifie ensuite si la vue n'est pas nulle et récupère le contexte via 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"));
}
Canard en caoutchouc
la source
Je recherche un problème similaire ici stackoverflow.com/questions/22788289/… comment obtenons-nous "SuspectedActivity"? S'agit-il d'une API native?
Stella
2
MAIS de la documentation pour 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, ..." dans developer.android.com/reference/android/app/…
ToolmakerSteve
3
La documentation d' ActivityManager.getRunningTasks () indique désormais "Cette méthode était obsolète au niveau d'API 21".
markshep
-2

Je n'aime aucune des autres réponses. Le ActivityManager n'est pas destiné à être utilisé pour obtenir l'activité en cours. Super classer et dépendre de Détruire est également fragile et pas le meilleur design.

Honnêtement, le mieux que j'ai trouvé jusqu'à présent est simplement de maintenir une énumération dans mon application, qui est définie lorsqu'une activité est créée.

Une autre recommandation pourrait être d'éviter d'utiliser plusieurs activités si possible. Cela peut être fait soit avec l'utilisation de fragments, soit dans mes préférences personnalisées.

Stevebot
la source
1
une énumération? Comment cela aide-t-il à localiser l'instance d'activité de premier plan actuelle?
ToolmakerSteve
"Super classer et dépendre de onDestroy est également fragile" Comment est-ce fragile?
ToolmakerSteve
-3

Une solution plutôt simple consiste à créer une classe de gestionnaire singleton, dans laquelle vous pouvez stocker une référence à une ou plusieurs activités, ou à tout autre élément auquel vous souhaitez accéder dans toute l'application.

Appelez UberManager.getInstance().setMainActivity( activity );onCreate de l'activité principale.

Appelez UberManager.getInstance().getMainActivity();n'importe où dans votre application pour la récupérer. (J'utilise ceci pour pouvoir utiliser Toast à partir d'un thread non UI.)

Assurez-vous d'ajouter un appel UberManager.getInstance().cleanup();lorsque votre application est en cours de destruction.

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
la source
Ceci est intrusif et nécessite des changements dans toutes les activités. La réponse d'AZ_ est bien meilleure car elle est totalement localisée et autonome sans nécessiter d'autres changements dans la base de code.
markshep
-7

J'ai environ 3 ans de retard mais j'y répondrai quand même au cas où quelqu'un trouverait ça comme moi.

J'ai résolu cela en utilisant simplement ceci:

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

Notez que "getIntent (). ToString ()" inclut un tas d'autres textes tels que le nom de votre package et les filtres d'intention pour votre activité. Techniquement, nous vérifions l'intention actuelle, pas l'activité, mais le résultat est le même. Utilisez simplement par exemple Log.d ("test", getIntent (). ToString ()); si vous voulez voir tout le texte. Cette solution est un peu piratée mais elle est beaucoup plus propre dans votre code et la fonctionnalité est la même.

Simon Hyll
la source