我有一个服务,我认为它正在前台运行,如何检查我的实现是否有效?
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;
}
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
。
一个更高效的答案变体:https://dev59.com/eWw15IYBdhLWcg3wtN2O#36127260
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;
}
从API 26开始,getRunningService()
已被弃用。
现在的解决方案是将Activity与Service绑定。然后你可以从Activity中调用Service的方法来检查它是否正在运行。
1 - 在你的Service中创建一个继承Binder类并返回你的Service的类。
public class LocalBinder extends Binder {
MyService getService() {
return MyService.this;
}
}
2- 在您的服务中声明 binder
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中,您可以绑定到您的Service
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);
}
要了解更多信息,请查看官方文档中的绑定服务概述。
从API29(Q)开始,您可以使用以下代码简单地检查它。
可以从您的服务内部调用。如果您没有服务实例,您可以使用binder获取它。
class MyService : Service {
val isForeground: Boolean get() = foregroundServiceType != FOREGROUND_SERVICE_TYPE_NONE
}
FOREGROUND_SERVICE_TYPE_NONE
只有在启动一次后才会出现。无论是否删除通知,调用stopForeground()
仍将导致foregroundServiceType
不是FOREGROUND_SERVICE_TYPE_NONE
。我建议将getRunningService()
答案之一(并检查foreground
字段)合并,即使它已被弃用。 - technicalflaw关于Adam的回答,稍作补充:
@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
这在加密货币新闻的Coinverse应用程序中对我起作用。
这是最简洁的Kotlin解决方案。感谢Abbas Naqdi在GitHub问题中的贡献。
@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 }
it.foreground
。 - Elyess Abouda