一、問題
我們知道,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", 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);
} 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
);