1025

如何检查后台服务是否正在运行?

我想要一个切换服务状态的 Android 活动——它让我在它关闭时打开它,如果它打开则关闭它。

4

32 回答 32

1759

我在活动中使用以下内容:

private boolean isMyServiceRunning(Class<?> serviceClass) {
    ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (serviceClass.getName().equals(service.service.getClassName())) {
            return true;
        }
    }
    return false;
}

我称之为:

isMyServiceRunning(MyService.class)

这很可靠,因为它基于 Android 操作系统通过ActivityManager#getRunningServices提供的有关运行服务的信息。

所有使用 onDestroy 或 onSometing 事件或 Binder 或静态变量的方法都不会可靠地工作,因为作为开发人员,您永远不知道 Android 何时决定终止您的进程或调用或不调用哪个回调。请注意Android 文档中生命周期事件表中的“可杀死”列。

于 2011-05-07T12:54:46.370 回答
311

不久前我遇到了同样的问题。由于我的服务是本地的,我最终只是使用服务类中的静态字段来切换状态,如 hackbod所述

编辑(备案):

这是hackbod提出的解决方案:

如果您的客户端和服务器代码是同一个 .apk 的一部分,并且您使用具体的 Intent(指定确切服务类的意图)绑定到服务,那么您可以简单地让您的服务在运行时设置一个全局变量您的客户可以检查。

我们故意没有 API 来检查服务是否正在运行,因为几乎没有失败,当您想做类似的事情时,您的代码中会出现竞争条件。

于 2009-03-03T22:58:35.127 回答
80

知道了!

必须要求startService()您的服务正确注册并且通过是BIND_AUTO_CREATE不够的。

Intent bindIntent = new Intent(this,ServiceTask.class);
startService(bindIntent);
bindService(bindIntent,mConnection,0);

现在是 ServiceTools 类:

public class ServiceTools {
    private static String LOG_TAG = ServiceTools.class.getName();

    public static boolean isServiceRunning(String serviceClassName){
        final ActivityManager activityManager = (ActivityManager)Application.getContext().getSystemService(Context.ACTIVITY_SERVICE);
        final List<RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);

        for (RunningServiceInfo runningServiceInfo : services) {
            if (runningServiceInfo.service.getClassName().equals(serviceClassName)){
                return true;
            }
        }
        return false;
     }
}
于 2011-02-12T04:42:52.107 回答
62

一个小的补充是:

我的目标是知道一个服务是否正在运行,如果它没有运行,它实际上没有运行它。

调用 bindService 或调用可以被服务捕获的意图不是一个好主意,因为如果服务没有运行,它将启动服务。

所以,正如miracle2k建议的那样,最好在服务类中有一个静态字段来知道服务是否已经启动。

为了更简洁,我建议将服务转换为单例,并使用非常非常懒惰的获取:也就是说,完全没有通过静态方法对单例实例进行实例化。您的服务/单例的静态 getInstance 方法仅返回单例的实例(如果已创建)。但它实际上并没有启动或实例化单例本身。该服务仅通过正常的服务启动方法启动。

然后修改单例设计模式以将令人困惑的 getInstance 方法重命名为类似isInstanceCreated() : boolean方法的名称会更加简洁。

代码将如下所示:

public class MyService extends Service
{
   private static MyService instance = null;

   public static boolean isInstanceCreated() {
      return instance != null;
   }//met

   @Override
   public void onCreate()
   {
      instance = this;
      ....
   }//met

   @Override
   public void onDestroy()
   {
      instance = null;
      ...
   }//met
}//class

此解决方案很优雅,但仅当您有权访问服务类并且仅适用于服务的应用程序/包之外的类时才有意义。如果您的类在服务应用程序/包之外,那么您可以使用 Pieter-Jan Van Robays 强调的限制查询 ActivityManager。

于 2011-05-20T10:58:23.227 回答
32

您可以使用它(我还没有尝试过,但我希望它有效):

if(startService(someIntent) != null) {
    Toast.makeText(getBaseContext(), "Service is already running", Toast.LENGTH_SHORT).show();
}
else {
    Toast.makeText(getBaseContext(), "There is no service running, starting service..", Toast.LENGTH_SHORT).show();
}

如果有一个已经在运行的服务,startService 方法会返回一个 ComponentName 对象。如果不是,则返回 null。

请参阅公共抽象 ComponentName startService(意图服务)

