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");
}
}
}
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章