212

Whenever my broadcast is executed I want to show alert to foreground activity.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Deepali
  • 2,227
  • 2
  • 15
  • 8
  • from where you want to get context of Activity. Is this will be ur app activity or other application. – AAnkit Jul 10 '12 at 10:34
  • this is an app activity. I have done alert dialog coding on broadcastreceiver onreceive() function. – Deepali Jul 10 '12 at 10:37
  • an app activity! is this your app?? and why do you want this, any reason, may there are alternative for the same – AAnkit Jul 10 '12 at 10:40
  • I want to show alert on my foreground activity.Is their any other way to show alert to foreground activity without context. – Deepali Jul 10 '12 at 10:53
  • 1
    in onreceive only u get COntext as a param, you can say context.getApplicationContext() – AAnkit Jul 10 '12 at 10:55
  • No you will need to have reference of context to show alert on it. See my answer carefully and you have your solution right there ;) – Waqas Jul 10 '12 at 10:56
  • possible duplicate of [Android: How can I get the current foreground activity (from a service)?](http://stackoverflow.com/questions/3873659/android-how-can-i-get-the-current-foreground-activity-from-a-service) – Heath Borders Dec 03 '13 at 19:56
  • @AAnkit: No, to show any UI, in this case an alert dialog, need a context that is an activity; `getApplicationContext` won't return an activity, so won't work for this use. – ToolmakerSteve Oct 07 '15 at 22:49
  • All the answers seem to build on each other over time. Can someone write a clear solution for today in 2016? – Nathan H Feb 14 '16 at 09:12

18 Answers18

233

(Note: An official API was added in API 14: See this answer https://stackoverflow.com/a/29786451/119733)

DO NOT USE PREVIOUS (waqas716) answer.

You will have memory leak problem, because of the static reference to the activity. For more detail see the following link http://android-developers.blogspot.fr/2009/01/avoiding-memory-leaks.html

To avoid this, you should manage activities references. Add the name of the application in the manifest file:

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

Your application class :

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

Create a new Activity :

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

So, now instead of extending Activity class for your activities, just extend MyBaseActivity. Now, you can get your current activity from application or Activity context like that :

Activity currentActivity = ((MyApp)context.getApplicationContext()).getCurrentActivity();
Community
  • 1
  • 1
gezdy
  • 3,292
  • 2
  • 14
  • 14
  • 15
    You could just use WeakReference and achieve the same result with less code. – Nacho Coloma May 26 '13 at 15:55
  • 5
    @Nacho I would never recomment to use `WeakReferences` in Android the GC collectes them faster then you think. – rekire Jun 25 '13 at 10:46
  • Why do you duplicate `onResume/onPause` logic to `onCreate/onRestore`? In other words, is it possible `destroy` without `stop`? – Maxim Korobov Aug 01 '13 at 13:04
  • What if my activity extends ListActivity then in that case I can't extend BaseActivity? – Anuj Mehta Aug 23 '13 at 08:26
  • 4
    @MaximKorobov Yes it is possible if you call finish() from onCreate(), if you use your activity just to launch another activity and stops this one. In this scenario it skips onPause() and onStoo(). See the bottom note of: http://developer.android.com/training/basics/activity-lifecycle/starting.html – Rodrigo Leitão Oct 30 '13 at 16:45
  • 3
    @rekire @NachoColoma Use of `WeakReference` is not advised for caching, this is not caching, that is the `mCurrentActivity` will only have a reference to it when it's alive so the `WeakReference` will never be collected while the `Activity` is on top. However what @NachoColoma suggest is wrong because the `WeakReference` may still reference a non-resumed (not alive/not on top) activity if the variable is not cleared! – TWiStErRob Aug 13 '14 at 13:52
  • @RodrigoLeitão @MaxinKorobov in case of `finish()` in `onCreate`: `onResume` won't be called so essentially we don't need to clear in `onDestroy`. – TWiStErRob Aug 13 '14 at 13:59
  • 14
    Starting from Android API level 14 it should be possible to use `Application .ActivityLifecycleCallbacks`, which would be more central and you wouldn't have to add any management code in all your activities. Also see http://developer.android.com/reference/android/app/Application.html#registerActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks) – Filou Apr 14 '15 at 12:45
  • 1
    Why is `mMyApp.setCurrentActivity(this);` not called in `onCreate()` in addition to `onResume()`? `onResume()` gets called pretty late and sometimes it's necessary to have it initialized earlier. – Daniel F May 01 '15 at 21:30
  • 1
    but you still use the same concept of static reference to activity ! – Menna-Allah Sami Jun 14 '15 at 13:52
  • @RodrigoLeitão in that case, when finish() is called in onCreate(), no other lifecycle method than onDestroy is being called. It's not necessary to clear references in onDestroy() if they weren't set in onCreate(). – jeff Jun 22 '15 at 12:37
  • @Filou `Application .ActivityLifecycleCallbacks` is not suitable for this purpose. It first executes callbacks for creating a new activity and after that it executes callbacks for destroying the previous activity. So your `mCurrentActivity` becomes null even though it's not null just because the callbacks for destroying activity were executed later. At least this is true for API 21. – serg66 Jul 17 '15 at 06:08
  • 1
    @Filou actually it can be suitable, my bad) You can store a class of the current activity and compare it to the activity class in the destroy methods. If they don't match, then don't make the current activity null. – serg66 Jul 17 '15 at 06:28
  • 2
    Down voted for using a horrible global variable that had to be manually updated literally everywhere in your app. *Never* write code like this! – grahamparks Sep 09 '15 at 14:26
  • Despite the claim that this is better than waqas answer "because this doesn't use a static", the claim is false. Class Application is a singleton; its lifetime is the lifetime of your app. Setting a field of Application has the same lifetime as setting a static on some shorter-lived class. In either case, the real issue is that it outlives the Activity; and the solution (which is now included in waqas' answer) is to null the reference when appropriate. – ToolmakerSteve Oct 07 '15 at 23:18
  • **This answer would be improved** if `clearReferences` was a public method of `MyApp`, that takes parameter `Activity dyingActivity`. Change `this` in its body to `dyingActivity`, and call it from each activity with `((MyApp) getApplication()).clearReferences(this);`. NOTE: This doesn't matter if you subclass all your activities from this class (I missed that suggestion at first). **Its also unnecessary** to have `protected MyApp mMyApp;` in each Activity. App is a singleton, "getApplication()" can always retrieve it. – ToolmakerSteve Oct 07 '15 at 23:40
  • @grahamparks: Perhaps you missed a key line: ***now instead of extending Activity class for your activities, just extend MyBaseActivity***. Doing so means all the setting of that global variable is centralized in one place. This still may be an obsolete approach given newer APIs, but it doesn't seem as horrible to me as you describe it. – ToolmakerSteve Oct 07 '15 at 23:42
  • The one way in which this answer is superior to waqas` answer, is the suggestion to create MyBaseActivity, and then subclass your activitys from that. This avoids having to repeat the code in every activity. – ToolmakerSteve Oct 08 '15 at 00:39
  • To address people's concern about the lifetime of the global, change `Activity mCurrentActivity` to `WeakReference mCurrentActivity`. To access the activity from the WeakReference: `mCurrentActivity.get()`. – ToolmakerSteve Oct 08 '15 at 00:42
  • @rekire: your concern about using WeakReference cannot be valid. As long as the Activity is active, the app *must* hold a strong reference to it somewhere internally. If it did not, then it could not guarantee that GC would not destroy the Activity. – ToolmakerSteve Oct 08 '15 at 00:50
  • Great answer. Got so much of clarity. Just need to know I have the same where I extend my BaseActivity by another ChildActivity in which I need to keep track of something if I start something else from ChildActivity. So, I am doing same steps except onPause clearing reference in onDestroy only. Is it right way? – VVB Dec 14 '16 at 07:01
  • I can't use this method because I don't have the source code to the main activity in the app I'm using. The [answer from AZ_](http://stackoverflow.com/a/28423385/641332) works without needing to alter the main activity code at all, so is much better and works for me. – markshep Dec 15 '16 at 15:32
79

I expand on the top of @gezdy's answer.

In every Activities, instead of having to "register" itself with Application with manual coding, we can make use of the following API since level 14, to help us achieve similar purpose with less manual coding.

public void registerActivityLifecycleCallbacks (Application.ActivityLifecycleCallbacks callback)

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

In Application.ActivityLifecycleCallbacks, you can get which Activity is "attached" to or "detached" to this Application.

However, this technique is only available since API level 14.

Cheok Yan Cheng
  • 47,586
  • 132
  • 466
  • 875
  • 1
    What's up with all the other answers? Clearly this is designed API for this purpose. Thank you, Cheok Yan Cheng – Michael Bushe Jul 13 '15 at 22:46
  • 2
    @MichaelBushe - in 2012, when the other answers were written, depending on API level 14 was not something to rely on in every device, given that the API had only been recently released (Oct 2011). – ToolmakerSteve Oct 07 '15 at 23:58
  • 4
    Found an answer showing how to use this approach: http://stackoverflow.com/a/11082332/199364 The benefit is that **nothing need be done to the activities themselves**; the code is all in your custom callback class. You simply make a class that `implements Application.ActivityLifecycleCallbacks`, and add the methods to implement that. Then in that class' constructor (or onCreate or init or other method that runs when instance is becoming active/ready), put `getApplication().registerActivityLifecycleCallbacks(this);` as the last line. – ToolmakerSteve Oct 08 '15 at 01:40
  • I think your answer is best – burulangtu Sep 30 '16 at 07:27
  • 3
    great answer. the only downside is you still need to save the activity some place if you need to query your class for the current activity. so you still need to avoid memory leak and null the reference. – Raphael C Oct 06 '16 at 11:09
  • This is solid. Simple solution. – Nestor Ledon Oct 03 '18 at 17:24
71

Update 3: There is an official api added for this, please use ActivityLifecycleCallbacks instead.

Waqas
  • 4,411
  • 6
  • 27
  • 31
  • 3
    This answer should really get more up-votes, simple solution, but powerful when you have classes that need to manipulate activities, but aren't activities themselves. – shecodesthings Oct 02 '12 at 13:38
  • It's about just a static reference of your activity object. You can create it wherever you want :). It doesn't matter. – Waqas Nov 24 '12 at 11:23
  • This is btw equivalent to your previous answer. `Application` is only created once and never garbage collected exactly like a static variable. – zapl Aug 08 '13 at 01:14
  • right the clear reference part is missing, I was in hurry. Will update my answer again. Thanks for pointing out :). – Waqas Aug 08 '13 at 05:32
  • 1
    There'll be problems with hierarchic activities. When you return from a child activity to the parent one: (1) is called child's onPause; (2) parent's onResume; (3) child's onDestroy ==> the current activity will be null. You should do some check like @gezdy in his example in the method clearReferences. – Arts Feb 26 '14 at 21:56
  • 4
    @waqas716 I'd suggest to simplify the condition in `clearReferences()` to `(this.equals(currActivity))`. – naXa stands with Ukraine Jun 22 '14 at 03:32
  • This requires altering the source code for the activity and my case I don't have that. I ended up using [the answer by AZ_](http://stackoverflow.com/a/28423385/641332) as that can be implemented anywhere. – markshep Dec 15 '16 at 15:36
  • I have been using this approach and have found several scenarios where this doesn't work because the wrong activity is set as the current activity, including `onResume` being called for an activity that isn't actually visible for some reason. Since all of my activities inherit from a BaseActivity I created, I overrode the onWindowFocusChange in the base activity and notified the class that keeps track of the current activity and that seems to be much more reliable. I still use the lifecycle callbacks to null the current activity when the onDestroy is called. – odiggity Sep 24 '20 at 04:27
  • @odiggity you shouldn't need to use this approach. You should just use the following https://developer.android.com/reference/android/app/Application.ActivityLifecycleCallbacks.html Or this tutorial https://medium.com/@pahlevikun/automatically-listening-to-all-of-your-activity-lifecycle-event-with-activitylifecyclecallbacks-261b8ecadd50 – Waqas Sep 25 '20 at 17:11
  • @Waqas I don't think you read my comment. It explicitly states that I'm fully aware of lifecycle callbacks that you linked and have been using them for a long time. The problem with using them that I have discovered, is that the order of activity onResumes is not guaranteed and I have noticed scenarios where onResume of an activity in the back stack is called after onResume of the currently visible Activity, meaning I ended up with the wrong current activity being set. One scenario in particular this happens is when returning from FB login. That's why I suggested using onWindowFocusChanged – odiggity Sep 25 '20 at 22:15
  • @odiggity yeah sorry, IMO you shouldn't need to have the requirement to getting exactly the current activity in scenarios where you aren't in that code flow. But I think this requires more context knowledge what you need to do etc. But if that approach is working for you, nice! – Waqas Sep 26 '20 at 11:12
46

Knowing that ActivityManager manages Activity, so we can gain information from ActivityManager. We get the current foreground running Activity by

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

UPDATE 2018/10/03
getRunningTasks() is DEPRECATED. see the solutions below.

This method was deprecated in API level 21. As of Build.VERSION_CODES.LOLLIPOP, this method is no longer available to third party applications: the introduction of document-centric recents means it can leak person information to the caller. For backwards compatibility, it will still return a small subset of its data: at least the caller's own tasks, and possibly some other tasks such as home that are known to not be sensitive.

KAlO2
  • 838
  • 11
  • 13
  • 17
    don't think so Martin, from SDK help of 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" – ruhalde Jan 08 '13 at 20:21
  • 3
    Apparently this only supports a limited subset of running tasks in Android 5 / Lollipop. – Sam Jan 03 '15 at 02:34
  • 7
    The documentation for [ActivityManager.getRunningTasks()](https://developer.android.com/reference/android/app/ActivityManager.html#getRunningTasks(int)) says "This method was deprecated in API level 21". – markshep Dec 15 '16 at 15:26
22

I did the Following in Kotlin

  1. Create Application Class
  2. Edit the Application Class as Follows

    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. Create the ActivityLifecycleCallbacks class

    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. you can now use it in any class by calling the following: FTApplication.currentActivity()

Rashad.Z
  • 2,494
  • 2
  • 27
  • 58
  • 3
    That's the only clean solution i found, btw you just need to run onActivityResumed, the other actions are useless as the resume is launched after the Activity is created. Just to be sure i would set currentActivity = null on onActivityStopped if currentActivity == activity – Plokko Oct 15 '20 at 09:17
  • It works well, thank you. FYI: to activate the Callbacks, you have to add in AndroidManifest: – Caesar Dec 13 '21 at 09:58
6

getCurrentActivity() is also in ReactContextBaseJavaModule.
(Since the this question was initially asked, many Android app also has ReactNative component - hybrid app.)

class ReactContext in ReactNative has the whole set of logic to maintain mCurrentActivity which is returned in getCurrentActivity().

Note: I wish getCurrentActivity() is implemented in Android Application class.

朱梅寧
  • 139
  • 1
  • 4
  • in some cases this context from ReactContextBaseJavaModule is null, do you know why? – Moxor Aug 02 '18 at 19:05
  • `ReactContext.getCurrentActivity()` is not reliable enough. See [this bug](https://github.com/facebook/react-native/issues/37518), for example. – d4vidi May 23 '23 at 12:13
6

For backwards compatibility:

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
  • 1
  • 19
  • 155
  • 216
  • 5
    Unless there's a way to get from ComponentName to the current instance of the Activity, this doesn't answer the question IMO. – nasch May 22 '19 at 19:52
  • @nasch one can keep and get a `WeakReference` handle from an `Application` class - while the `ComponentName` is required to determine if the desired `Activity` is on top of the running tasks list. And if this does not fully answer the question, the accepted answer does not either. – Martin Zeitler Sep 12 '19 at 19:10
  • I agree, the accepted answer doesn't fully answer the question either. – nasch Sep 12 '19 at 19:58
  • 2
    `topActivity` is available only from Android Q – Eugen Martynov Sep 19 '19 at 15:30
4

I could not find a solution that our team would be happy with so we rolled our own. We use ActivityLifecycleCallbacks to keep track of current activity and then expose it through a service. More details here: https://stackoverflow.com/a/38650587/10793

Community
  • 1
  • 1
Muxa
  • 5,563
  • 6
  • 46
  • 56
2

by using this part of code you detect when your app goes background/foreground and you access the current activity name and context.

My answer is based on this article : Android: How to detect when App goes background/foreground

First, create a class that extends the android.app.Application and implements the ActivityLifecycleCallbacks interface. In the Application.onCreate(), register the callback.

public class App extends Application implements ActivityLifecycleCallbacks
@Override
public void onCreate() {
    super.onCreate();
    registerActivityLifecycleCallbacks(this);
}

Register the “App” class in the Manifest as below,

<application
    android:name=".App"

This is how the ActivityLifecycleCallbacks interface looks like,

public interface ActivityLifecycleCallbacks {
    void onActivityCreated(Activity activity, Bundle savedInstanceState);
    void onActivityStarted(Activity activity);
    void onActivityResumed(Activity activity);
    void onActivityPaused(Activity activity);
    void onActivityStopped(Activity activity);
    void onActivitySaveInstanceState(Activity activity, Bundle outState);
    void onActivityDestroyed(Activity activity);
}

So, when any of your Activity(Activities you created or included by your Libraries) goes through any of the above mentioned lifecycle methods, these callbacks will be called. There will be at least one Activity in the started state when the app is in the foreground and there will be no Activity in the started state when the app is in the background. Declare 2 variables as below in the “App” class.

private int activityReferences = 0;
private boolean isActivityChangingConfigurations = false;

activityReferences will keep the count of number of Activities in the started state. isActivityChangingConfigurations is a flag to indicate if the current Activity is going through configuration change like orientation switch. Using the following code you can detect if the App comes foreground.

@Override
public void onActivityStarted(Activity activity) {
    if (++activityReferences == 1 && !isActivityChangingConfigurations) {
        // App enters foreground
    }
}

You can access context in this method like this :

activity.getBaseContext()

This is how to detect if the App goes background.

Override
public void onActivityStopped(Activity activity) {

    isActivityChangingConfigurations = activity.isChangingConfigurations();
    if (--activityReferences == 0 && !isActivityChangingConfigurations) {
        // App enters background
    }
}

Now you can access the current foreground activity name and context.

Ghazal
  • 123
  • 2
  • 9
2

Best solution so far Create a class name ActivityManager in your app (java)

public class ActivityManager implements Application.ActivityLifecycleCallbacks {

    private Activity activity;


    public ActivityManager(App myApplication) {
        myApplication.registerActivityLifecycleCallbacks(this);
    }

    public Activity getActivity(){
        return activity;
    }
    @Override
    public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle bundle) {
        this. activity = activity;

    }

    @Override
    public void onActivityStarted(@NonNull Activity activity) {
       this. activity = activity;
    }

    @Override
    public void onActivityResumed(@NonNull Activity activity) {
        this. activity = activity;

    }

    @Override
    public void onActivityPaused(@NonNull Activity activity) {

    }

    @Override
    public void onActivityStopped(@NonNull Activity activity) {

    }

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

    }

    @Override
    public void onActivityDestroyed(@NonNull Activity activity) {

    }
}

Then initialize it in your Application (kotlin)

class App : Application() {

    override fun onCreate() {
     
        appOpenManager =  AppOpenManager(this);
    }
  companion object {
        lateinit var appOpenManager: AppOpenManager
    }
}

Then use like

App.activityManager.getActivity()

nhCoder
  • 451
  • 5
  • 11
1

Personally I did as "Cheok Yan Cheng" said, but I used a "List" to have a "Backstack" of all my activities.

If you want to check Which is the Current Activity you just need to get the last activity class in the list.

Create an application which extends "Application" and do this:

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 my case I used "Application.ActivityLifecycleCallbacks" to:

  • Bind/Unbind Merlin Instance (used to get event when the app lose or get connection, for example when you close mobile data or when you open it). It is useful after the "OnConnectivityChanged" intent action was disabled. For more info about MERLIN see: MERLIN INFO LINK

  • Close my last Realm Instance when the application is closed; I will init it inside a BaseActivity wich is extended from all others activities and which has a private RealmHelper Instance. For more info about REALM see: REALM INFO LINK For instance I have a static "RealmHelper" instance inside my "RealmHelper" class which is instantiated inside my application "onCreate". I have a synchronization service in which I create I new "RealmHelper" because Realm is "Thread-Linked" and a Realm Instance can't work inside a different Thread. So in order to follow Realm Documentation "You Need To Close All Opened Realm Instances to avoid System Resources Leaks", to accomplish this thing I used the "Application.ActivityLifecycleCallbacks" as you can see up.

  • Finally I have a receiver wich is triggered when I finish to synchronize my application, then when the sync end it will call the "IEndSyncCallback" "onEndSync" method in which I look if I have a specific Activity Class inside my ActivitiesBackStack List because I need to update the data on the view if the sync updated them and I could need to do others operations after the app sync.

That's all, hope this is helpful. See u :)

Z3R0
  • 1,011
  • 10
  • 19
0

You can use this Class for flexible lifecycle handling

Usage:

    //Initialization
    val lifeCycleHandler = ActivityLifeCycleHandler<Activity>()

    //Detect only a specific type of activities
    val lifeCycleHandler = ActivityLifeCycleHandler<MainActivity>()

    //Get current activity
    val instance = lifeCycleHandler.currentReference

    //Get current activity state
    val state = lifeCycleHandler.currentState

    //Use listeners
    lifeCycleHandler.addStateChangeListener { newState ->
        //TODO: handle new state
    }

    lifeCycleHandler.addSpecificStateChangeListener(ActivityLifeCycleHandler.ActivityState.STARTED) {
        //TODO: handle new state
    }

    //Removable listeners
    val listener = { newState: Int ->

    }

    lifeCycleHandler.addStateChangeListener(listener)
    lifeCycleHandler.removeStateChageListener(listener)


    //Start listening
    App.app.registerActivityLifecycleCallbacks(lifeCycleHandler)

    //Stop listening
    lifeCycleHandler.releaseListeners()
    App.app.unregisterActivityLifecycleCallbacks(lifeCycleHandler)
Tamim Attafi
  • 2,253
  • 2
  • 17
  • 34
0

If you're using kotlin then it can help yoy to get current activity name. However getRecentTasks() method is deprecated in Java.

 val am: ActivityManager = applicationContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
 val activityName: String = am.getRecentTasks(1, 0).get(0).topActivity.toString()
-1

The answer by waqas716 is good. I created a workaround for a specific case demanding less code and maintenance.

I found a specific work around by having a static method fetch a view from the activity I suspect to be in the foreground. You can iterate through all activities and check if you wish or get the activity name from martin's answer

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

I then check if the view is not null and get the context 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"));
}
Community
  • 1
  • 1
Rubber Duck
  • 3,673
  • 3
  • 40
  • 59
  • I am looking for similar issue here http://stackoverflow.com/questions/22788289/android-dynamically-find-view-of-the-top-running-activity how do we get "SuspectedActivity" ? Is this native API? – Stella Apr 02 '14 at 17:18
  • 2
    BUT from docs for `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 http://developer.android.com/reference/android/app/ActivityManager.html#getRunningTasks(int) – ToolmakerSteve Oct 07 '15 at 22:59
  • 3
    The documentation for [ActivityManager.getRunningTasks()](https://developer.android.com/reference/android/app/ActivityManager.html#getRunningTasks(int)) now says "This method was deprecated in API level 21". – markshep Dec 15 '16 at 15:38
-1

Use the is operator or its negated form !is to perform a runtime check that identifies whether an object conforms to a given type:

if (this !is OneActivity) {
// do something
} else if (this !is TwoActivity) {
// do something 2
}
Hasan Mhd Amin
  • 220
  • 2
  • 11
-2

I don't like any of the other answers. The ActivityManager is not meant to be used for getting the current activity. Super classing and depending on onDestroy is also fragile and not the best design.

Honestly, the best I have came up with so far is just maintaining an enum in my Application, which gets set when an activity is created.

Another recommendation might be to just shy away from using multiple activities if possible. This can be done either with using fragments, or in my preference custom views.

stevebot
  • 23,275
  • 29
  • 119
  • 181
-3

A rather simple solution is to create a singleton manager class, in which you can store a reference to one or more Activities, or anything else you want access to throughout the app.

Call UberManager.getInstance().setMainActivity( activity ); in the main activity's onCreate.

Call UberManager.getInstance().getMainActivity(); anywhere in your app to retrieve it. (I am using this to be able to use Toast from a non UI thread.)

Make sure you add a call to UberManager.getInstance().cleanup(); when your app is being destroyed.

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
  • 49
  • 12
  • This is intrusive and requires changes in all the activities. The [answer by AZ_](http://stackoverflow.com/a/28423385/641332) is much better as it's totally localised and standalone without requiring other changes in the codebase. – markshep Dec 15 '16 at 15:42
-7

I'm like 3 years late but I'll answer it anyway in case someone finds this like I did.

I solved this by simply using this:

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

Note that "getIntent().toString()" includes a bunch of other text such as your package name and any intent filters for your activity. Technically we're checking the current intent, not activity, but the result is the same. Just use e.g. Log.d("test", getIntent().toString()); if you want to see all the text. This solution is a bit hacky but it's much cleaner in your code and the functionality is the same.

Simon Hyll
  • 3,265
  • 3
  • 24
  • 44