如何检查服务是否在Android上运行?

如何检查服务是否在Android上运行?,android,android-service,Android,Android Service,如何检查后台服务是否正在运行 我想要一个Android活动来切换服务的状态——它让我在关闭时打开它,在打开时关闭它。不久前我也遇到过同样的问题。因为我的服务是本地的,所以我最终只使用服务类中的一个静态字段来切换状态,正如hackbod所描述的那样 编辑(记录): 以下是hackbod提出的解决方案: 如果您的客户端和服务器代码是同一.apk的一部分,那么您是 绑定到具有具体意图的服务(指定 精确的服务类),然后您只需将服务设置为 全局变量,当它运行时,您的客户端可以检查它 我们故意没有API来检

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


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

不久前我也遇到过同样的问题。因为我的服务是本地的,所以我最终只使用服务类中的一个静态字段来切换状态,正如hackbod所描述的那样

编辑(记录):

以下是hackbod提出的解决方案:

如果您的客户端和服务器代码是同一.apk的一部分,那么您是 绑定到具有具体意图的服务(指定 精确的服务类),然后您只需将服务设置为 全局变量,当它运行时,您的客户端可以检查它

我们故意没有API来检查服务是否可用 跑步是因为,几乎没有失败,当你想做某事的时候 这样,代码中就有了竞争条件

您可以使用这个(我还没有尝试过,但我希望它能起作用):

如果已有正在运行的服务,startService方法将返回ComponentName对象。否则,将返回null


我认为这与检查不同,因为它正在启动服务,所以您可以添加
stopService(someIntent)在代码下。

onDestroy
并不总是在服务中调用,因此这是无用的

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

明白了

您必须调用
startService()
才能正确注册您的服务,仅通过
BIND\u AUTO\u 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;
     }
}
公共类服务工具{
私有静态字符串LOG_TAG=ServiceTools.class.getName();
公共静态布尔IServiceRunning(字符串serviceClassName){
最终ActivityManager ActivityManager=(ActivityManager)Application.getContext().getSystemService(Context.ACTIVITY_服务);
最终列表服务=activityManager.getRunningServices(Integer.MAX_值);
for(RunningServiceInfo RunningServiceInfo:services){
if(runningServiceInfo.service.getClassName().equals(serviceClassName)){
返回true;
}
}
返回false;
}
}

首先,您不应该使用。(讨论)

服务可以独立运行,也可以绑定到活动,或者两者都可以。检查活动中服务是否正在运行的方法是创建一个接口(扩展Binder),在该接口中声明
活动
服务
都能理解的方法。您可以在声明的地方创建自己的接口,例如“
isServiceRunning()
”,来实现这一点。 然后可以将活动绑定到服务,运行方法isServiceRunning(),服务将检查自身是否正在运行,并为活动返回布尔值


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

我在活动中使用以下方法:

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;
}
这是可靠的,因为它基于Android操作系统通过提供的有关运行服务的信息

所有使用onDestroy或onSometing事件、binder或静态变量的方法都无法可靠地工作,因为作为开发人员,您永远不知道Android何时决定终止您的进程,或者所提到的回调调用与否。请注意Android文档中的“killable”列。

一个小补充是:

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

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

因此,正如miracle2k所建议的,最好是在服务类中有一个静态字段,以了解服务是否已启动

为了使它更干净,我建议在一个单例中使用非常非常懒惰的抓取来转换服务:也就是说,没有通过静态方法对所有实例进行实例化。服务/singleton的静态getInstance方法仅返回已创建的singleton实例。但它实际上并没有启动或实例化singleton本身。该服务仅通过正常的服务启动方法启动

然后,修改singleton设计模式,将混乱的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。

这更适用于意向服务调试,因为它们会生成线程,但也可能适用于常规服务。多亏了宾果,我找到了这根线


在我的例子中,我使用了调试器并找到了线程视图。它看起来有点像MS Word中的圆点图标。无论如何,您不必在调试器模式下使用它。单击流程并单击该按钮。任何Intent服务都将在运行时显示,至少在模拟器上显示。

我只想在@Snicolas的回答中添加一条注释。以下步骤可用于在调用/不调用
ondestory()
的情况下检查停止服务

  • ondestory()
    调用:转到设置->应用程序->运行服务->选择并停止服务

  • ondestory()
    未调用:转到设置->应用程序->管理应用程序->选择
    isMyServiceRunning(MyService.class)
    
    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
    
    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
    
    @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;
    }
    
    /**
     * 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;
    }
    
    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);
    }
    
     public static Boolean serviceRunning = false;
    
     public int onStartCommand(Intent intent, int flags, int startId) {
    
        serviceRunning = true;
        ...
    }
    
     @Override
    public void onDestroy()
    {
        serviceRunning = false;
    
    } 
    
    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;
    }
    
    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);
    
    @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"));
        }
    }
    
        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;   
            }
        }
    
    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;
                }
            }
        };
    }
    
    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.
    
    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);
    
     public final void bindApplication(...) {
    
            if (services != null) {
                // Setup the service cache in the ServiceManager
                ServiceManager.initServiceCache(services);
            }
    
     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();
    
    /**
     * 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 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;
    }
    
        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(...);
        }
    
    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)
    
    class MyService : Service() {
        override fun onCreate() {
            super.onCreate()
            isServiceStarted = true
        }
        override fun onDestroy() {
            super.onDestroy()
            isServiceStarted = false
        }
        companion object {
            var isServiceStarted = false
        }
    }
    
    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)
            }
        }
    }
    
    private fun isMyServiceRunning(serviceClass: Class<out Service>) =
        (getSystemService(ACTIVITY_SERVICE) as ActivityManager)
            .getRunningServices(Int.MAX_VALUE)
            ?.map { it.service.className }
            ?.contains(serviceClass.name) ?: false
    
    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;
        }
    
    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
    }
    
    companion object{
         var isRuning = false
    
    }
    
     override fun onCreate() {
            super.onCreate()
            isRuning = true
        }
    
    override fun onDestroy() {
        super.onDestroy()
        isRuning = false
        }
    
    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 }
    }
    
    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)
    
    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.