360 Android 插件开发 DroidPlugin 代码分析 -随笔



备注:本文是个人的随笔,之后如果有时间,会书写比较正式的分析博客

 60的插件
DroidPlugin

引用的工程

DroidPlugin中在资源清单文件中几乎申请了所有的权限

在demo中配置插件的启动




PluginHelper.getInstance().applicationOnCreate(getBaseContext());是核心操作,进行了初始化的一系列的工作

PluginHelper . getInstance (). applicationAttachBaseContext ( base ); 并没有做什么操作,只是注册了crash之后的log发送之类的信息

分析 PluginHelper . getInstance (). applicationOnCreate ( getBaseContext ());

   
public void applicationOnCreate(final Context baseContext) {
initPlugin(baseContext);
}

1. 安装钩子函数相关
2. 判断是否允许钩子函数的运行
3. 注册插件service的监听
4. 启动插件service

   
private void initPlugin(Context baseContext) {
long b = System.currentTimeMillis();
try {
try {
fixMiUiLbeSecurity();
} catch (Throwable e) {
Log.e(TAG, "fixMiUiLbeSecurity has error", e);
}
 
try {
PluginProcessManager.installHook(baseContext);
} catch (Throwable e) {
Log.e(TAG, "installHook has error", e);
}
 
try {
if (PluginProcessManager.isPluginProcess(baseContext)) {
PluginProcessManager.setHookEnable(true);
} else {
PluginProcessManager.setHookEnable(false);
}
} catch (Throwable e) {
Log.e(TAG, "setHookEnable has error", e);
}
 
try {
PluginManager.getInstance().addServiceConnection(PluginHelper.this);
PluginManager.getInstance().init(baseContext);
} catch (Throwable e) {
Log.e(TAG, "installHook has error", e);
}
 
 
} finally {
Log.i(TAG, "Init plugin in process cost %s ms", (System.currentTimeMillis() - b));
}
}

PluginProcessManager . installHook ( baseContext );

    
public static void installHook(Context hostContext) throws Throwable {
HookFactory.getInstance().installHook(hostContext, null);
}

     
public final void installHook(Context context, ClassLoader classLoader) throws Throwable {
installHook(new IClipboardBinderHook(context), classLoader);
//for ISearchManager
installHook(new ISearchManagerBinderHook(context), classLoader);
//for INotificationManager
installHook(new INotificationManagerBinderHook(context), classLoader);
installHook(new IMountServiceBinder(context), classLoader);
installHook(new IAudioServiceBinderHook(context), classLoader);
installHook(new IContentServiceBinderHook(context), classLoader);
installHook(new IWindowManagerBinderHook(context), classLoader);
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP_MR1) {
installHook(new IGraphicsStatsBinderHook(context), classLoader);
}
if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
installHook(new IMediaRouterServiceBinderHook(context), classLoader);
}
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
installHook(new ISessionManagerBinderHook(context), classLoader);
}
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR2) {
installHook(new IWifiManagerBinderHook(context), classLoader);
}
 
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR2) {
installHook(new IInputMethodManagerBinderHook(context), classLoader);
}
 
installHook(new IPackageManagerHook(context), classLoader);
installHook(new IActivityManagerHook(context), classLoader);//以此为案例,做分析
installHook(new PluginCallbackHook(context), classLoader);
installHook(new InstrumentationHook(context), classLoader);
installHook(new LibCoreHook(context), classLoader);
 
installHook(new SQLiteDatabaseHook(context), classLoader);
}

    
public void installHook(Hook hook, ClassLoader cl) {
try {
hook.onInstall(cl);
synchronized (mHookList) {
mHookList.add(hook);
}
} catch (Throwable throwable) {
Log.e(TAG, "installHook %s error", throwable, hook);
}
}

以IActivityManagerHook为例,在初始化之后,调用了onInstall的方法,先记录到此处
现在查看Hook的体系结构

Hook
--| ProxyHook
--| IActivityManagerHook

Hook基类,
1. 设置是否可以enable hook
2. 在构造时,需要创建hook的处理类
3. install和uninstall hook

    
public abstract class Hook {
 
private boolean mEnable = false;
 
protected Context mHostContext;
protected BaseHookHandle mHookHandles;
 
public void setEnable(boolean enable, boolean reInstallHook) {
this.mEnable = enable;
}
 
public final void setEnable(boolean enable) {
setEnable(enable, false);
}
 
public boolean isEnable() {
return mEnable;
}
 
 
protected Hook(Context hostContext) {
mHostContext = hostContext;
mHookHandles = createHookHandle();
}
 
protected abstract BaseHookHandle createHookHandle();
 
 
protected abstract void onInstall(ClassLoader classLoader) throws Throwable;
 
protected void onUnInstall(ClassLoader classLoader) throws Throwable {
 
}
}

