1

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

SystemServiceRegistry的评论中

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

这意味着 System 注册的服务可以从 Context 中获取他的引用。

关于ServiceManager,如何访问 ServiceManager 在未由 SystemServiceRegistry 注册的应用程序中添加的服务?

4

2 回答 2

8

这个答案真的很晚,但访问隐藏类 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。

于 2017-05-23T13:50:28.097 回答
0

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

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

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

startService(new Intent(this, YourServiceClass.class));
于 2017-01-11T17:29:12.640 回答