Skip to content

Commit 7b06da2

Browse files
committed
Code Format
1 parent e1b9d83 commit 7b06da2

13 files changed

+383
-360
lines changed

PluginCore/src/com/plugin/core/PluginClassLoader.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import java.util.concurrent.LinkedBlockingQueue;
55

66
import com.plugin.content.PluginProviderInfo;
7-
import com.plugin.core.ui.stub.PluginStubReceiver;
87
import com.plugin.util.LogUtil;
98

109
import dalvik.system.DexClassLoader;
@@ -33,6 +32,12 @@ public PluginClassLoader(String dexPath, String optimizedDirectory, String libra
3332
super(dexPath, optimizedDirectory, libraryPath, parent);
3433
}
3534

35+
@Override
36+
public String findLibrary(String name) {
37+
LogUtil.d("findLibrary", name);
38+
return super.findLibrary(name);
39+
}
40+
3641
@Override
3742
protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException {
3843

PluginCore/src/com/plugin/core/PluginCompat.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.plugin.core;
22

33
import com.plugin.content.PluginDescriptor;
4-
import com.plugin.util.LogUtil;
54

65
import android.content.Context;
76
import android.os.Build;

PluginCore/src/com/plugin/core/PluginContentProviderInstaller.java

Lines changed: 0 additions & 35 deletions
This file was deleted.
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
package com.plugin.core;
2+
3+
import android.annotation.TargetApi;
4+
import android.app.Activity;
5+
import android.app.Application;
6+
import android.app.Instrumentation;
7+
import android.content.Context;
8+
import android.content.ContextWrapper;
9+
import android.content.Intent;
10+
import android.content.pm.ActivityInfo;
11+
import android.content.pm.ProviderInfo;
12+
import android.os.Build;
13+
import android.os.Handler;
14+
import android.view.ContextThemeWrapper;
15+
import android.view.LayoutInflater;
16+
17+
import com.plugin.content.PluginProviderInfo;
18+
import com.plugin.core.ui.PluginNormalFragmentActivity;
19+
import com.plugin.core.ui.stub.PluginStubActivity;
20+
import com.plugin.util.ClassLoaderUtil;
21+
import com.plugin.util.FragmentHelper;
22+
import com.plugin.util.LogUtil;
23+
import com.plugin.util.RefInvoker;
24+
25+
import java.util.ArrayList;
26+
import java.util.Collection;
27+
import java.util.List;
28+
29+
public class PluginInjector {
30+
31+
private static final String android_app_ActivityThread = "android.app.ActivityThread";
32+
private static final String android_app_ActivityThread_currentActivityThread = "currentActivityThread";
33+
private static final String android_app_ActivityThread_mInstrumentation = "mInstrumentation";
34+
private static final String android_app_ActivityThread_getHandler = "getHandler";
35+
private static final String android_app_ActivityThread_installContentProviders = "installContentProviders";
36+
37+
private static final String android_content_ContextWrapper_mBase = "mBase";
38+
39+
private static final String android_os_Handler_mCallback = "mCallback";
40+
41+
private static final String android_app_Activity_mInstrumentation = "mInstrumentation";
42+
private static final String android_app_Activity_mActivityInfo = "mActivityInfo";
43+
44+
private static final String android_content_ContextThemeWrapper_attachBaseContext = "attachBaseContext";
45+
private static final String android_content_ContextThemeWrapper_mResources = "mResources";
46+
private static final String android_content_ContextThemeWrapper_mTheme = "mTheme";
47+
48+
49+
/**
50+
* 替换宿主程序Application对象的mBase是为了修改它的几个StartActivity、
51+
* StartService和SendBroadcast方法
52+
*/
53+
static void injectBaseContext(Application application) {
54+
LogUtil.d("替换宿主程序Application对象的mBase");
55+
Context base = (Context)RefInvoker.getFieldObject(application, ContextWrapper.class.getName(),
56+
android_content_ContextWrapper_mBase);
57+
Context newBase = new PluginBaseContextWrapper(base);
58+
RefInvoker.setFieldObject(application, ContextWrapper.class.getName(),
59+
android_content_ContextWrapper_mBase, newBase);
60+
}
61+
62+
static Object getActivityThread() {
63+
// 从ThreadLocal中取出来的
64+
LogUtil.d("从宿主程序中取出ActivityThread对象备用");
65+
Object activityThread = RefInvoker.invokeStaticMethod(android_app_ActivityThread,
66+
android_app_ActivityThread_currentActivityThread,
67+
(Class[]) null, (Object[]) null);
68+
return activityThread;
69+
}
70+
71+
/**
72+
* 注入Instrumentation主要是为了支持Activity
73+
*/
74+
static void injectInstrumentation(Object activityThread) {
75+
// 给Instrumentation添加一层代理,用来实现隐藏api的调用
76+
LogUtil.d("替换宿主程序Intstrumentation");
77+
Instrumentation originalInstrumentation = (Instrumentation) RefInvoker.getFieldObject(activityThread,
78+
android_app_ActivityThread, android_app_ActivityThread_mInstrumentation);
79+
RefInvoker.setFieldObject(activityThread, android_app_ActivityThread,
80+
android_app_ActivityThread_mInstrumentation,
81+
new PluginInstrumentionWrapper(originalInstrumentation));
82+
}
83+
84+
static void injectHandlerCallback(Object activityThread) {
85+
LogUtil.d("向插入宿主程序消息循环插入回调器");
86+
Handler handler = (Handler) RefInvoker.invokeMethod(activityThread,
87+
android_app_ActivityThread, android_app_ActivityThread_getHandler,
88+
(Class[]) null, (Object[]) null);
89+
RefInvoker.setFieldObject(handler, Handler.class.getName(), android_os_Handler_mCallback,
90+
new PluginAppTrace(handler));
91+
}
92+
93+
static void installContentProviders(Context context, Collection<PluginProviderInfo> pluginProviderInfos) {
94+
LogUtil.d("安装插件ContentProvider", pluginProviderInfos.size());
95+
Object activityThread = PluginInjector.getActivityThread();
96+
if (activityThread != null) {
97+
ClassLoaderUtil.hackClassLoaderIfNeeded();
98+
List<ProviderInfo> providers = new ArrayList<ProviderInfo>();
99+
for (PluginProviderInfo pluginProviderInfo : pluginProviderInfos) {
100+
ProviderInfo p = new ProviderInfo();
101+
p.name = pluginProviderInfo.getName();
102+
p.authority = pluginProviderInfo.getAuthority();
103+
p.applicationInfo = context.getApplicationInfo();
104+
p.exported = pluginProviderInfo.isExported();
105+
p.packageName = context.getApplicationInfo().packageName;
106+
providers.add(p);
107+
}
108+
RefInvoker.invokeMethod(activityThread,
109+
android_app_ActivityThread, android_app_ActivityThread_installContentProviders,
110+
new Class[]{Context.class, List.class}, new Object[]{context, providers});
111+
}
112+
}
113+
114+
static void injectInstrumetionFor360Safe(Activity activity, Instrumentation pluginInstrumentation) {
115+
// 检查mInstrumention是否已经替换成功。
116+
// 之所以要检查,是因为如果手机上安装了360手机卫士等app,它们可能会劫持用户app的ActivityThread对象,
117+
// 导致在PluginApplication的onCreate方法里面替换mInstrumention可能会失败
118+
// 所以这里再做一次检查
119+
Instrumentation instrumention = (Instrumentation) RefInvoker.getFieldObject(activity, Activity.class.getName(),
120+
android_app_Activity_mInstrumentation);
121+
if (!(instrumention instanceof PluginInstrumentionWrapper)) {
122+
// 说明被360还原了,这里再次尝试替换
123+
RefInvoker.setFieldObject(activity, Activity.class.getName(), android_app_Activity_mInstrumentation, pluginInstrumentation);
124+
}
125+
}
126+
127+
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
128+
static void injectActivityContext(Activity activity) {
129+
Intent intent = activity.getIntent();
130+
// 如果是打开插件中的activity
131+
if (intent.getComponent() != null
132+
&& (intent.getComponent().getClassName().equals(PluginStubActivity.class.getName()) || intent
133+
.getComponent().getClassName().equals(PluginNormalFragmentActivity.class.getName()))) {
134+
// 为了不需要重写插件Activity的attachBaseContext方法为:
135+
// @Override
136+
// protected void attachBaseContext(Context newBase) {
137+
// super.attachBaseContext(PluginLoader.getDefaultPluginContext(PluginNotInManifestActivity.class));
138+
// }
139+
// 我们在activityoncreate之前去完成attachBaseContext的事情
140+
141+
142+
Context pluginContext = null;
143+
if (activity.getClass().getName().equals(PluginNormalFragmentActivity.class.getName())) {
144+
// 为了能够在宿主中的Activiy里面展示来自插件的普通Fragment,
145+
// 我们将宿主程序中用来展示插件普通Fragment的Activity的Context也替换掉
146+
String classId = activity.getIntent().getStringExtra(FragmentHelper.FRAGMENT_ID_IN_PLUGIN);
147+
@SuppressWarnings("rawtypes")
148+
Class clazz = PluginLoader.loadPluginFragmentClassById(classId);
149+
pluginContext = PluginLoader.getNewPluginContext(clazz);
150+
} else {
151+
pluginContext = PluginLoader.getNewPluginContext(activity.getClass());
152+
}
153+
154+
// 重设BaseContext
155+
RefInvoker.setFieldObject(activity, ContextWrapper.class.getName(), android_content_ContextWrapper_mBase, null);
156+
RefInvoker.invokeMethod(activity, ContextThemeWrapper.class.getName(), android_content_ContextThemeWrapper_attachBaseContext,
157+
new Class[]{Context.class }, new Object[] { pluginContext });
158+
159+
// 重设LayoutInflater
160+
LogUtil.d(activity.getWindow().getClass().getName());
161+
RefInvoker.setFieldObject(activity.getWindow(), activity.getWindow().getClass().getName(),
162+
"mLayoutInflater", LayoutInflater.from(pluginContext));
163+
164+
// 如果api>=11,还要重设factory2
165+
if (Build.VERSION.SDK_INT >= 11) {
166+
RefInvoker.invokeMethod(activity.getWindow().getLayoutInflater(), LayoutInflater.class.getName(),
167+
"setPrivateFactory", new Class[] { LayoutInflater.Factory2.class }, new Object[] { activity });
168+
}
169+
170+
// 由于在attach的时候Resource已经被初始化了,所以还需要重置Resource
171+
RefInvoker.setFieldObject(activity, ContextThemeWrapper.class.getName(), android_content_ContextThemeWrapper_mResources, null);
172+
173+
// 重设theme
174+
ActivityInfo activityInfo = (ActivityInfo) RefInvoker.getFieldObject(activity, Activity.class.getName(),
175+
android_app_Activity_mActivityInfo);
176+
int theme = activityInfo.getThemeResource();
177+
if (theme != 0) {
178+
RefInvoker.setFieldObject(activity, ContextThemeWrapper.class.getName(), android_content_ContextThemeWrapper_mTheme, null);
179+
activity.setTheme(theme);
180+
}
181+
} else {
182+
// 如果是打开宿主程序的activity,注入一个无害的Context,用来在宿主程序中startService和sendBroadcast时检查打开的对象是否是插件中的对象
183+
// 插入Context
184+
Context mainContext = new PluginBaseContextWrapper(activity.getBaseContext());
185+
RefInvoker.setFieldObject(activity, ContextWrapper.class.getName(), android_content_ContextWrapper_mBase, null);
186+
RefInvoker.invokeMethod(activity, ContextThemeWrapper.class.getName(), android_content_ContextThemeWrapper_attachBaseContext,
187+
new Class[]{Context.class }, new Object[] { mainContext });
188+
}
189+
}
190+
191+
192+
}

0 commit comments

Comments
 (0)