下面查看ProxyHook

因为是代理,
1. 提供了一个setOldobj的方法,用户缓存OldObj
2. 实现了Java体系中默认的动态代理方式
3. 如果当前的handle不为空,并且是enabled的情况下,那么交给HookedMethodHandle.doHookInner()方法来处理

    
public abstract class ProxyHook extends Hook implements InvocationHandler {
 
protected Object mOldObj;
 
public ProxyHook(Context hostContext) {
super(hostContext);
}
 
public void setOldObj(Object oldObj) {
this.mOldObj = oldObj;
}
 
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 
try {
if (!isEnable()) {
return method.invoke(mOldObj, args);
}
HookedMethodHandler hookedMethodHandler = mHookHandles.getHookedMethodHandler(method);
if (hookedMethodHandler != null) {
return hookedMethodHandler.doHookInner(mOldObj, method, args);
}
return method.invoke(mOldObj, args);
} catch (InvocationTargetException e) {
Throwable cause = e.getTargetException();
if (cause != null && MyProxy.isMethodDeclaredThrowable(method, cause)) {
throw cause;
} else if (cause != null) {
RuntimeException runtimeException = !TextUtils.isEmpty(cause.getMessage()) ? new RuntimeException(cause.getMessage()) : new RuntimeException();
runtimeException.initCause(cause);
throw runtimeException;
} else {
RuntimeException runtimeException = !TextUtils.isEmpty(e.getMessage()) ? new RuntimeException(e.getMessage()) : new RuntimeException();
runtimeException.initCause(e);
throw runtimeException;
}
} catch (Throwable e) {
if (MyProxy.isMethodDeclaredThrowable(method, e)) {
throw e;
} else {
RuntimeException runtimeException = !TextUtils.isEmpty(e.getMessage()) ? new RuntimeException(e.getMessage()) : new RuntimeException();
runtimeException.initCause(e);
throw runtimeException;
}
}
}
}


插曲: HookedMethodHandle的内容
核心内容:  doHookInner实现代理的逻辑

{
1. 先执行beforeInvoke方法,如果返回true,那么便拦截掉了这个事件
2. 如果 beforeInvoke返回false,那么继续处理这个事件
3. 调用afterInvoke的方法
}
    
public class HookedMethodHandler {
 
private static final String TAG = HookedMethodHandler.class.getSimpleName();
protected final Context mHostContext;
 
private Object mFakedResult = null;
private boolean mUseFakedResult = false;
 
public HookedMethodHandler(Context hostContext) {
this.mHostContext = hostContext;
}
 
 
public synchronized Object doHookInner(Object receiver, Method method, Object[] args) throws Throwable {
long b = System.currentTimeMillis();
try {
mUseFakedResult = false;
mFakedResult = null;
boolean suc = beforeInvoke(receiver, method, args);
Object invokeResult = null;
if (!suc) {
invokeResult = method.invoke(receiver, args);
}
afterInvoke(receiver, method, args, invokeResult);
if (mUseFakedResult) {
return mFakedResult;
} else {
return invokeResult;
}
} finally {
long time = System.currentTimeMillis() - b;
if (time > 5) {
Log.i(TAG, "doHookInner method(%s.%s) cost %s ms", method.getDeclaringClass().getName(), method.getName(), time);
}
}
}
 
public void setFakedResult(Object fakedResult) {
this.mFakedResult = fakedResult;
mUseFakedResult = true;
}
 
/**
* 在某个方法被调用之前执行,如果返回true,则不执行原始的方法,否则执行原始方法
*/
protected boolean beforeInvoke(Object receiver, Method method, Object[] args) throws Throwable {
return false;
}
 
protected void afterInvoke(Object receiver, Method method, Object[] args, Object invokeResult) throws Throwable {
}
 
public boolean isFakedResult() {
return mUseFakedResult;
}
 
public Object getFakedResult() {
return mFakedResult;
}
}


插曲结束

继续分析Hook的结构 : IActivityManagerHook