这不像是我认为的检查,因为它是启动服务,所以你可以stopService(someIntent);在代码下添加。

于 2010-09-23T17:01:57.360 回答
28
/**
 * Check if the service is Running 
 * @param serviceClass the class of the Service
 *
 * @return true if the service is running otherwise false
 */
public boolean checkServiceRunning(Class<?> serviceClass){
    ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
    for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE))
    {
        if (serviceClass.getName().equals(service.service.getClassName()))
        {
            return true;
        }
    }
    return false;
}
于 2014-07-14T03:23:52.953 回答
24

Android文档的摘录:

sendBroadcast(Intent)类似,但如果 Intent 有任何接收者,此函数将阻塞并在返回之前立即分派它们。

将此 hack 视为“ping”Service . 由于我们可以同步广播,我们可以在 UI 线程上同步广播并获得结果。

Service

@Override
public void onCreate() {
   LocalBroadcastManager
     .getInstance(this)
     .registerReceiver(new ServiceEchoReceiver(), new IntentFilter("ping"));
     //do not forget to deregister the receiver when the service is destroyed to avoid
     //any potential memory leaks 
}

private class ServiceEchoReceiver extends BroadcastReceiver {
    public void onReceive (Context context, Intent intent) {
      LocalBroadcastManager
         .getInstance(this)
         .sendBroadcastSync(new Intent("pong"));
    }
}

Activity

    bool serviceRunning = false;

    protected void onCreate (Bundle savedInstanceState){
        LocalBroadcastManager.getInstance(this).registerReceiver(pong, new IntentFilter("pong"));
        LocalBroadcastManager.getInstance(this).sendBroadcastSync(new Intent("ping"));
        if(!serviceRunning){
           //run the service
        }
    }

    private BroadcastReceiver pong = new BroadcastReceiver(){
        public void onReceive (Context context, Intent intent) {
          serviceRunning = true;   
        }
    }

在许多应用程序中,赢家当然是设置为trueinService.onCreate()和 to falsein的服务上的静态布尔字段,Service.onDestroy()因为它要简单得多。

于 2016-09-19T17:48:29.593 回答
15

检查服务是否正在运行的正确方法是简单地询问它。在您的服务中实现一个 BroadcastReceiver 来响应来自您的活动的 ping。服务启动时注册BroadcastReceiver,服务销毁时注销。从您的活动(或任何组件)中,向服务发送本地广播意图,如果它响应,您就知道它正在运行。请注意下面代码中 ACTION_PING 和 ACTION_PONG 之间的细微差别。

public class PingableService extends Service {
    public static final String ACTION_PING = PingableService.class.getName() + ".PING";
    public static final String ACTION_PONG = PingableService.class.getName() + ".PONG";

    public int onStartCommand (Intent intent, int flags, int startId) {
        LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, new IntentFilter(ACTION_PING));
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy () {
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
        super.onDestroy();
    }

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive (Context context, Intent intent) {
            if (intent.getAction().equals(ACTION_PING)) {
                LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getApplicationContext());
                manager.sendBroadcast(new Intent(ACTION_PONG));
            }
        }
    };
}

public class MyActivity extends Activity {
    private boolean isSvcRunning = false;

    @Override
    protected void onStart() {
        LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getApplicationContext());
        manager.registerReceiver(mReceiver, new IntentFilter(PingableService.ACTION_PONG));
        // the service will respond to this broadcast only if it's running
        manager.sendBroadcast(new Intent(PingableService.ACTION_PING));
        super.onStart();
    }

    @Override
    protected void onStop() {
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
        super.onStop();
    }

    protected BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive (Context context, Intent intent) {
            // here you receive the response from the service
            if (intent.getAction().equals(PingableService.ACTION_PONG)) {
                isSvcRunning = true;
            }
        }
    };
}
于 2016-10-29T20:15:06.563 回答
13

我稍微修改了上面介绍的解决方案之一,但传递了类而不是通用字符串名称,以确保比较来自同一方法的字符串class.getName()

public class ServiceTools {
    private static String LOG_TAG = ServiceTools.class.getName();

    public static boolean isServiceRunning(Context context,Class<?> serviceClass){
        final ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
        final List<RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);

        for (RunningServiceInfo runningServiceInfo : services) {
            Log.d(Constants.TAG, String.format("Service:%s", runningServiceInfo.service.getClassName()));
            if (runningServiceInfo.service.getClassName().equals(serviceClass.getName())){
                return true;
            }
        }
        return false;
    }
}

