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

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

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

569138 次浏览

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

编辑(供记录):

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

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

我们故意没有API来检查服务是否存在跑步是因为,几乎没有失败,当你想做某事时就像你在代码中结束了竞争条件一样。

你可以使用这个(我还没有尝试过,但我希望这能奏效):

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();}

如果存在已在运行的服务,则start Service方法返回ComponentName对象。如果没有,将返回null。

公共抽象组件名称start Service

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

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

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

抓到了!

必须呼叫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;}}

首先,您不应该使用ActivityManager来访问服务。(讨论这里

服务可以自己运行,也可以绑定到活动,或者两者兼而有之。如果你的服务正在运行,签入活动的方法是创建一个接口(扩展Binder),在那里你声明ActivityService都理解的方法。你可以通过制作自己的接口来做到这一点,例如声明“isServiceRunning()”。然后,您可以将您的活动绑定到您的服务,运行方法isServiceRrun(),服务将自行检查它是否正在运行并向您的活动返回一个布尔值。

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

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

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操作系统通过活动管理器#获取正在运行的服务提供的服务的信息。

所有使用onDestroy或onSom的事件或Binders或静态变量的方法都不能可靠地工作,因为作为开发人员,你永远不知道Android何时决定终止你的进程,或者是否调用了哪些提到的回调。请注意Android留档生命周期事件表中的“可杀死”列。

一个小的补充是:

我的目标是知道一个服务正在运行,而不是实际运行它,如果它不运行。

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

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

为了使其更清晰,我建议使用非常非常懒惰的获取将服务转换为单例:也就是说,通过静态方法根本没有实例化单例实例。您的服务/单例的静态getInstance方法只是返回已创建的单例实例。但它实际上并没有启动或实例化单例本身。服务仅通过正常的服务启动方法启动。

然后,修改单例设计模式以将令人困惑的getInstance方法重命名为类似于isInstanceCreated() : boolean方法的东西会更清晰。

代码将如下所示:

public class MyService extends Service{private static MyService instance = null;
public static boolean isInstanceCreated() {return instance != null;}//met
@Overridepublic void onCreate(){instance = this;....}//met
@Overridepublic void onDestroy(){instance = null;...}//met}//class

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

这更适用于Intent Service调试,因为它们会产生一个线程,但也可能适用于常规服务。多亏了必应,我找到了这个线程

在我的例子中,我使用调试器并找到了线程视图。它看起来有点像MS Word中的项目符号图标。无论如何,您不必处于调试器模式即可使用它。单击进程并单击该按钮。任何意图服务都会在运行时显示出来,至少在模拟器上是这样。

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

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

  2. onDestroy()未调用:转到设置->应用程序->管理应用程序->选择并强制停止运行服务的应用程序。但是,由于您的应用程序在此处停止,因此服务实例肯定也会停止。

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

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

放松点,伙计们:)

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

逻辑非常简单;在服务类中任何想要的位置放置一个布尔值,该值将作为服务是否正在运行的标志。然后在应用程序中任何你想要的地方读取这个值。

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

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

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);}

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

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

希望这有帮助。

如果服务属于另一个进程或APK,请使用基于ActivityManager的解决方案。

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

您还可以从您的服务发送广播通知,指示它正在运行其他信息,例如进度。

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

我刚刚创建了两个应用程序。第一个应用程序的包名是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.Mock2Service03-27 12:02:33.755: D/TAG(32277): Mock-02: com.example.mock.lorem.Mock2Service

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

ComponentName的equals()方法。

@Overridepublic 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;}

同样,如果人们使用挂起的意图(例如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);}

其中CODE是一个常量,您在类中私下定义它以标识与您的服务关联的挂起意图。

在TheServiceClass内部定义:

 public static Boolean serviceRunning = false;

然后在onStartCommand(…)

 public int onStartCommand(Intent intent, int flags, int startId) {
serviceRunning = true;...}
@Overridepublic void onDestroy(){serviceRunning = false;
}

然后,从任何类调用if(TheServiceClass.serviceRunning == true)

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;}

我稍微修改了上面提出的一个解决方案,但传递类而不是通用字符串名称,以确保比较来自同一方法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);

摘自android文档:

类似于发送广播(意图),但如果有任何接收器此函数将阻止并立即发送它们回来之前

Service。由于我们可以同步广播,我们可以在UI线程上广播并获得结果同步

Service

@Overridepublic 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;}}

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