1. 在createHookHandle()的时候,新创建了一个IActivityManagerHookHandle
2. onInstall为安装此Hook的调用方法

   
public class IActivityManagerHook extends ProxyHook {
 
private static final String TAG = IActivityManagerHook.class.getSimpleName();
 
public IActivityManagerHook(Context hostContext) {
super(hostContext);
}
 
@Override
public BaseHookHandle createHookHandle() {
return new IActivityManagerHookHandle(mHostContext);
}
 
@Override
public void onInstall(ClassLoader classLoader) throws Throwable {
//TODO ------解析来分析-------
}
}

IActivityManagerHook --> onInstall方法分析

1. 找到系统的IActivityManager
2. 接下来判断此IActivityManager是否是单例,根据是否是单例,做不同的代理的处理
但是这个对于我们想要看的逻辑没有大的影响,我们按照简单的看(个人查看android 2.3的源码时(在线查看地址: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3.7_r1/android/app/ActivityManagerNative.java ),发现是单例,我们不按照单例的看,为什么,是因为简单,便于理解!)

   
@Override
public void onInstall(ClassLoader classLoader) throws Throwable {
Class cls = ActivityManagerNativeCompat.Class();
Object obj = FieldUtils.readStaticField(cls, "gDefault");
if (obj == null) {
ActivityManagerNativeCompat.getDefault();
obj = FieldUtils.readStaticField(cls, "gDefault");
}
 
if (IActivityManagerCompat.isIActivityManager(obj)) {
setOldObj(obj);
Class<?> objClass = mOldObj.getClass();
List<Class<?>> interfaces = Utils.getAllInterfaces(objClass);
Class[] ifs = interfaces != null && interfaces.size() > 0 ? interfaces.toArray(new Class[interfaces.size()]) : new Class[0];
Object proxiedActivityManager = MyProxy.newProxyInstance(objClass.getClassLoader(), ifs, this);
FieldUtils.writeStaticField(cls, "gDefault", proxiedActivityManager);
Log.i(TAG, "Install ActivityManager Hook 1 old=%s,new=%s", mOldObj, proxiedActivityManager);
} else if (SingletonCompat.isSingleton(obj)) {
Object obj1 = FieldUtils.readField(obj, "mInstance");
if (obj1 == null) {
SingletonCompat.get(obj);
obj1 = FieldUtils.readField(obj, "mInstance");
}
setOldObj(obj1);
List<Class<?>> interfaces = Utils.getAllInterfaces(mOldObj.getClass());
Class[] ifs = interfaces != null && interfaces.size() > 0 ? interfaces.toArray(new Class[interfaces.size()]) : new Class[0];
final Object object = MyProxy.newProxyInstance(mOldObj.getClass().getClassLoader(),ifs, IActivityManagerHook.this);
Object iam1 = ActivityManagerNativeCompat.getDefault();
 
//这里先写一次,防止后面找不到Singleton类导致的挂钩子失败的问题。
FieldUtils.writeField(obj, "mInstance", object);
 
//这里使用方式1,如果成功的话,会导致上面的写操作被覆盖。
FieldUtils.writeStaticField(cls, "gDefault", new android.util.Singleton<Object>() {
@Override
protected Object create() {
Log.e(TAG, "Install ActivityManager 3 Hook old=%s,new=%s", mOldObj, object);
return object;
}
});
 
Log.i(TAG, "Install ActivityManager Hook 2 old=%s,new=%s", mOldObj.toString(), object);
Object iam2 = ActivityManagerNativeCompat.getDefault();
// 方式2
if (iam1 == iam2) {
//这段代码是废的,没啥用,写这里只是不想改而已。
FieldUtils.writeField(obj, "mInstance", object);
}
} else {
throw new AndroidRuntimeException("Can not install IActivityManagerNative hook");
}
}
这里采用了java的动态代理,用的activityManager是我们经过代理的activityManager
非静态代理的源码:
   
setOldObj(obj);
Class<?> objClass = mOldObj.getClass();
List<Class<?>> interfaces = Utils.getAllInterfaces(objClass);
Class[] ifs = interfaces != null && interfaces.size() > 0 ? interfaces.toArray(new Class[interfaces.size()]) : new Class[0];
Object proxiedActivityManager = MyProxy.newProxyInstance(objClass.getClassLoader(), ifs, this);
FieldUtils.writeStaticField(cls, "gDefault", proxiedActivityManager);
Log.i(TAG, "Install ActivityManager Hook 1 old=%s,new=%s", mOldObj, proxiedActivityManager);

