【问题标题】:How to get a service from ServiceManager in Android?如何从 Android 中的 ServiceManager 获取服务?
【发布时间】:2017-01-11 17:24:06
【问题描述】:

我怀疑 ServiceManager 注册的服务,而不是 SystemServiceRegistry 注册的服务。

SystemServiceRegistry 的cmets中

/**
 * Manages all of the system services that can be returned by {@link Context#getSystemService}.
 * Used by {@link ContextImpl}.
 */

也就是说System注册的服务可以从Context中得到他的引用。

关于ServiceManager,我怎样才能访问ServiceManager在一个应用程序中添加的服务,而该应用程序没有被SystemServiceRegistry注册?

【问题讨论】:

  • ServiceManagerSystemServiceRegistry 都不是 Android SDK 的一部分。如注释所示,在Context 上使用getSystemService() 来检索系统服务。
  • 是的,但是我要找的服务不是系统注册的,是ServiceManager添加的。上下文无法为我解决。
  • try/catch 调用getSystemService("service_name") 并检查调用是否将句柄返回给系统服务!= null... "未由系统注册并由系统添加的服务ServiceManager" AFAIK 添加服务与在ServiceManager 中注册服务相同。
  • @Onik 我正在使用“库存”API。添加服务与在系统中注册服务不同,您可以在此问题的参考资料中查看。
  • @Andriel 好的。但是在不注册的情况下将服务添加到ServiceManager 的列表有什么意义呢?不是Context不能解决,你不能利用——系统不能操作。不管怎样,试试我建议的方法。

标签: android android-service system-services


【解决方案1】:

这个答案真的很晚,但访问隐藏类 ServiceManager 上的方法的另一种方法是使用反射。由于类上的所有方法都是静态的,因此您不需要将对象引用传递给调用方法。您可以简单地传入类实例。为了获得隐藏类上的类实例,您可以使用更多反射。 示例:

Class localClass = Class.forName("android.os.ServiceManager");
Method getService = localClass.getMethod("getService", new Class[] {String.class});
if(getService != null) {
   Object result = getService.invoke(localClass, new Object[]{Context.AUDIO_SERVICE});
   if(result != null) {
      IBinder binder = (IBinder) result;
      // DO WHAT EVER YOU WANT AT THIS POINT, YOU WILL
      // NEED TO CAST THE BINDER TO THE PROPER TYPE OF THE SERVICE YOU USE.
   }
}

这几乎是访问隐藏或私有方法所需要做的所有事情(尽管使用私有方法,但您需要修改方法的访问权限)。 我知道反射在 Android 中很糟糕,它们通常是一些 API 未公开但有一些有效用例可以使用它的好理由。如果您不经常调用反射代码,那么性能损失并不可怕,如果是,您可以缓存方法,这样您就不必在每次调用时都执行查找。话虽如此,请仔细分析您是否真的需要访问非公共 API。

【讨论】:

  • 您能完成将活页夹转换为 AudioManager 的示例吗?
【解决方案2】:

正如@CommonsWare 正确提到的,您需要在上下文中使用 getSystemService()。 例如。获取位置服务:

LocationManager mLocationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);

供您自定义服务使用(假设您的服务已在 AndroidManifest.xml 中注册):

startService(new Intent(this, YourServiceClass.class));

【讨论】:

  • 请检查我上面的评论,上下文引用只有系统注册的服务,而不是来自 ServiceManager 的服务。
  • 供您的自定义服务使用:startService(new Intent(this, YourServiceClass.class));
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-29
  • 1970-01-01
  • 1970-01-01
  • 2016-07-22
  • 2020-03-20
  • 2016-07-30
  • 1970-01-01
相关资源
最近更新 更多