一、问题
我们知道,ActivityManagerService随着版本的变化,获取方式上也出现了差异,最容易获取的方式当然是
ActivityManager activityManager = Context.getSystemService("activity");
但是,这种方式获取到ActivityManager存在很多限制,导致无法和AMS通信,那么还有没其他方式?
二,获取方式
1、关于ServiceManager
我们知道,ServiceManager是早于Zygote_Server和System_Server,我们可以提前获取的服务很多。而AMS在System_server进程中运行,后期将服务注册到ServceManager,本质上ServiceManager是系统服务的路由角色
2、如何获取呢,方法如下
public Object getActivityManagerProxy(){
final Class<?> serviceManagerClazz = Class.forName("android.os.ServiceManager");
final Method getServiceMethod =
serviceManagerClazz.getMethod("getService",IBinder.class);
final IBinder activityBinder = (IBinder) getServiceMethod.invoke(serviceManagerClazz, "activity");
Class<?> activityManagerStu = Class.forName("android.app.IActivityManager$Stub");
Method asInterface = activityManagerStu.getMethod("asInterface",IBinder.class);
return asInterface.invoke(activityManagerStu,activityBinder);
}
3、事实上上述方法存在缺陷
因为在Android O之前,AMS继承自ActivityManagerNative, 虽然这个类在用户进程可见,而且在ActivityThread中进行了注册,但并不能满足我们的要求。不过倒是一种获取BinderProxy的途径。
AMS 不存在IActivityManager.Stub,而使用的android.os.ActivityManagerProxy,我们需要做一下兼容即可
public static Object getActivityManagerProxy(){
try {
if(Build.VERSION.SDK_INT< Build.VERSION_CODES.N){
Class activityManagerNativeClass = Class.forName("android.app.ActivityManagerNative");
Method getDefault = activityManagerNativeClass.getDeclaredMethod("getDefault");
return getDefault.invoke(null);
}
final Class<?> serviceManagerClazz = Class.forName("android.os.ServiceManager");
final Method getServiceMethod = serviceManagerClazz.getMethod("getService", String.class);
final IBinder activityBinder = (IBinder) getServiceMethod.invoke(serviceManagerClazz, "activity");
Class<?> activityManagerStu = Class.forName("android.app.IActivityManager$Stub");
Method asInterface = activityManagerStu.getMethod("asInterface", IBinder.class);
return asInterface.invoke(activityManagerStu, activityBinder);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
三、测试
Method startService = activityManagerProxy.getClass().getDeclaredMethod("startService",
Class.forName("android.app.IApplicationThread"),
Intent.class,
String.class,
String.class,
int.class
);