Как получить текущий контекст активности переднего плана в Android?

Всякий раз, когда моя трансляция выполняется, я хочу показывать предупреждение переднего плана деятельности.

 AAnkit10 июл. 2012 г., 12:40
активность приложения! это ваше приложение ?? и зачем тебе это, по любой причине, может есть альтернатива по тому же
 AAnkit10 июл. 2012 г., 12:34
откуда вы хотите получить контекст Activity. Будет ли это ваше приложение активности или другое приложение.
 Deepali10 июл. 2012 г., 12:37
это приложение активности. Я выполнил кодирование предупреждений в функции onreceive () вещательного приемника.
 AAnkit10 июл. 2012 г., 12:55
только при получении COntext в качестве параметра, вы можете сказать context.getApplicationContext ()
 Deepali10 июл. 2012 г., 12:53
Я хочу показать оповещение о своей активности на переднем плане. Это любой другой способ показать оповещение об активности на переднем плане без контекста.

Ответы на вопрос(13)

Список & quot; иметь & quot; Backstack & quot; всей моей деятельности.

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

Создайте приложение, которое расширяет «Приложение». и сделать это:

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

}

В моем случае я использовал «Application.ActivityLifecycleCallbacks» чтобы:

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 do some operation if I already have passed this point inside my application.

Это все, надеюсь, это полезно. Увидимся :)

waqas716 это хорошо. Я создал обходной путь для конкретного случая, требующего меньше кода и обслуживания.

Я нашел конкретную работу, применив статический метод, извлекающий представление из действия, которое, как я подозреваю, находится на переднем плане. Вы можете перебирать все действия и проверять, хотите ли вы или получите название действия отmartin's ответ

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

Затем я проверяю, не является ли представление нулевым, и получаю контекст через 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"));
}
 15 дек. 2016 г., 16:38
Документация дляActivityManager.getRunningTasks() теперь говорит "Этот метод устарел на уровне API 21".
 08 окт. 2015 г., 00:59
НО из документов для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, ..."  вdeveloper.android.com/reference/android/app/…
 02 апр. 2014 г., 19:18
Я ищу похожую проблему здесьstackoverflow.com/questions/22788289/…                                Как мы можем получить «SuspectedActivity»? ? Это родной API?
Решение Вопроса

ActivityManager управляетActivityтак что мы можем получить информацию отActivityManager, Мы получаем текущий передний план, выполняющий Activity by

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

ОБНОВЛЕНИЕ 2018/10/03
getRunningTasks() устарела. увидеть решения ниже.

Этот метод устарел на уровне API 21. Начиная с версии Build.VERSION_CODES.LOLLIPOP, этот метод больше не доступен для сторонних приложений: введение центрированных на документы последних событий означает, что он может передавать информацию о человеке вызывающей стороне. Для обратной совместимости он по-прежнему будет возвращать небольшое подмножество своих данных: по меньшей мере, собственные задачи вызывающего абонента и, возможно, некоторые другие задачи, такие как home, которые, как известно, не являются чувствительными.

 03 янв. 2015 г., 03:34
По-видимому, это поддерживает только ограниченный набор запущенных задач в Android 5 / Lollipop.
 10 февр. 2015 г., 04:18
stackoverflow.com/a/28423385/185022 :) лучший подход
 08 янв. 2013 г., 21:21
Не думайте, Мартин, из справки SDR getRunningTasks. Примечание: этот метод предназначен только для отладки и представления пользовательских интерфейсов управления задачами. Это никогда не должно использоваться для основной логики в приложении & quot;
 15 дек. 2016 г., 16:26
Документация дляActivityManager.getRunningTasks() говорит "Этот метод устарел на уровне API 21".

в котором вы можете хранить ссылку на одно или несколько действий или что-то еще, к чему вы хотите получить доступ во всем приложении.

ВызовUberManager.getInstance().setMainActivity( activity ); в основной деятельности по созданию.

ВызовUberManager.getInstance().getMainActivity(); в любом месте вашего приложения, чтобы получить его. (Я использую это, чтобы иметь возможность использовать тост из потока не пользовательского интерфейса.)

Убедитесь, что вы добавили вызовUberManager.getInstance().cleanup(); когда ваше приложение разрушается.

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;
    }
}
 15 дек. 2016 г., 16:42
Это навязчиво и требует изменений во всех видах деятельности.answer by AZ_ намного лучше, поскольку он полностью локализован и автономен, не требуя других изменений в кодовой базе.

но все равно отвечу, если кто-то найдет это, как я.

Я решил это, просто используя это:

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

Обратите внимание, что & quot; getIntent (). ToString () & quot; включает в себя кучу другого текста, такого как имя вашего пакета и любые фильтры намерений для вашей деятельности. Технически мы проверяем текущее намерение, а не деятельность, но результат тот же. Просто используйте, например, Log.d (& quot; test & quot ;, getIntent (). ToString ()); если вы хотите увидеть весь текст. Это решение немного хакерское, но оно гораздо чище в вашем коде и функциональность та же.