检查服务是否正在运行的正确方法是简单地询问它。在您的服务中实现一个BroadcastRecector,它会响应来自您的活动的ping。在服务启动时注册BroadcastRecector,并在服务销毁时取消注册。从您的活动(或任何组件)向服务发送本地广播意图,如果它响应,您就知道它正在运行。请注意下面代码中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);}
@Overridepublic void onDestroy () {LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);super.onDestroy();}
private BroadcastReceiver mReceiver = new BroadcastReceiver() {@Overridepublic 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;
@Overrideprotected 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 runningmanager.sendBroadcast(new Intent(PingableService.ACTION_PING));super.onStart();}
@Overrideprotected void onStop() {LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);super.onStop();}
protected BroadcastReceiver mReceiver = new BroadcastReceiver() {@Overridepublic void onReceive (Context context, Intent intent) {// here you receive the response from the serviceif (intent.getAction().equals(PingableService.ACTION_PONG)) {isSvcRunning = true;}}};}

简单的使用绑定到不创建自动-查看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.

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


PS。Android留档具有误导性,我在谷歌跟踪器上打开了一个问题以消除任何疑虑:

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

正如我们所看到的,bind服务实际上通过ActivityManager binder通过Service缓存binders调用事务-我dint跟踪哪个服务负责绑定,但正如我们所看到的,bind的结果是:

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

交易通过binder进行:

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 ServiceManagerServiceManager.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中挖掘,所以直到我解剖休息调用我暂停我的答案。

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

更新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(意图服务,字符串解析类型,字符串调用Package)抛出远程异常;

*

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;}

*

下面是一个涵盖所有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 thrownreturn mInstance != null && mInstance.ping();} catch (NullPointerException e) {// destroyed/not-startedreturn false;}}
/*** Simply returns true. If the service is still active, this method will be accessible.* @return*/private boolean ping() {return true;}
@Overridepublic void onCreate() {mInstance = this;}
@Overridepublic void onDestroy() {mInstance = null;}}

然后是:

    if(AService.isServiceCreated()){...}else{startService(...);}

geekQ的响应,但在静态编程语言类。谢谢geekQ

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

那个电话

isMyServiceRunning(NewService::class.java)

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

MyService.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.isServiceStartedif (!serviceStarted) {val startFileObserverService = Intent(this, FileObserverService::class.java)ContextCompat.startForegroundService(this, startFileObserverService)}}}

我对基于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

请使用此代码。

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;}

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

fun isMyServiceRunning(calssObj: Class<SERVICE_CALL_NAME>): Boolean {val manager = requireActivity().getSystemService(Context.ACTIVITY_SERVICE) as ActivityManagerfor (service in manager.getRunningServices(Integer.MAX_VALUE)) {if (calssObj.getName().equals(service.service.getClassName())) {return true}}return false}

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

companion object{var isRuning = false
}

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

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

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

fun isMyServiceRunning(serviceClass: Class<*>): Boolean {val manager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManagerreturn 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 ActivityManagerreturn manager.getRunningServices(Integer.MAX_VALUE).any { it.service.className == serviceClass.name }}

用法

context.isMyServiceRunning(MyService::class.java)

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

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.

检测服务是否正在运行的唯一方法是创建PING/Pong功能。

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

没有实现广播,因为它们可能会被错过。

如果您有一个多模块应用程序,并且您想知道服务是否从不依赖于包含服务的模块的模块运行,您可以使用此函数:

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")

如果服务类名更改且调用函数未相应更改,则此函数可能无法正常工作。

从Android 8(或Oreo)开始,APIgetRunningServices已弃用。当然,您可以使用@SuppressWarnings("deprecation")来摆脱警告。

如果您的服务不需要有多个实例,以下是如何在没有getRunnngServices的情况下进行操作:使用单例模式。

public class MyMusicService extends Service {
private static MyMusicService instance = null;    
public static boolean isMyMusicServiceRunning() {return instance != null;}

然后,您可以从您的活动或其他地方调用MyMusicService.isMyMusicServiceRunning

这是我想出的很好的解决方案,但它仅适用于在单独进程中运行的服务。这可以通过在清单中添加android:process属性来实现,例如:

<serviceandroid:name=".ExampleService"android:process="com.example.service"...

现在,您的服务将在具有给定名称的单独进程中运行。从您的应用程序中,您可以调用

val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManageractivityManager.runningAppProcesses.any { it.processName == "com.example.service" }

如果服务正在运行,则返回true,否则返回false

重要事项:注意,它会显示你的服务何时启动,但是当你禁用它时(意味着,在系统解除绑定后),该进程仍然可以是活动的。所以你可以简单地强制删除它:

override fun onUnbind(intent: Intent?): Boolean {stopSelf()return super.onUnbind(intent)}
override fun onDestroy() {super.onDestroy()killProcess(Process.myPid())}

然后它完美地工作。