如何确定Android Service 是不是在前台运行?

Posted

技术标签:

【中文标题】如何确定Android Service 是不是在前台运行?【英文标题】:How to determine if an Android Service is running in the foreground?如何确定Android Service 是否在前台运行? 【发布时间】:2011-09-21 02:26:24 【问题描述】:

我有一个我认为在前台运行的服务,我如何检查我的实现是否正常工作?

【问题讨论】:

【参考方案1】:
public static boolean isServiceRunningInForeground(Context context, Class<?> serviceClass) 
      ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
      for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) 
         if (serviceClass.getName().equals(service.service.getClassName())) 
            if (service.foreground) 
               return true;
            

         
      
      return false;
   

【讨论】:

我发现此答案中的代码比已接受答案中的代码更简洁,并且与已接受的答案不同,即使有超过 50 个服务正在运行,它也能正常工作。 与接受的相同,但更清晰、更短、更简单。还要检查所有服务,不仅仅是 50。 这里唯一的问题是“从 Oreo 开始,此方法不再适用于第三方应用程序。为了向后兼容,它仍将返回调用者自己的服务。” 如果我想在 android O 中做同样的事情怎么办? getRunningServices 在 Android 9 中已弃用【参考方案2】:
private boolean isServiceRunning(String serviceName)
    boolean serviceRunning = false;
    ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
    List<ActivityManager.RunningServiceInfo> l = am.getRunningServices(50);
    Iterator<ActivityManager.RunningServiceInfo> i = l.iterator();
    while (i.hasNext()) 
        ActivityManager.RunningServiceInfo runningServiceInfo = i
                .next();

        if(runningServiceInfo.service.getClassName().equals(serviceName))
            serviceRunning = true;

            if(runningServiceInfo.foreground)
            
                //service run in foreground
            
        
    
    return serviceRunning;

如果您想知道您的服务是否在前台运行,只需打开其他一些胖应用程序,然后检查服务是否仍在运行或检查标志 service.foreground

【讨论】:

谢谢,效果很好!我只需要添加这一行: serviceInForeground = runningServiceInfo.foreground; onDestroy() 中的 stopForeground(true) 怎么样?这不会阻止服务在前台运行吗? @user811985 仅供参考,RunningServiceInfo.foreground 上的文档指出:“如果服务已要求作为前台进程运行,则设置为 true。”。也就是说,它不会告诉你 android 是否真的接受了前台服务。 developer.android.com/reference/android/app/… 不幸的是,GetRunningServices 现在被标记为已弃用【参考方案3】:

更有效的答案变体:https://***.com/a/36127260/1275265

public static boolean isServiceRunningInForeground(Context context, Class<?> serviceClass) 
   ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
   for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) 
      if (serviceClass.getName().equals(service.service.getClassName())) 
         return service.foreground;
      
   
   return false;

【讨论】:

【参考方案4】:

从 API 26 开始,getRunningService() 已弃用。

现在的一个解决方案是将您的活动绑定到您的服务。然后您可以从您的 Activity 中调用您的 Service 的方法,以检查它是否正在运行。

1 - 在您的 Service 中,创建一个扩展 Binder 并返回您的 Service 的类

  public class LocalBinder extends Binder 
        MyService getService() 
            return MyService.this;
        
    

2 - 在您的服务中,声明活页夹

private final IBinder binder = new LocalBinder();

3 - 在您的 Service 中,实现 onBind(),这将返回 Binder

  @Nullable
    @Override
    public IBinder onBind(Intent intent) 
        return binder;
    

4 - 在您的服务中,创建一个检查它是否正在运行的方法(例如检查变量是否已初始化)

  public boolean isRunning() 
        // If running
            return true;
        // If not running
            return false;
        
    

5 - 在您的 Activity 中,创建一个保存您的服务的变量

private MyService myService;

6 - 现在,在您的 Activity 中,您可以绑定到您的服务

private void checkIfEnabled() 
    ServiceConnection connection = new ServiceConnection() 

        @Override
        public void onServiceConnected(ComponentName className,
                                       IBinder service) 
            MyService.LocalBinder binder = (MyService.LocalBinder) service;
            myService = binder.getService();
            
            // Calling your service public method
            if(myService.isRunning()) 
                // Your service is enabled
             else 
                // Your service is disabled
            
        

        @Override
        public void onServiceDisconnected(ComponentName arg0) 

        
    ;

    // Bind to MyService
    Intent intent = new Intent(this, MyService.class);
    bindService(intent, connection, Context.BIND_AUTO_CREATE);

欲了解更多信息,请查看官方文档中的Bound services overview。

【讨论】:

【参考方案5】:

这适用于我在 Coinverse 应用程序中获取加密新闻。

这是最简洁的 Kotlin 解决方案。感谢Abbas Naqdi 在此GitHub issue。

@Suppress("DEPRECATION") // Deprecated for third party Services.
fun <T> Context.isServiceRunning(service: Class<T>) =
        (getSystemService(ACTIVITY_SERVICE) as ActivityManager)
            .getRunningServices(Integer.MAX_VALUE)
            .any  it.service.className == service.name 

【讨论】:

如果您需要停止服务,这是 Android 9.0 的 latest implementation。 问题是关于前台运行的服务。所以你也应该检查it.foreground【参考方案6】:

对亚当的回答稍作改动:

@Suppress("DEPRECATION") // Deprecated for third party Services.
fun <T> Context.isServiceForegrounded(service: Class<T>) =
    (getSystemService(ACTIVITY_SERVICE) as? ActivityManager)
        ?.getRunningServices(Integer.MAX_VALUE)
        ?.find  it.service.className == service.name 
        ?.foreground == true

【讨论】:

以上是关于如何确定Android Service 是不是在前台运行?的主要内容,如果未能解决你的问题,请参考以下文章

Service初涉

Android入门第42天-Android中的Service(IntentService)

Android:如何确定 IntentService 是不是正在运行?

如何确定Android应用程序是不是被强制关闭?

如何通过经纬度确定位置 知道经纬度怎么查询实际地点?

如何确定我的 android 应用程序是不是存在内存泄漏?