Question

[Solved] How to get current foreground activity context in android?

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

Enquirer: Deepali

||

Solution #1:

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.

Respondent: KAlO2

Solution #2:

(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();
Respondent: gezdy

Solution #3:

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.

Respondent: Cheok Yan Cheng

Solution #4:

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

Respondent: Waqas

Solution #5:

@lockwobr Thanks for update

This does not work 100% of the time in api version 16, if you read the
code on github the function “currentActivityThread” was change in
Kitkat, so I want to say version 19ish, kind of hard to match api
version to releases in github.

Having access to the current Activity is very handy. Wouldn’t it be nice to have a static getActivity method returning the current Activity with no unnecessary questions?

The Activity class is very useful. It gives access to the application’s UI thread, views, resources, and many more. Numerous methods require a Context, but how to get the pointer? Here are some ways:

  • Tracking the application’s state using overridden lifecycle methods.
    You have to store the current Activity in a static variable and you
    need access to the code of all Activities.
  • Tracking the application’s state using Instrumentation. Declare
    Instrumentation in the manifest, implement it and use its methods to
    track Activity changes. Passing an Activity pointer to methods and
    classes used in your Activities. Injecting the pointer using one of
    the code injection libraries. All of these approaches are rather
    inconvenient
    ; fortunately, there is a much easier way to get the
    current Activity.
  • Seems like the system needs access to all Activities without the
    issues mentioned above. So, most likely there is a way to get
    Activities using only static calls. I spent a lot of time digging
    through the Android sources on grepcode.com, and I found what I was
    looking for. There is a class called ActivityThread. This class has
    access to all Activities and, what’s even better, has a static method
    for getting the current ActivityThread. There is only one little
    problem – the Activity list has package access.

Easy to solve using reflection:

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

Such a method can be used anywhere in the app and it’s much more convenient than all of the mentioned approaches. Moreover, it seems like it’s not as unsafe as it looks. It doesn’t introduce any new potential leaks or null pointers.

The above code snippet lacks exception handling and naively assumes that the first running Activity is the one we’re looking for. You might want to add some additional checks.

Blog Post

Respondent: AZ_

Solution #6:

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

Respondent: Rashad.Z

Solution #7:

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.

Respondent: ???

Solution #8:

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

Respondent: Muxa

Solution #9:

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;
}
Respondent: Martin Zeitler

Solution #10:

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 🙂

Respondent: Z3R0

Solution #11:

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)
Respondent: Tamim Attafi

Solution #12:

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"));
}
Respondent: Rubber Duck

Solution #13:

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.

Respondent: stevebot

Solution #14:

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;
    }
}
Respondent: MukRaker

Solution #15:

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.

Respondent: Simon Hyll

The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .

Most Popular

To Top
India and Pakistan’s steroid-soaked rhetoric over Kashmir will come back to haunt them both clenbuterol australia bossier man pleads guilty for leadership role in anabolic steriod distribution conspiracy