进而

Boolean isServiceRunning = ServiceTools.isServiceRunning(
                    MainActivity.this.getApplicationContext(),
                    BackgroundIntentService.class);
于 2016-07-13T14:26:04.143 回答
13

使用 kotlin 的另一种方法。受到其他用户回答的启发

fun isMyServiceRunning(serviceClass: Class<*>): Boolean {
    val manager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
    return manager.getRunningServices(Integer.MAX_VALUE)
            .any { it.service.className == serviceClass.name }
}

作为 kotlin 扩展

fun Context.isMyServiceRunning(serviceClass: Class<*>): Boolean {
    val manager = this.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
    return manager.getRunningServices(Integer.MAX_VALUE)
            .any { it.service.className == serviceClass.name }
}

用法

context.isMyServiceRunning(MyService::class.java)
于 2019-10-16T01:26:17.447 回答
9

我只想在@Snicolas 的答案中添加注释。以下步骤可用于检查是否调用停止服务onDestroy()

  1. onDestroy()调用:转到设置 -> 应用程序 -> 运行服务 -> 选择并停止您的服务。

  2. onDestroy()未调用:转到设置 -> 应用程序 -> 管理应用程序 -> 选择并“强制停止”您的服务正在其中运行的应用程序。但是,由于您的应用程序在这里停止,所以服务实例肯定也会停止。

最后,我想提一下,那里提到的在单例类中使用静态变量的方法对我有用。

于 2012-09-16T16:54:06.190 回答
8

onDestroy并不总是在服务中调用,所以这是没用的!

例如:只需在 Eclipse 中进行一次更改,再次运行该应用程序。使用 SIG: 9 强制退出应用程序。

于 2011-02-12T04:26:54.580 回答
8

首先,您不应该使用ActivityManager. (在这里讨论)

服务可以单独运行,也可以绑定到 Activity 或两者兼而有之。如果您的 Service 正在运行,则检查 Activity 的方法是创建一个接口(扩展 Binder),在该接口中声明 theActivity和 the都Service可以理解的方法。您可以通过在您声明的地方创建自己的接口来做到这一点,例如“ isServiceRunning()”。然后,您可以将您的 Activity 绑定到您的服务,运行 isServiceRunning() 方法,服务将检查自己是否正在运行,并向您的 Activity 返回一个布尔值。

您还可以使用此方法停止您的服务或以其他方式与之交互。

于 2011-03-30T14:56:30.447 回答
8

同样,如果人们使用待处理的意图,人们可能会发现另一种更清洁的选择(例如AlarmManager

public static boolean isRunning(Class<? extends Service> serviceClass) {
    final Intent intent = new Intent(context, serviceClass);
    return (PendingIntent.getService(context, CODE, intent, PendingIntent.FLAG_NO_CREATE) != null);
}

WhereCODE是您在类中私下定义的常量,用于标识与您的服务关联的待处理意图。

于 2014-08-06T23:41:37.983 回答
8

下面是一个优雅的 hack,涵盖了所有Ifs. 这仅适用于本地服务。

    public final class AService extends Service {

        private static AService mInstance = null;

        public static boolean isServiceCreated() {
            try {
                // If instance was not cleared but the service was destroyed an Exception will be thrown
                return mInstance != null && mInstance.ping();
            } catch (NullPointerException e) {
                // destroyed/not-started
                return false;
            }
        }

        /**
         * Simply returns true. If the service is still active, this method will be accessible.
         * @return
         */
        private boolean ping() {
            return true;
        }

        @Override
        public void onCreate() {
            mInstance = this;
        }

        @Override
        public void onDestroy() {
            mInstance = null;
        }
    }

然后稍后:

    if(AService.isServiceCreated()){
        ...
    }else{
        startService(...);
    }
于 2018-01-19T14:08:18.150 回答
7

Xamarin C# 版本:

private bool isMyServiceRunning(System.Type cls)
{
    ActivityManager manager = (ActivityManager)GetSystemService(Context.ActivityService);

    foreach (var service in manager.GetRunningServices(int.MaxValue)) {
        if (service.Service.ClassName.Equals(Java.Lang.Class.FromType(cls).CanonicalName)) {
            return true;
        }
    }
    return false;
}
于 2016-06-13T19:00:22.793 回答
6

对于这里给出的用例,我们可以简单地使用stopService()方法的返回值。true如果存在指定的服务并被杀死,则返回。否则返回false。因此,如果结果是,您可以重新启动服务,false否则可以确保当前服务已停止。:) 如果你看看这个会更好。

