检查 Activity 是不是从 Service 运行

Posted

技术标签:

【中文标题】检查 Activity 是不是从 Service 运行【英文标题】:Check if Activity is running from Service检查 Activity 是否从 Service 运行 【发布时间】:2012-08-23 17:14:37 【问题描述】:

Service 如何检查其应用程序的Activity 之一是否在前台运行?

【问题讨论】:

这个问题不太合理,因为我不确定我是否理解它的动机或用例?每当服务进入前台/后台时,您都可以绑定和取消绑定,只需在 onPause/onResume 等处进行适当的调用,这似乎是更基本的潜在问题的 hackier 解决方案。 我的服务运行时间比活动长得多,它只是需要识别活动是否正在运行的操作之一。服务终止并且可以通过系统广播事件重新调用。然后是服务检查活动是否正在运行。 我有同样的问题:推送接收服务需要在应用上弹出通知或某种弹出窗口之间做出决定 【参考方案1】:

将以下方法与您的包名称一起使用。如果您的任何活动在前台,它将返回 true。

public boolean isForeground(String myPackage) 
    ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
    List<ActivityManager.RunningTaskInfo> runningTaskInfo = manager.getRunningTasks(1); 
    ComponentName componentInfo = runningTaskInfo.get(0).topActivity;
    return componentInfo.getPackageName().equals(myPackage);

Update:

添加权限:

<uses-permission android:name="android.permission.GET_TASKS" />

【讨论】:

值得注意的是,您需要将 &lt;uses-permission android:name="android.permission.GET_TASKS" /&gt; 添加到清单中才能使其正常工作。 这个答案是针对包的。但问题是关于 Activity,如果条件必须检查 componentInfo.getClassName()。 GET_TASK 现已弃用。 此方法在 API 21 developer.android.com/reference/android/app/… 中已弃用 使用REAL_GET_TASKS 代替。【参考方案2】:

使用 SharedPreferences 将应用的状态保存在 onResume、onPause 等中。

像这样:

 @Override
public void onPause() 
    super.onPause();
    PreferenceManager.getDefaultSharedPreferences(this).edit().putBoolean("isActive", false).commit();


@Override
public void onDestroy() 
    super.onDestroy();
    PreferenceManager.getDefaultSharedPreferences(this).edit().putBoolean("isActive", false).commit();


@Override
public void onResume() 
    super.onResume();
    PreferenceManager.getDefaultSharedPreferences(this).edit().putBoolean("isActive", true).commit();

然后在服务中:

if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("isActive", false)) 
            return;

我同时使用了 onPause 和 onDestroy,因为有时它会直接跳转到 onDestroy :) 基本上都是巫术

无论如何, 希望对某人有所帮助

【讨论】:

谢谢@eiran。这是我发现的唯一可行的解​​决方案。 这应该是公认的答案,因为接受的一个使用弃用的一个【参考方案3】:

从 Lollipop 开始,getRunningTasks 已被弃用:

 * <p><b>Note: this method is only intended for debugging and presenting
 * task management user interfaces</b>.  This should never be used for
 * core logic in an application, such as deciding between different
 * behaviors based on the information found here.</p>
 *
 * @deprecated As of @link android.os.Build.VERSION_CODES#LOLLIPOP, this method
 * is no longer available to third party applications.

一种方法是在应用启动时绑定到服务。然后: 1. 如果您需要检查应用程序的任何活动是否正在运行,您可以为您的活动创建一个基类并覆盖 onPause 和 onResume。在 onPause 中,调用一个服务方法让它知道它在后台。在 onResume 中,调用一个服务方法让它知道它在前台。 2. 如果您只需要对某些特定活动执行此操作,只需覆盖这些活动的 onResume 和 onPause 或为这些活动创建基础活动。

【讨论】:

【参考方案4】:

Erian 有正确答案,但使用“getDefaultSharedPreferences”并不安全。当您启动服务时,它使用与 Activity 不同的实例。活动中偏好的任何更改,都不会更新服务中的默认共享偏好。所以我将使用“.getSharedPreferences”更改 Erian 代码,如下所示:

活动中:

    @Override
    public void onPause() 
        super.onPause();
        getApplicationContext().getSharedPreferences("preferences", MODE_MULTI_PROCESS).edit().putBoolean("isActive", false).commit();;
    

    @Override
    public void onDestroy() 
        super.onDestroy();
        getApplicationContext().getSharedPreferences("preferences", MODE_MULTI_PROCESS).edit().putBoolean("isActive", false).commit();
    

    @Override
    public void onResume() 
        super.onResume();
        getApplicationContext().getSharedPreferences("preferences", MODE_MULTI_PROCESS).edit().putBoolean("isActive", false).commit();
    