既然是经过代理的,那么代理部分肯定是部分经过我们处理的,那么这部分逻辑就是关键了,看到代理的回调部分是交给 IActivityManagerHook处理的,其实就是基类ProxyHook来处理的
刚才已经分析,就是invoke的插曲部分
那么现在需要关心的就是HookedMethodHandler的实现逻辑了
但是在 HookedMethodHandler中,我们只是看到了逻辑框架部分,具体的处理逻辑需要在子类中查看,那么对应 IActivityManagerHook的Handler是那个呢?


IActivityManagerHook的createHookHandle()的方法中,我们已经看到使用的是 IActivityManagerHookHandle ,那么现在我们需要关系新的就是 IActivityManagerHookHandle中做了怎么样的逻辑处理,但是在这之前,我们先看看 IActivityManagerHookHandle的构造部分

代码看起来很长的样子,其实就是 sHookedMethodHandlers中存放了当前需要关联的函数名字和对应的处理内容


   
public IActivityManagerHookHandle(Context hostContext) {
super(hostContext);
}
 
@Override
protected void init() {
sHookedMethodHandlers.put("startActivity", new startActivity(mHostContext));
sHookedMethodHandlers.put("startActivityAsUser", new startActivityAsUser(mHostContext));
sHookedMethodHandlers.put("startActivityAsCaller", new startActivityAsCaller(mHostContext));
sHookedMethodHandlers.put("startActivityAndWait", new startActivityAndWait(mHostContext));
sHookedMethodHandlers.put("startActivityWithConfig", new startActivityWithConfig(mHostContext));
sHookedMethodHandlers.put("startActivityIntentSender", new startActivityIntentSender(mHostContext));
sHookedMethodHandlers.put("startVoiceActivity", new startVoiceActivity(mHostContext));
sHookedMethodHandlers.put("startNextMatchingActivity", new startNextMatchingActivity(mHostContext));
sHookedMethodHandlers.put("startActivityFromRecents", new startActivityFromRecents(mHostContext));
sHookedMethodHandlers.put("finishActivity", new finishActivity(mHostContext));
sHookedMethodHandlers.put("registerReceiver", new registerReceiver(mHostContext));
sHookedMethodHandlers.put("broadcastIntent", new broadcastIntent(mHostContext));
sHookedMethodHandlers.put("unbroadcastIntent", new unbroadcastIntent(mHostContext));
sHookedMethodHandlers.put("getCallingPackage", new getCallingPackage(mHostContext));
sHookedMethodHandlers.put("getCallingActivity", new getCallingActivity(mHostContext));
sHookedMethodHandlers.put("getAppTasks", new getAppTasks(mHostContext));
sHookedMethodHandlers.put("addAppTask", new addAppTask(mHostContext));
sHookedMethodHandlers.put("getTasks", new getTasks(mHostContext));
sHookedMethodHandlers.put("getServices", new getServices(mHostContext));
sHookedMethodHandlers.put("getProcessesInErrorState", new getProcessesInErrorState(mHostContext));
sHookedMethodHandlers.put("getContentProvider", new getContentProvider(mHostContext));
sHookedMethodHandlers.put("getContentProviderExternal", new getContentProviderExternal(mHostContext));
sHookedMethodHandlers.put("removeContentProviderExternal", new removeContentProviderExternal(mHostContext));
sHookedMethodHandlers.put("publishContentProviders", new publishContentProviders(mHostContext));
sHookedMethodHandlers.put("getRunningServiceControlPanel", new getRunningServiceControlPanel(mHostContext));
sHookedMethodHandlers.put("startService", new startService(mHostContext));
sHookedMethodHandlers.put("stopService", new stopService(mHostContext));
sHookedMethodHandlers.put("stopServiceToken", new stopServiceToken(mHostContext));
sHookedMethodHandlers.put("setServiceForeground", new setServiceForeground(mHostContext));
sHookedMethodHandlers.put("bindService", new bindService(mHostContext));
sHookedMethodHandlers.put("publishService", new publishService(mHostContext));
sHookedMethodHandlers.put("unbindFinished", new unbindFinished(mHostContext));
sHookedMethodHandlers.put("peekService", new peekService(mHostContext));
sHookedMethodHandlers.put("bindBackupAgent", new bindBackupAgent(mHostContext));
sHookedMethodHandlers.put("backupAgentCreated", new backupAgentCreated(mHostContext));
sHookedMethodHandlers.put("unbindBackupAgent", new unbindBackupAgent(mHostContext));
sHookedMethodHandlers.put("killApplicationProcess", new killApplicationProcess(mHostContext));
sHookedMethodHandlers.put("startInstrumentation", new startInstrumentation(mHostContext));
sHookedMethodHandlers.put("getActivityClassForToken", new getActivityClassForToken(mHostContext));
sHookedMethodHandlers.put("getPackageForToken", new getPackageForToken(mHostContext));
sHookedMethodHandlers.put("getIntentSender", new getIntentSender(mHostContext));
sHookedMethodHandlers.put("clearApplicationUserData", new clearApplicationUserData(mHostContext));
sHookedMethodHandlers.put("handleIncomingUser", new handleIncomingUser(mHostContext));
sHookedMethodHandlers.put("grantUriPermission", new grantUriPermission(mHostContext));
sHookedMethodHandlers.put("getPersistedUriPermissions", new getPersistedUriPermissions(mHostContext));
sHookedMethodHandlers.put("killBackgroundProcesses", new killBackgroundProcesses(mHostContext));
sHookedMethodHandlers.put("forceStopPackage", new forceStopPackage(mHostContext));
sHookedMethodHandlers.put("getRunningAppProcesses", new getRunningAppProcesses(mHostContext));
sHookedMethodHandlers.put("getRunningExternalApplications", new getRunningExternalApplications(mHostContext));
sHookedMethodHandlers.put("getMyMemoryState", new getMyMemoryState(mHostContext));
sHookedMethodHandlers.put("crashApplication", new crashApplication(mHostContext));
sHookedMethodHandlers.put("grantUriPermissionFromOwner", new grantUriPermissionFromOwner(mHostContext));
sHookedMethodHandlers.put("checkGrantUriPermission", new checkGrantUriPermission(mHostContext));
sHookedMethodHandlers.put("startActivities", new startActivities(mHostContext));
sHookedMethodHandlers.put("getPackageScreenCompatMode", new getPackageScreenCompatMode(mHostContext));
sHookedMethodHandlers.put("setPackageScreenCompatMode", new setPackageScreenCompatMode(mHostContext));
sHookedMethodHandlers.put("getPackageAskScreenCompat", new getPackageAskScreenCompat(mHostContext));
sHookedMethodHandlers.put("setPackageAskScreenCompat", new setPackageAskScreenCompat(mHostContext));
sHookedMethodHandlers.put("navigateUpTo", new navigateUpTo(mHostContext));
sHookedMethodHandlers.put("serviceDoneExecuting", new serviceDoneExecuting(mHostContext));
 
}