于 2013-05-28T09:55:23.910 回答
3

geekQ 的响应,但在 Kotlin 类中。感谢极客Q

fun isMyServiceRunning(serviceClass : Class<*> ) : Boolean{
    var manager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
    for (service in manager.getRunningServices(Integer.MAX_VALUE)) {
        if (serviceClass.name.equals(service.service.className)) {
            return true
        }
    }
    return false
}

通话

isMyServiceRunning(NewService::class.java)
于 2018-03-23T21:43:10.453 回答
3

在您的服务子类中使用静态布尔值来获取服务的状态,如下所示。

我的服务.kt

class MyService : Service() {
    override fun onCreate() {
        super.onCreate()
        isServiceStarted = true
    }
    override fun onDestroy() {
        super.onDestroy()
        isServiceStarted = false
    }
    companion object {
        var isServiceStarted = false
    }
}

MainActivity.kt

class MainActivity : AppCompatActivity(){
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val serviceStarted = FileObserverService.isServiceStarted
        if (!serviceStarted) {
            val startFileObserverService = Intent(this, FileObserverService::class.java)
            ContextCompat.startForegroundService(this, startFileObserverService)
        }
    }
}
于 2019-02-08T13:05:01.223 回答
3

对于 kotlin,您可以使用以下代码。

fun isMyServiceRunning(calssObj: Class<SERVICE_CALL_NAME>): Boolean {
    val manager = requireActivity().getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
    for (service in manager.getRunningServices(Integer.MAX_VALUE)) {
        if (calssObj.getName().equals(service.service.getClassName())) {
            return true
        }
    }
    return false
}
于 2019-07-24T06:29:38.110 回答
2

在 TheServiceClass 内部定义:

 public static Boolean serviceRunning = false;

然后在 onStartCommand(...)

 public int onStartCommand(Intent intent, int flags, int startId) {

    serviceRunning = true;
    ...
}

 @Override
public void onDestroy()
{
    serviceRunning = false;

} 

然后,if(TheServiceClass.serviceRunning == true)从任何班级打电话。

于 2015-10-23T18:35:09.317 回答
2

简单地使用绑定与不创建自动- 见 ps。并更新...

public abstract class Context {

 ... 

  /*
  * @return {true} If you have successfully bound to the service, 
  *  {false} is returned if the connection is not made 
  *  so you will not receive the service object.
  */
  public abstract boolean bindService(@RequiresPermission Intent service,
        @NonNull ServiceConnection conn, @BindServiceFlags int flags);

例子 :

    Intent bindIntent = new Intent(context, Class<Service>);
    boolean bindResult = context.bindService(bindIntent, ServiceConnection, 0);

为什么不使用?获取运行服务()

List<ActivityManager.RunningServiceInfo> getRunningServices (int maxNum)
Return a list of the services that are currently running.

注意:此方法仅用于调试或实现服务管理类型的用户界面。


附言。android 文档具有误导性,我在 google tracker 上打开了一个问题以消除任何疑问:

https://issuetracker.google.com/issues/68908332

正如我们所看到的,绑定服务实际上通过 ActivityManager 绑定器通过服务缓存绑定器调用事务 - 我试图跟踪哪个服务负责绑定,但我们可以看到绑定的结果是:

int res = ActivityManagerNative.getDefault().bindService(...);
return res != 0;

交易是通过活页夹进行的:

ServiceManager.getService("activity");

下一个:

  public static IBinder getService(String name) {
    try {
        IBinder service = sCache.get(name);
        if (service != null) {
            return service;
        } else {
            return getIServiceManager().getService(name);

这是通过以下方式在 ActivityThread 中设置的:

 public final void bindApplication(...) {

        if (services != null) {
            // Setup the service cache in the ServiceManager
            ServiceManager.initServiceCache(services);
        }

这在 ActivityManagerService 中的方法中调用:

 private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
    ...
    thread.bindApplication(... , getCommonServicesLocked(),...)

然后:

 private HashMap<String, IBinder> getCommonServicesLocked() {

但是没有“活动”只有窗口包和警报..

所以我们需要回去打电话:

 return getIServiceManager().getService(name);

    sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());

这通过以下方式拨打电话:

    mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);

这导致 :

BinderInternal.getContextObject()

这是本机方法....

  /**
     * Return the global "context object" of the system.  This is usually
     * an implementation of IServiceManager, which you can use to find
     * other services.
     */
    public static final native IBinder getContextObject();

我现在没有时间挖掘 c,所以在我剖析休息电话之前,我暂停我的回答。

但是检查服务是否正在运行的最佳方法是创建绑定(如果未创建绑定,则服务不存在)-并通过绑定查询服务的状态(使用存储在其状态上的内部标志)。

更新 23.06.2018

我发现那些很有趣:

/**
 * Provide a binder to an already-bound service.  This method is synchronous
 * and will not start the target service if it is not present, so it is safe
 * to call from {@link #onReceive}.
 *
 * For peekService() to return a non null {@link android.os.IBinder} interface
 * the service must have published it before. In other words some component
 * must have called {@link android.content.Context#bindService(Intent, ServiceConnection, int)} on it.
 *
 * @param myContext The Context that had been passed to {@link #onReceive(Context, Intent)}
 * @param service Identifies the already-bound service you wish to use. See
 * {@link android.content.Context#bindService(Intent, ServiceConnection, int)}
 * for more information.
 */
public IBinder peekService(Context myContext, Intent service) {
    IActivityManager am = ActivityManager.getService();
    IBinder binder = null;
    try {
        service.prepareToLeaveProcess(myContext);
        binder = am.peekService(service, service.resolveTypeIfNeeded(
                myContext.getContentResolver()), myContext.getOpPackageName());
    } catch (RemoteException e) {
    }
    return binder;
}

简而言之 :)

“为已绑定的服务提供绑定器。此方法是同步的,如果目标服务不存在,则不会启动它。”

public IBinder peekService(Intent service, String resolvedType, String callingPackage) 抛出 RemoteException;

*

public static IBinder peekService(IBinder remote, Intent service, String resolvedType)
             throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken("android.app.IActivityManager");
    service.writeToParcel(data, 0);
    data.writeString(resolvedType);
    remote.transact(android.os.IBinder.FIRST_CALL_TRANSACTION+84, data, reply, 0);
    reply.readException();
    IBinder binder = reply.readStrongBinder();
    reply.recycle();
    data.recycle();
    return binder;
}

*

于 2017-03-11T17:11:43.577 回答
2

在 kotlin 中,您可以在伴生对象中添加布尔变量,并从您想要的任何类中检查其值:

companion object{
     var isRuning = false

}

创建和销毁服务时更改它的值

 override fun onCreate() {
        super.onCreate()
        isRuning = true
    }

override fun onDestroy() {
    super.onDestroy()
    isRuning = false
    }
于 2019-08-04T04:47:20.740 回答
1

可以有多个具有相同类名的服务。

我刚刚创建了两个应用程序。第一个应用程序的包名称是com.example.mock. 我创建了一个lorem在应用程序中调用的子包和一个名为Mock2Service. 所以它的全称是com.example.mock.lorem.Mock2Service.

然后我创建了第二个应用程序和一个名为Mock2Service. 第二个应用的包名是com.example.mock.lorem. 服务的完全限定名称com.example.mock.lorem.Mock2Service也是 。

这是我的 logcat 输出。

03-27 12:02:19.985: D/TAG(32155): Mock-01: com.example.mock.lorem.Mock2Service
03-27 12:02:33.755: D/TAG(32277): Mock-02: com.example.mock.lorem.Mock2Service

一个更好的主意是比较ComponentName实例,因为equals()比较ComponentName包名和类名。并且不能在设备上安装两个具有相同包名称的应用程序。

的 equals() 方法ComponentName

@Override
public boolean equals(Object obj) {
    try {
        if (obj != null) {
            ComponentName other = (ComponentName)obj;
            // Note: no null checks, because mPackage and mClass can
            // never be null.
            return mPackage.equals(other.mPackage)
                    && mClass.equals(other.mClass);
        }
    } catch (ClassCastException e) {
    }
    return false;
}

组件名称

于 2014-03-27T08:11:45.283 回答
1

请使用此代码。

if (isMyServiceRunning(MainActivity.this, xyzService.class)) { // Service class name
    // Service running
} else {
    // Service Stop
}


public static boolean isMyServiceRunning(Activity activity, Class<?> serviceClass) {
        ActivityManager manager = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            if (serviceClass.getName().equals(service.service.getClassName())) {
                return true;
            }
        }
        return false;
    }
于 2019-04-09T08:46:35.890 回答
1

检测服务是否正在运行的唯一有效/最快/干净的方法是创建 PING/PONG 功能。

在服务中实现 Messenger 或 AIDL 方法:isAlive()- 返回服务的状态。

不要实施广播,因为它们可能会被错过

于 2020-08-10T09:57:05.177 回答
1

如果您有一个多模块应用程序,并且您想知道该服务是否正在运行,而该模块不依赖于包含该服务的模块,则可以使用此功能:

fun isServiceRunning(context: Context, serviceClassName: String): Boolean {

    val manager = ContextCompat.getSystemService(
        context,
        ActivityManager::class.java
    ) ?: return false

    return manager.getRunningServices(Integer.MAX_VALUE).any { serviceInfo ->
        serviceInfo.service.shortClassName.contains(vpnServiceClassName)
    }
}

服务用途MyService

isServiceRunning(context, "MyService")

如果服务类名称发生变化而调用函数没有相应变化,则该函数可能无法正常工作。

于 2021-12-06T06:46:12.577 回答
0

这更适用于 Intent Service 调试,因为它们会产生一个线程,但也可能适用于常规服务。感谢 Binging,我找到了这个帖子

就我而言,我使用了调试器并找到了线程视图。它有点像 MS Word 中的项目符号图标。无论如何,您不必处于调试器模式即可使用它。单击该过程,然后单击该按钮。任何 Intent 服务都会在它们运行时出现,至少在模拟器上是这样。

于 2012-08-03T20:32:49.850 回答
0

如果服务属于其他进程或 APK,则使用基于 ActivityManager 的解决方案。

如果您可以访问其源代码,只需使用基于静态字段的解决方案。但是我建议使用一个布尔值而不是使用一个 Date 对象。在服务运行时,只需将其值更新为“现在”,并在完成后将其设置为空。从活动中,您可以检查它是否为空或日期是否太旧,这意味着它没有运行。

您还可以从您的服务发送广播通知,指示该通知正在运行进一步的信息,如进度。

于 2013-08-04T11:14:41.827 回答
-1

ActivityManager::getRunningServices我对基于答案的 kotlin 转换。将此功能放入活动中-

private fun isMyServiceRunning(serviceClass: Class<out Service>) =
    (getSystemService(ACTIVITY_SERVICE) as ActivityManager)
        .getRunningServices(Int.MAX_VALUE)
        ?.map { it.service.className }
        ?.contains(serviceClass.name) ?: false
于 2019-03-15T13:58:37.593 回答
-5

伙计们,放轻松... :)

