如何在android中获取当前的前台活动上下文?
每当我的广播执行,我想显示警报前景活动。
知道ActivityManagerpipe理Activity ,所以我们可以从ActivityManager获取信息。 我们得到当前正在运行的Activity by
ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE); ComponentName cn = am.getRunningTasks(1).get(0).topActivity;
( 注意:官方API被添加到API 14中:请参阅此答案https://stackoverflow.com/a/29786451/119733 )
不要使用以前(waqas716)的答案。
由于对活动的静态引用,您将有内存泄漏问题。 有关更多详细信息,请参阅以下链接http://android-developers.blogspot.fr/2009/01/avoiding-memory-leaks.html
为了避免这种情况,你应该pipe理活动引用。 在清单文件中添加应用程序的名称:
<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 setCurrentActivity(Activity mCurrentActivity){ this.mCurrentActivity = mCurrentActivity; } }
创build一个新的活动:
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); } }
所以,现在不要为活动扩展Activity类,只需扩展MyBaseActivity即可。 现在,您可以像应用程序或Activity一样获取当前的活动:
Activity currentActivity = ((MyApp)context.getApplicationContext()).getCurrentActivity();
我在@ gezdy的答案的顶部展开。
在每个活动中,我们可以使用14级以下的API来帮助我们以较less的手工编码实现类似的目的,而不必通过手动编码“注册” Application
。
public void registerActivityLifecycleCallbacks (Application.ActivityLifecycleCallbacks callback)
在Application.ActivityLifecycleCallbacks
,你可以得到哪个Activity
被“附加”到或“分离”到这个Application
。
但是,这种技术仅在API级别14以后才可用。
[[UPDATE]]
正如@gezdy所指出的,我很感激。 为当前活动设置引用为null ,而不是每一个onResume上的更新设置为null在每个Activity的onDestroy,以避免内存泄漏问题。
前一段时间,我需要相同的function,这是我如何实现这一目标的方法。 在你的每一个活动覆盖这些生命周期方法。
@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); }
现在在您的广播课程中,您可以访问当前活动以显示警报。
@lockwobr感谢您的更新
这在api版本16中没有100%的工作时间,如果你读了github上的代码,函数“currentActivityThread”在Kitkat中是变化的,所以我想说版本19ish,很难匹配api版本到github 。
获得当前的Activity
非常方便。 有一个静态的getActivity
方法返回当前的Activity没有不必要的问题不是很好吗?
Activity
类非常有用。 它可以访问应用程序的UI线程,视图,资源等等。 许多方法需要一个Context
,但如何获得指针? 以下是一些方法:
- 使用重写的生命周期方法跟踪应用程序的状态。 您必须将当前活动存储在静态variables中,并且需要访问所有活动的代码。
- 使用Instrumentation跟踪应用程序的状态。 在manifest中声明Instrumentation,实现它并使用它的方法来跟踪Activity的变化。 将活动指针传递给活动中使用的方法和类。 使用其中一个代码注入库注入指针。 所有这些方法都很不方便 ; 幸运的是,获得当前活动有一个更简单的方法。
- 似乎系统需要访问所有活动,而没有上述问题。 所以,最有可能的方法是仅使用静态调用来获取活动。 我花了很多时间在grepcode.com上挖掘Android源代码,并且find了我正在寻找的东西。 有一个叫做
ActivityThread
的类。 这个类可以访问所有的活动,甚至更好,有一个获取当前ActivityThread
的静态方法。 只有一个小问题 – 活动列表具有包访问权限。
使用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; }
这样的方法可以在应用程序中的任何地方使用,并且比所有提到的方法更方便。 而且,它看起来并不像看起来那样不安全。 它不会引入任何新的潜在的泄漏或空指针。
上面的代码片段缺lessexception处理,并且天真地假定第一个运行的Activity是我们正在寻找的。 您可能想要添加一些额外的检查。
博客文章
我找不到一个解决scheme,我们的团队会很高兴,所以我们推出了自己的。 我们使用ActivityLifecycleCallbacks
来跟踪当前活动,然后通过服务公开它。 更多细节在这里: https : //stackoverflow.com/a/38650587/10793
我不喜欢任何其他的答案。 ActivityManager不是用来获取当前活动的。 超级分类和依赖onDestroy也是脆弱的,而不是最好的devise。
说实话,迄今为止我所提出的最好的方法就是在应用程序中维护一个枚举,当创build一个活动时它会被设置。
如果可能,另一个build议可能是避免使用多个活动。 这可以通过使用片段来完成,也可以在我的偏好自定义视图中完成。
waqas716的答案很好。 我为需要较less代码和维护的特定情况创build了一个解决方法。
我发现一个特定的工作,通过静态方法从我怀疑在前台的活动中获取一个视图。 你可以遍历所有的活动,并检查你是否希望或从马丁的答案获得活动的名称
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")); }
我迟到了3年,但我会回答,以防有人发现我这样做。
我简单地使用这个解决了这个问题:
if (getIntent().toString().contains("MainActivity")) { // Do stuff if the current activity is MainActivity }
请注意,“getIntent()。toString()”包含一系列其他文本,如包名称和您的活动的任何意图filter。 从技术上讲,我们正在检查当前的意图,而不是活动,但结果是一样的。 只要使用Log.d(“test”,getIntent()。toString()); 如果你想看到所有的文字。 这个解决scheme有点不方便,但是在你的代码中它更干净,function也是一样的。
一个相当简单的解决scheme是创build一个单例pipe理器类,在该类中可以存储对一个或多个活动的引用,或者您想要在整个应用程序中访问的其他任何内容。
调用UberManager.getInstance().setMainActivity( activity );
在主要活动的onCreate。
调用UberManager.getInstance().getMainActivity();
在您的应用程序的任何地方检索它。 (我正在使用这个来从非UI线程中使用Toast。)
确保你添加了一个调用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; } }