如何检查Android 8(API 26)上的服务是否正在运行?

9

当我升级到Android 8时,我的应用程序的某些功能出现了问题,即使没有明确针对API 26进行目标设置。特别是,检查服务是否正在运行的经典方法(如StackOverflow上记录的: How to check if a service is running on Android?)不再起作用。

只是为了提醒我们的共同记忆,这是一个经典的方法:

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

现在的问题是 getRunningServices 已经被弃用,不再返回正在运行的服务。有谁在 Android 8 上遇到过这个问题吗?是否有官方解决方案(或黑科技)可用?我还应该指出,我想要查找的 Service 不在 调用 isMyServiceRunning() 的代码所在的进程/应用程序中(出于向后兼容的原因仍提供此功能)


@CommonsWare 我同意你对于代码臭味的看法。问题在于我需要使用它来检查第三方应用程序的服务(这个应用程序碰巧是我的)。因此,该服务与调用isMyServiceRunning()的代码不在同一个进程中,也许我应该在我的问题中进行说明。 - Enrico Casini
1
这是一位Android架构师说的话:https://groups.google.com/forum/#!topic/android-developers/jEvXMWgbgzE “我们故意没有提供检查服务是否运行的API,因为几乎总是会在代码中出现竞争条件。” - pskink
1
这里的问题是我需要使用它来检查第三方应用程序的服务是否运行。你为什么关心服务是否正在运行?假设你的 isMyServiceRunning() 返回 true,你会怎么做?假设它返回 false,你会怎么做? - CommonsWare
如果 isMyServiceRunning 返回 false,但是服务在此期间已经启动了呢? - pskink
1
你不应该依赖于服务的“物理”状态(已启动/未启动),而应该依赖于其“逻辑”状态(例如连接/未连接)。你可以通过调用(无条件地)startService 并通过 Intent 的 extras 传递 ResultReceiverMessenger 对象来轻松检查该状态,在 Service#onStartCommand 中简单地响应当前状态。 - pskink
显示剩余5条评论
1个回答

5

"getRunningServices()"这个方法已经不再对第三方应用程序开放。目前没有其他替代方法来获取正在运行的服务。

https://developer.android.com/reference/android/app/ActivityManager.html#getRunningServices(int)

如何检查Android上的服务是否正在运行? 我只是手动检查它,当服务正在运行时我将布尔值设置为true,当服务停止或销毁时,我将布尔值设置为false。我使用SharedPreferences来保存这个布尔值。

Service.class

override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
    Log.d("service", "onStartCommand")
    setRunning(true)
}

private fun setRunning(running: Boolean) {
    val sessionManager = SessionManager(this)
    sessionManager.isRunning = running
}


override fun onDestroy() {
   setRunning(false)
   super.onDestroy()
}

SessionManager.class

class SessionManager(var context: Context) {
    private val loginpreferences: SharedPreferences
    private val logineditor: SharedPreferences.Editor

    init {
      loginpreferences = context.getSharedPreferences(Pref_name, private_modde)
      logineditor = loginpreferences.edit()
    }

    var isRunning: Boolean
      get() = loginpreferences.getBoolean(SERVICES, false)
      set(value) {
         logineditor.putBoolean(SERVICES, value)
         logineditor.commit()
      }

    companion object {
      private val SERVICES = "service"
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接