SharedPreferences我认为最合适的解决方案是在服务是否正在运行时保存一个键值对。

逻辑很直;在您的服务级别中的任何所需位置;放置一个布尔值,作为服务是否正在运行的标志。然后在应用程序中的任意位置读取此值。

我在我的应用程序中使用的示例代码如下:

在我的服务类(音频流的服务)中,我在服务启动时执行以下代码;

private void updatePlayerStatus(boolean isRadioPlaying)
{
        SharedPreferences sharedPref = this.getSharedPreferences(getString(R.string.str_shared_file_name), Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPref.edit();
        editor.putBoolean(getString(R.string.str_shared_file_radio_status_key), isRadioPlaying);
        editor.commit();
}

然后在我的应用程序的任何活动中,我都在以下代码的帮助下检查服务的状态;

private boolean isRadioRunning() {
        SharedPreferences sharedPref = this.getSharedPreferences(getString(R.string.str_shared_file_name), Context.MODE_PRIVATE);

        return sharedPref.getBoolean(getString(R.string.str_shared_file_radio_status_key), false);
}

没有特殊权限,没有循环......简单的方法,干净的解决方案:)

如果您需要更多信息,请参阅链接

希望这可以帮助。

于 2013-07-02T20:46:08.207 回答
-5

您可以使用 Android 开发人员选项中的此选项来查看您的服务是否仍在后台运行。

1. Open Settings in your Android device.
2. Find Developer Options.
3. Find Running Services option.
4. Find your app icon.
5. You will then see all the service that belongs to your app running in the background.
于 2019-11-06T16:58:33.670 回答