ля получения текущей активности. Суперклассификация и в зависимости от onDestroy также хрупкая и не самый лучший дизайн.

Честно говоря, лучшее из того, что я придумал до сих пор, - это просто поддерживать enum в моем приложении, которое устанавливается при создании действия.

Другая рекомендация может заключаться в том, чтобы просто избегать использования нескольких видов деятельности, если это возможно. Это можно сделать либо с помощью фрагментов, либо в моих предпочтениях пользовательских представлений.

 08 окт. 2015 г., 01:02
перечисление? Как это помогает найти текущий экземпляр активности переднего плана?
 08 окт. 2015 г., 02:58
"Суперклассификация и в зависимости от onDestroy также хрупкая" Как это хрупко?


(Поскольку этот вопрос был задан изначально, многие приложения для Android также имеют компонент ReactNative - гибридное приложение.)

Класс ReactContext в ReactNative имеет полный набор логики для поддержки mCurrentActivity, который возвращается в getCurrentActivity ().

Примечание. Мне бы хотелось, чтобы getCurrentActivity () была реализована в классе приложений Android.

 02 авг. 2018 г., 21:05
в некоторых случаях этот контекст из ReactContextBaseJavaModule имеет значение null, знаете почему?

I did the Following in Kotlin

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

 }

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
}

}

you can now use it in any class by calling the following: FTApplication.currentActivity()

Update 2: Для этого добавлен официальный API, пожалуйста, используйтеActivityLifecycleCallbacks вместо.

UPDATE:

Как указано @gezdy, и я благодарен за это.set reference to null too для текущей активности вместо обновления только для каждого onResume установите для него значение null в каждом onDestroy действия, чтобы избежать проблемы утечки памяти.

Некоторое время назад мне нужна была та же функциональность, и вот метод, как я этого добился. В каждой вашей деятельности переопределите эти методы жизненного цикла.

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

Теперь в вашем классе вещания вы можете получить доступ к текущей активности, чтобы показать предупреждение о ней.

 24 нояб. 2012 г., 08:49
@ waqas716: где должен быть написан класс AppConsts ????
 22 июн. 2014 г., 05:32
@ waqas716 Я предлагаю упростить условие вclearReferences() в(this.equals(currActivity)).
 26 февр. 2014 г., 22:56
Там будут проблемы с иерархической деятельностью. Когда вы возвращаетесь из дочернего действия в родительское, оно: (1) называется onPause дочернего элемента; (2) родительский onResume; (3) onDestroy ребенка == & gt; текущая активность будет нулевой. Вы должны сделать некоторую проверку как @gezdy в его примере в методе clearReferences.
 02 окт. 2012 г., 16:53
Спасибо. Но, похоже, @Deepali не успел это принять :).
 02 окт. 2012 г., 15:38
Этот ответ действительно должен получить больше голосов, простое решение, но мощное, когда у вас есть классы, которым нужно манипулировать действиями, но не самими действиями.

В каждой деятельности вместо того, чтобы «регистрироваться» сам сApplication с помощью ручного кодирования мы можем использовать следующий API начиная с уровня 14, чтобы помочь нам достичь аналогичной цели с меньшим количеством ручного кодирования.

public void registerActivityLifecycleCallbacks (Application.ActivityLifecycleCallbacks callback)

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

ВApplication.ActivityLifecycleCallbacksВы можете получить какойActivity "прикреплен" или "отсоединен" к этомуApplication.

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

 08 окт. 2015 г., 01:58
@MichaelBushe - в 2012 году, когда были написаны другие ответы, в зависимости от уровня API 14 нельзя было полагаться на каждое устройство, учитывая, что API был выпущен только недавно (октябрь 2011 года).
 30 сент. 2016 г., 09:27
Я думаю, что ваш ответ лучше
 06 окт. 2016 г., 13:09
отличный ответ. Единственным недостатком является то, что вам все еще нужно сохранять активность в каком-либо месте, если вам нужно запросить у вашего класса текущую активность. так что вам все равно нужно избегать утечки памяти и обнулять ссылку.
 14 июл. 2015 г., 00:46
Что со всеми остальными ответами? Очевидно, что это разработанный API для этой цели. Спасибо, Чок Ян Ченг
 08 окт. 2015 г., 03:40
Нашел ответ, показывающий, как использовать этот подход:stackoverflow.com/a/11082332/199364  Преимущество в том, чтоnothing need be done to the activities themselves; код находится в вашем пользовательском классе обратного вызова. Вы просто делаете класс, которыйimplements Application.ActivityLifecycleCallbacksи добавьте методы для реализации этого. Затем в этом классе конструктор (или onCreate или init или другой метод, который запускается, когда экземпляр становится активным / готовым), положитьgetApplication().registerActivityLifecycleCallbacks(this); как последняя строка.

Note: Официальный API был добавлен в API 14: см. Этот ответhttps://stackoverflow.com/a/29786451/119733)

НЕ ИСПОЛЬЗУЙТЕ ПРЕДЫДУЩИЙ waqas716) ответ.