这样在ProxyHook的invoke的方法中,便可以获取到对应的方法需要处理的 HookedMethodHandler,假如此方法需要处理,那么便调用此方法的doHookInner方法即可

   
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 
try {
if (!isEnable()) {
return method.invoke(mOldObj, args);
}
HookedMethodHandler hookedMethodHandler = mHookHandles.getHookedMethodHandler(method);
if (hookedMethodHandler != null) {
return hookedMethodHandler.doHookInner(mOldObj, method, args);
}
return method.invoke(mOldObj, args);
} catch (InvocationTargetException e) {
Throwable cause = e.getTargetException();
if (cause != null && MyProxy.isMethodDeclaredThrowable(method, cause)) {
throw cause;
} else if (cause != null) {
RuntimeException runtimeException = !TextUtils.isEmpty(cause.getMessage()) ? new RuntimeException(cause.getMessage()) : new RuntimeException();
runtimeException.initCause(cause);
throw runtimeException;
} else {
RuntimeException runtimeException = !TextUtils.isEmpty(e.getMessage()) ? new RuntimeException(e.getMessage()) : new RuntimeException();
runtimeException.initCause(e);
throw runtimeException;
}
} catch (Throwable e) {
if (MyProxy.isMethodDeclaredThrowable(method, e)) {
throw e;
} else {
RuntimeException runtimeException = !TextUtils.isEmpty(e.getMessage()) ? new RuntimeException(e.getMessage()) : new RuntimeException();
runtimeException.initCause(e);
throw runtimeException;
}
}
}

以startActivity为例,代码如下:
关于HookedMethodHandler的处理逻辑我们已经介绍,下面,只需要关心子类的beforeInvoke方法和 afterInvoke方法即可

发现startActivity类,只是做了beforeInvoke的逻辑,并且没有返回true,因而,还是会调用系统的startActivity方法,但是为什么就可以打开作为插件打开呢?这就是beforeInvoke的逻辑了
   