服务中:

    if (getApplicationContext().getSharedPreferences("preferences", MODE_MULTI_PROCESS).getBoolean("isActive", false)) 
        return;
    

【讨论】:

onResume 需要为“true” 谢谢!这是一个可喜的变化,我什至没有考虑过多个流程:D【参考方案5】:

上面的大多数答案都有一个缺陷,如果您的活动具有触发顶部另一个活动的某些功能,例如发送电子邮件

topActivity 不会返回您的包名,而是返回 Android 活动选择器包名。

因此,最好检查baseActivity 而不是topActivity

public boolean isMainActivityRunning(String packageName) 
    ActivityManager activityManager = (ActivityManager) getSystemService (Context.ACTIVITY_SERVICE);
    List<RunningTaskInfo> tasksInfo = activityManager.getRunningTasks(Integer.MAX_VALUE); 

    for (int i = 0; i < tasksInfo.size(); i++) 
        if (tasksInfo.get(i).baseActivity.getPackageName().toString().equals(packageName)
            return true;
    

    return false;
 

【讨论】:

【参考方案6】:

使用 Android 架构组件,检查这一点非常简单

annotationProcessor 'android.arch.lifecycle:compiler:1.1.1'
implementation 'android.arch.lifecycle:extensions:1.1.1'

生命周期观察者类,保留一个 pref 标志

public class AppLifecycleObserver implements LifecycleObserver 

public static final String TAG = "AppLifecycleObserver";

@OnLifecycleEvent(Lifecycle.Event.ON_START)
void onEnterForeground() 
    Log.d(TAG, "onEnterForeground");
    PreferencesUtils.save(Constants.IN_FOREGROUND, true);


@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
void onEnterBackground() 
    Log.d(TAG, "onEnterBackground");
    PreferencesUtils.save(Constants.IN_FOREGROUND, false);
  

应用程序类观察生命周期

public class App extends Application 


private static App instance;

public static App getInstance() 
    return instance;


@Override
public void onCreate() 
    super.onCreate();

    AppLifecycleObserver appLifecycleObserver = new AppLifecycleObserver();
    ProcessLifecycleOwner.get().getLifecycle().addObserver(appLifecycleObserver);

现在,您可以使用 Pref 标志在您喜欢的任何地方进行检查。

【讨论】:

【参考方案7】:

getRunningTasks() 已弃用

getRunningTask() 已被 android 弃用,现在我们可以使用 getRunningAppProcesses()。这将返回一个列表或RunningAppProcessInfo,我们可以在其中检查第一个进程的importance

更多详情请查看官方文档:https://developer.android.com/reference/android/app/ActivityManager#getRunningAppProcesses()

代码:

 public boolean isAppInForeground() 
        ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> runningTaskInfo = manager.getRunningAppProcesses();
        if (runningTaskInfo.size() > 0)
            return runningTaskInfo.get(0).importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
        return false; // no running process
    

【讨论】:

【参考方案8】:

我认为您可以在 Android 上 getRunninTasks 并检查您的包名是否正在运行任务。

public boolean isServiceRunning()  

ActivityManager activityManager = (ActivityManager)Monitor.this.getSystemService (Context.ACTIVITY_SERVICE); 
List<RunningTaskInfo> services = activityManager.getRunningTasks(Integer.MAX_VALUE); 
isServiceFound = false; 
for (int i = 0; i < services.size(); i++)  
    if (services.get(i).topActivity.toString().equalsIgnoreCase("ComponentInfocom.lyo.AutoMessage/com.lyo.AutoMessage.TextLogList")) 
        isServiceFound = true;
    
 
return isServiceFound; 
 

【讨论】:

它是用于检查服务是否处于活动状态......而不是用于检查活动是否正在工作。【参考方案9】:

使用以下方法获取当前activity的全类名(包+类名),并检查是否等于你想要的activity的全类名(包+类名):

 public String getCurrentClass() 

    ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
    List<ActivityManager.RunningTaskInfo> runningTaskInfo = manager.getRunningTasks(1);

    ComponentName componentInfo = runningTaskInfo.get(0).topActivity;
    String className = componentInfo.getClassName();
    return className;
 

【讨论】:

欢迎您,仅供参考,这不是博客,您的回答与之前的回答几乎相同。我建议你看看帮助部分:***.com/help/answering

以上是关于检查 Activity 是不是从 Service 运行的主要内容,如果未能解决你的问题,请参考以下文章

android中怎样动态的将数据从service上传递到activity

Android:将参数从Activity传递给Service

从 Service 向 Activity 发送简单消息

如何从后台service传递数据到前台正在运行的activity

如何在 Kotlin 中将数据从 Service 传递到 Activity?

关于android编程中service和activity的区别