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

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


当前回答

同样,如果使用pending intent(例如使用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是一个常量,您在类中私有地定义它,以标识与您的服务相关联的挂起意图。

其他回答

得到它!

你必须调用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;
     }
}

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

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

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

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

为什么不使用呢?getRunningServices ()

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

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


附注:android文档具有误导性,我已经在谷歌跟踪器上打开了一个问题,以消除任何疑问:

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的method中调用:

 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,所以在我解析rest call之前,我暂停了我的回答。

但是检查服务是否正在运行的最好方法是创建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;
}

简而言之:)

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

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

*

我只是想给@Snicolas的答案加上一个注释。以下步骤可以使用/不调用onDestroy()来检查停止服务。

onDestroy() called: Go to Settings -> Application -> Running Services ->选择并停止服务。 onDestroy()未调用:转到设置->应用程序->管理应用程序->选择并“强制停止”您的应用程序,其中您的服务正在运行。但是,由于您的应用程序在这里停止,因此服务实例也肯定会停止。

最后,我想提一下,在单例类中使用静态变量的方法对我来说是有效的。

你可以使用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.