private static class startActivity extends HookedMethodHandler {
 
public startActivity(Context hostContext) {
super(hostContext);
}
 
protected void doReplaceIntentForStartActivityAPIHigh(Object[] args) throws RemoteException {
int intentOfArgIndex = findFirstIntentIndexInArgs(args);
if (args != null && args.length > 1 && intentOfArgIndex >= 0) {
Intent intent = (Intent) args[intentOfArgIndex];
//XXX String callingPackage = (String) args[1];
ActivityInfo activityInfo = resolveActivity(intent);
if (activityInfo != null && isPackagePlugin(activityInfo.packageName)) {
ComponentName component = selectProxyActivity(intent);
if (component != null) {
Intent newIntent = new Intent();
try {
ClassLoader pluginClassLoader = PluginProcessManager.getPluginClassLoader(component.getPackageName());
setIntentClassLoader(newIntent, pluginClassLoader);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
newIntent.setComponent(component);
newIntent.putExtra(Env.EXTRA_TARGET_INTENT, intent);
String callingPackage = (String) args[1];
if (TextUtils.equals(mHostContext.getPackageName(), callingPackage)) {
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
args[intentOfArgIndex] = newIntent;
args[1] = mHostContext.getPackageName();
} else {
Log.w(TAG, "startActivity,replace selectProxyActivity fail");
}
}
}
}
 
private void setIntentClassLoader(Intent intent, ClassLoader classLoader) {
try {
Bundle mExtras = (Bundle) FieldUtils.readField(intent, "mExtras");
if (mExtras != null) {
mExtras.setClassLoader(classLoader);
} else {
Bundle value = new Bundle();
value.setClassLoader(classLoader);
FieldUtils.writeField(intent, "mExtras", value);
}
} catch (Exception e) {
} finally {
intent.setExtrasClassLoader(classLoader);
}
}
 
protected void doReplaceIntentForStartActivityAPILow(Object[] args) throws RemoteException {
int intentOfArgIndex = findFirstIntentIndexInArgs(args);
if (args != null && args.length > 1 && intentOfArgIndex >= 0) {
Intent intent = (Intent) args[intentOfArgIndex];
ActivityInfo activityInfo = resolveActivity(intent);
if (activityInfo != null && isPackagePlugin(activityInfo.packageName)) {
ComponentName component = selectProxyActivity(intent);
if (component != null) {
Intent newIntent = new Intent();
newIntent.setComponent(component);
newIntent.putExtra(Env.EXTRA_TARGET_INTENT, intent);
if (TextUtils.equals(mHostContext.getPackageName(), activityInfo.packageName)) {
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
args[intentOfArgIndex] = newIntent;
} else {
Log.w(TAG, "startActivity,replace selectProxyActivity fail");
}
}
}
}
 
@Override
protected boolean beforeInvoke(Object receiver, Method method, Object[] args) throws Throwable {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
doReplaceIntentForStartActivityAPILow(args);
} else {
doReplaceIntentForStartActivityAPIHigh(args);
}
return super.beforeInvoke(receiver, method, args);
}
}

看到:版本18以前和以后的处理方式是不同的, 我们以版本低的为例
处理的步骤: 
1. 找到反射中的intent
2. 根据intent解析为activityInfo
3. 判断是否需要插件来打开,如果不是,不需要处理
4. 如果是,找到对应的代理的acitivity
5. 替换反射中的intent

   
protected void doReplaceIntentForStartActivityAPILow(Object[] args) throws RemoteException {
int intentOfArgIndex = findFirstIntentIndexInArgs(args);
if (args != null && args.length > 1 && intentOfArgIndex >= 0) {
Intent intent = (Intent) args[intentOfArgIndex];
ActivityInfo activityInfo = resolveActivity(intent);
if (activityInfo != null && isPackagePlugin(activityInfo.packageName)) {
ComponentName component = selectProxyActivity(intent);
if (component != null) {
Intent newIntent = new Intent();
newIntent.setComponent(component);
newIntent.putExtra(Env.EXTRA_TARGET_INTENT, intent);
if (TextUtils.equals(mHostContext.getPackageName(), activityInfo.packageName)) {
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
args[intentOfArgIndex] = newIntent;
} else {
Log.w(TAG, "startActivity,replace selectProxyActivity fail");
}
}
}
}




posted @ 2015-09-29 14:09  Panda Pan  阅读(23)  评论(0编辑  收藏  举报