У вас будет проблема утечки памяти из-за статической ссылки на действие. Для более подробной информации смотрите следующую ссылкуhttp://android-developers.blogspot.fr/2009/01/avoiding-memory-leaks.html

Чтобы избежать этого, вы должны управлять ссылками на действия. Добавьте название приложения в файл манифеста:

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

Ваш класс приложения:

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

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

Создать новую активность:

public class MyBaseActivity extends Activity {
    protected MyApp mMyApp;

    public void onCreateBundle savedInstanceState) {
        super.onCreatesavedInstanceState);
        mMyApp = MyApp)this.getApplicationContext);
    }
    protected void onResume) {
        super.onResume);
        mMyApp.setCurrentActivitythis);
    }
    protected void onPause) {
        clearReferences);
        super.onPause);
    }
    protected void onDestroy) {        
        clearReferences);
        super.onDestroy);
    }

    private void clearReferences){
        Activity currActivity = mMyApp.getCurrentActivity);
        if this.equalscurrActivity))
            mMyApp.setCurrentActivitynull);
    }
}

Итак, теперь вместо расширения класса Activity для ваших действий просто расширьте MyBaseActivity. Теперь вы можете получить текущую активность из приложения или из контекста активности следующим образом:

Activity currentActivity = MyApp)context.getApplicationContext)).getCurrentActivity);
 26 мая 2013 г., 17:55
Вы можете просто использовать WeakReference и достичь того же результата с меньшим количеством кода.
 30 окт. 2013 г., 17:45
@MaximKorobov Да, это возможно, если вы вызываете finish () из onCreate (), если вы используете свое действие только для запуска другого действия и прекращаете его. В этом случае он пропускает onPause () и onStoo (). Смотрите нижнюю ноту:developer.android.com/training/basics/activity-lifecycle/…
 14 апр. 2015 г., 14:45
Начиная с Android API уровня 14 должно быть возможно использоватьApplication .ActivityLifecycleCallbacks, что будет более важным, и вам не придется добавлять какой-либо код управления во все ваши действия. Также смdeveloper.android.com/reference/android/app/…
 13 авг. 2014 г., 15:52
@rekire @NachoColoma ИспользованиеWeakReference не рекомендуется для кэширования, это не кэширование, то естьmCurrentActivity будет иметь ссылку на него, только когда он жив, так чтоWeakReference никогда не будут собраны, покаActivity на вершине. Однако то, что предлагает @NachoColoma, неверно, потому чтоWeakReference может по-прежнему ссылаться на невозобновленную (не активную / не активную) активность, если переменная не очищена!
 25 июн. 2013 г., 12:46
@ Начо я бы никогда не рекомендовал использоватьWeakReferences в Android GC собирает их быстрее, чем вы думаете.

@lockwobr Спасибо за обновление

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.

Имея доступ к текущемуActivity очень удобно Не было бы неплохо иметь статическийgetActivity метод, возвращающий текущую активность без лишних вопросов?

Activity класс очень полезен. Он предоставляет доступ к потоку пользовательского интерфейса приложения, представлениям, ресурсам и многому другому. Многочисленные методы требуютContextа как получить указатель? Вот несколько способов:

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.

Легко решить с помощью отражения:

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

Такой метод можно использовать в любом месте приложения, и он намного удобнее, чем все упомянутые выше подходы. Более того, кажется, что это не так небезопасно, как кажется. Он не вводит каких-либо новых потенциальных утечек или нулевых указателей.

В приведенном выше фрагменте кода отсутствует обработка исключений, и он наивно предполагает, что первое запущенное действие - это то, что мы ищем. Возможно, вы захотите добавить некоторые дополнительные проверки.

Сообщение блога

 19 окт. 2015 г., 13:58
в Kitkat и выше mActivities - это не HashMap, а ArrayMap, поэтому вам нужно изменить эту строку: HashMap activity = (HashMap) activityField.get (activityThread); выглядеть следующим образом: ArrayMap activity = (ArrayMap) activityField.get (activityThread);
 19 окт. 2016 г., 08:24
@lockwobr спасибо, решение обновлено с вашим комментарием:)
 31 авг. 2017 г., 18:51
Доступ к внутренним API через рефлексию не поддерживается и может работать не на всех устройствах или в будущем.
 23 дек. 2015 г., 09:35
@Palejandro для поддержки обоих уровней API (выше 18 и ниже), которые он должен использоватьMap интерфейс вместоHashMap или жеArrayMap, Я отредактировал @AZ_ ответ.
 18 окт. 2016 г., 22:24
Это не работает 100% времени в APIversion 16, если вы читаете код на github, функция & quot; currentActivityThread & quot; было изменение в Kitkat, поэтому я хочу сказать, версия19ishОтчасти трудно сопоставить версию API с выпусками в github.

которым наша команда была бы довольна, поэтому мы сделали свое дело. Мы используемActivityLifecycleCallbacks отслеживать текущую активность, а затем выставлять ее через сервис. Подробнее здесь:https://stackoverflow.com/a/38650587/10793

Ваш ответ на вопрос