如何查看后台服务是否正在运行?
我想要一个切换服务状态的Android活动——它让我打开它,如果它是关闭的,如果它是关闭的。
如何查看后台服务是否正在运行?
我想要一个切换服务状态的Android活动——它让我打开它,如果它是关闭的,如果它是关闭的。
当前回答
摘自Android文档:
比如sendBroadcast(Intent),但是如果有任何接收器 这个函数将阻塞并立即分发它们 返回之前。
你可以把这次入侵看成是"ping "服务。因为我们可以同步广播,所以我们可以在UI线程上同步广播并获得结果。
服务
@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;
}
}
当然,在许多应用程序中,赢家是服务上的静态布尔字段,在service . oncreate()中设置为true,在service . ondestroy()中设置为false,因为它要简单得多。
其他回答
这更适用于Intent Service调试,因为它们会生成一个线程,但也适用于常规服务。我找到这个线程感谢宾
在我的例子中,我摆弄了调试器并找到了线程视图。它看起来有点像微软Word里的项目符号图标。无论如何,您不必在调试器模式下使用它。单击该流程并单击该按钮。任何Intent服务都会在运行时显示出来,至少在模拟器上是这样。
请使用这个密码。
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;
}
这是我提出的一个很好的解决方案,但它只适用于运行在单独进程中的服务。这可以通过在manifest中添加一个android:process属性来实现。
<service
android:name=".ExampleService"
android:process="com.example.service"
...
现在,您的服务将运行在具有给定名称的单独进程中。从你的应用程序你可以打电话
val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
activityManager.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())
}
然后它就完美地工作了。
可以有多个具有相同类名的服务。
我刚刚创建了两个应用程序。第一个应用程序的包名是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实例,因为ComponentName的equals()比较包名和类名。一个设备上不能安装两个包名相同的应用程序。
ComponentName的equals()方法。
@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;
}
ComponentName
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;
}