每当我的广播被执行时,我想向前台活动显示警告。
答案 0 :(得分:190)
(注意: API 14中添加了官方API:请参阅此回答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 setCurrentActivity(Activity mCurrentActivity){
this.mCurrentActivity = mCurrentActivity;
}
}
创建一个新活动:
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 currentActivity = ((MyApp)context.getApplicationContext()).getCurrentActivity();
答案 1 :(得分:59)
我扩展了@ gezdy的答案。
在每个活动中,我们不需要使用手动编码将Application
“注册”给自己,而是从14级开始使用以下API,以帮助我们以更少的手动编码实现类似目的。
public void registerActivityLifecycleCallbacks (Application.ActivityLifecycleCallbacks callback)
在Application.ActivityLifecycleCallbacks
中,您可以将[{1}}“附加”或“分离”到此Activity
。
但是,此技术仅适用于API级别14。
答案 2 :(得分:51)
更新2 :为此添加了官方API,请改为使用ActivityLifecycleCallbacks。
<强>更新强>
正如@gezdy指出的那样,我很感激。 为当前活动设置对null 的引用,而不是仅在每个onResume上更新,在每个Activity的onDestroy上将其设置为null以避免内存泄漏问题。
前一段时间我需要相同的功能,这是我实现这一目标的方法。 在您的每个活动中覆盖这些生命周期方法。
@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);
}
现在,在您的广播课程中,您可以访问当前活动以在其上显示提醒。
答案 3 :(得分:45)
@lockwobr 感谢您的更新
如果您阅读了,那么在api版本16中这不会100%有效 代码在github上的函数&#34; currentActivityThread&#34;改变了 Kitkat,所以我想说版本19ish,有点难以匹配api 版本发布在github中。
有权访问当前的Activity
非常方便。使用静态getActivity
方法返回当前活动并没有不必要的问题会不会很好?
Activity
类非常有用。它可以访问应用程序的UI线程,视图,资源等等。许多方法需要Context
,但如何获取指针?以下是一些方法:
ActivityThread
的类。这堂课有
访问所有活动,更好的是,有一个静态方法
获取当前ActivityThread
。只有一点点
问题 - 活动列表具有包访问权限。 使用反射很容易解决:
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;
}
这种方法可以在应用程序的任何地方使用,它比所有提到的方法更方便。而且,它看起来并不像它看起来那样不安全。它不会引入任何新的潜在泄漏或空指针。
上面的代码片段没有异常处理,天真地假设第一个正在运行的Activity是我们正在寻找的。您可能想要添加一些额外的检查。
答案 4 :(得分:33)
知道 ActivityManager 管理活动,因此我们可以从 ActivityManager 获取信息。我们通过
获取当前前台运行的ActivityActivityManager 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。
答案 5 :(得分:5)
getCurrentActivity()也在ReactContextBaseJavaModule中 (由于这个问题最初被问到,很多Android应用程序也有ReactNative组件 - 混合应用程序。)
ReactNative中的类ReactContext具有整个逻辑集来维护在getCurrentActivity()中返回的mCurrentActivity。注意:我希望getCurrentActivity()在Android Application类中实现。
答案 6 :(得分:3)
我找不到我们团队满意的解决方案,所以我们推出了自己的解决方案。我们使用ActivityLifecycleCallbacks
来跟踪当前活动,然后通过服务公开它。更多详情:https://stackoverflow.com/a/38650587/10793
答案 7 :(得分:1)
我在Kotlin中进行了跟踪
按如下所述编辑应用程序类
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
}
}
}
创建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
}
}
您现在可以通过调用以下命令在任何类中使用它:FTApplication.currentActivity()
答案 8 :(得分:0)
我个人是按照“ Cheok Yan Cheng”的说法做的,但是我使用了“ List”将我所有的活动都做了“ Backstack”。
如果要检查哪个是当前活动,则只需要获取列表中的最后一个活动类别即可。
创建一个扩展“应用程序”的应用程序,然后执行以下操作:
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”进行了以下操作:
绑定/解除绑定Merlin实例(用于在应用程序丢失或获得连接时(例如,当您关闭移动数据或打开它时)获取事件)。禁用“ OnConnectivityChanged”意图操作后,此功能很有用。 有关MERLIN的更多信息,请参见:MERLIN INFO LINK
在应用程序关闭时关闭我的最后一个Realm实例;我将在所有其他活动的BaseActivity范围内对其进行初始化,该活动具有私有RealmHelper实例。 有关REALM的更多信息,请参见:REALM INFO LINK 例如,我的“ RealmHelper”类中有一个静态的“ RealmHelper”实例,该实例在我的应用程序“ onCreate”中实例化。我有一个同步服务,其中创建了新的“ RealmHelper”,因为Realm是“线程链接的”,并且Realm实例不能在其他线程中工作。 因此,为了遵循Realm文档“您需要关闭所有打开的Realm实例以避免系统资源泄漏”,为完成该任务,我使用了“ Application.ActivityLifecycleCallbacks”,您可以看到。
最后,当我完成对应用程序的同步时,我将触发一个接收器,然后在同步结束时它将调用“ IEndSyncCallback”“ onEndSync”方法,在该方法中,我是否查看特定的Activity类我的ActivityBackStack列表,因为如果我已经在应用程序中传递了这一点,则需要执行一些操作。
仅此而已,希望对您有所帮助。见你:)
答案 9 :(得分:0)
为了向后兼容:
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;
}
答案 10 :(得分:0)
您可以使用此 Class 进行灵活的生命周期处理
用法:
//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)
答案 11 :(得分:-1)
waqas716 的答案很好。我为特定案例创建了一个解决方法,需要更少的代码和维护。
我找到了一个具体的工作,通过静态方法从我怀疑在前台的活动中获取视图。 您可以遍历所有活动并检查您是否希望或从 martin的答案中获取活动名称
ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
ComponentName cn = am.getRunningTasks(1).get(0).topActivity;
然后检查视图是否为null并通过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"));
}
答案 12 :(得分:-2)
我不喜欢任何其他答案。 ActivityManager不用于获取当前活动。超级分类和依赖onDestroy也很脆弱,而不是最好的设计。
老实说,到目前为止我提出的最好的方法就是在我的应用程序中维护一个枚举,它在创建活动时被设置。
另一个建议可能是尽可能避免使用多个活动。这可以通过使用片段或在我的偏好自定义视图中完成。
答案 13 :(得分:-3)
一个相当简单的解决方案是创建一个单例管理器类,您可以在其中存储对一个或多个活动的引用,或者您希望在整个应用程序中访问的任何其他内容。
在主要活动的onCreate中调用UberManager.getInstance().setMainActivity( activity );
。
在应用中的任意位置拨打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;
}
}
答案 14 :(得分:-7)
我好像已经晚了三年但是无论如何我都会回答它,以防有人发现这个就像我一样。
我通过简单地使用它来解决这个问题:
if (getIntent().toString().contains("MainActivity")) {
// Do stuff if the current activity is MainActivity
}
请注意,“getIntent()。toString()”包含许多其他文本,例如您的包名称以及您的活动的任何意图过滤器。从技术上讲,我们正在检查当前的意图,而不是活动,但结果是一样的。只需使用例如Log.d(“test”,getIntent()。toString());如果你想看到所有的文字。这个解决方案有点hacky,但它在代码中更清晰,功能也相同。