下面列出了android.app.Application#onCreate ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private void bindRealApplicatin() throws Exception {
if (isBindReal) {
return;
}
if (TextUtils.isEmpty(app_name)) {
return;
}
//1. 得到 attachBaseContext(context) 传入的上下文 ContextImpl
Context baseContext = getBaseContext();
//2. 拿到真实 APK APPlication 的 class
Class<?> delegateClass = Class.forName(app_name);
//3. 反射实例化,其实 Android 中四大组件都是这样实例化的。
delegate = (Application) delegateClass.newInstance();
//3.1 得到 Application attach() 方法 也就是最先初始化的
Method attach = Application.class.getDeclaredMethod("attach", Context.class);
attach.setAccessible(true);
//执行 Application#attach(Context)
//3.2 将真实的 Application 和假的 Application 进行替换。想当于自己手动控制 真实的 Application 生命周期
attach.invoke(delegate, baseContext);
// ContextImpl---->mOuterContext(app) 通过Application的attachBaseContext回调参数获取
//4. 拿到 Context 的实现类
Class<?> contextImplClass = Class.forName("android.app.ContextImpl");
//4.1 获取 mOuterContext Context 属性
Field mOuterContextField = contextImplClass.getDeclaredField("mOuterContext");
mOuterContextField.setAccessible(true);
//4.2 将真实的 Application 交于 Context 中。这个根据源码执行,实例化 Application 下一个就行调用 setOuterContext 函数,所以需要绑定 Context
// app = mActivityThread.mInstrumentation.newApplication(
// cl, appClass, appContext);
// appContext.setOuterContext(app);
mOuterContextField.set(baseContext, delegate);
// ActivityThread--->mAllApplications(ArrayList) ContextImpl的mMainThread属性
//5. 拿到 ActivityThread 变量
Field mMainThreadField = contextImplClass.getDeclaredField("mMainThread");
mMainThreadField.setAccessible(true);
//5.1 拿到 ActivityThread 对象
Object mMainThread = mMainThreadField.get(baseContext);
// ActivityThread--->>mInitialApplication
//6. 反射拿到 ActivityThread class
Class<?> activityThreadClass=Class.forName("android.app.ActivityThread");
//6.1 得到当前加载的 Application 类
Field mInitialApplicationField = activityThreadClass.getDeclaredField("mInitialApplication");
mInitialApplicationField.setAccessible(true);
//6.2 将 ActivityThread 中的 Applicaiton 替换为 真实的 Application 可以用于接收相应的声明周期和一些调用等
mInitialApplicationField.set(mMainThread,delegate);
// ActivityThread--->mAllApplications(ArrayList) ContextImpl的mMainThread属性
//7. 拿到 ActivityThread 中所有的 Application 集合对象,这里是多进程的场景
Field mAllApplicationsField = activityThreadClass.getDeclaredField("mAllApplications");
mAllApplicationsField.setAccessible(true);
ArrayList<Application> mAllApplications =(ArrayList<Application>) mAllApplicationsField.get(mMainThread);
//7.1 删除 ProxyApplication
mAllApplications.remove(this);
//7.2 添加真实的 Application
mAllApplications.add(delegate);
// LoadedApk------->mApplication ContextImpl的mPackageInfo属性
//8. 从 ContextImpl 拿到 mPackageInfo 变量
Field mPackageInfoField = contextImplClass.getDeclaredField("mPackageInfo");
mPackageInfoField.setAccessible(true);
//8.1 拿到 LoadedApk 对象
Object mPackageInfo=mPackageInfoField.get(baseContext);
//9 反射得到 LoadedApk 对象
// @Override
// public Context getApplicationContext() {
// return (mPackageInfo != null) ?
// mPackageInfo.getApplication() : mMainThread.getApplication();
// }
Class<?> loadedApkClass=Class.forName("android.app.LoadedApk");
Field mApplicationField = loadedApkClass.getDeclaredField("mApplication");
mApplicationField.setAccessible(true);
//9.1 将 LoadedApk 中的 Application 替换为 真实的 Application
mApplicationField.set(mPackageInfo,delegate);
//修改ApplicationInfo className LooadedApk
//10. 拿到 LoadApk 中的 mApplicationInfo 变量
Field mApplicationInfoField = loadedApkClass.getDeclaredField("mApplicationInfo");
mApplicationInfoField.setAccessible(true);
//10.1 根据变量反射得到 ApplicationInfo 对象
ApplicationInfo mApplicationInfo = (ApplicationInfo)mApplicationInfoField.get(mPackageInfo);
//10.2 将我们真实的 APPlication ClassName 名称赋值于它
mApplicationInfo.className=app_name;
//11. 执行 代理 Application onCreate 声明周期
delegate.onCreate();
//解码完成
isBindReal = true;
}
public Application createApplication(Class class1)
{
assertNull("Application already created", application);
Application application1;
try
{
application1 = Instrumentation.newApplication(class1, getContext());
}
catch (Exception exception)
{
throw new RuntimeException((new StringBuilder()).append("Could not create application ").append(class1).toString(), exception);
}
application1.onCreate();
application = application1;
return application1;
}
@Override
public void onCreate() {
super.onCreate();
if (!TextUtils.isEmpty(realApplication)) {
Application app = ClassLoaderDelegate.changeTopApplication(realApplication);
if (app != null) {
app.onCreate();
}
}
}
private void starting() {
if (RuntimeVariables.safeMode) {
return;
}
if (BaselineInfoManager.instance().isUpdated("com.taobao.maindex")) {
// AdditionalPackageManager.getInstance();
}
long time = System.currentTimeMillis();
android.os.Bundle metaData = null;
try {
ApplicationInfo applicationInfo = RuntimeVariables.androidApplication.getPackageManager().getApplicationInfo(RuntimeVariables.androidApplication.getPackageName(),
PackageManager.GET_META_DATA);
metaData = applicationInfo.metaData;
} catch (NameNotFoundException e1) {
e1.printStackTrace();
}
if (metaData != null) {
String strApps = metaData.getString("application");
if (StringUtils.isNotEmpty(strApps)) {
String[] appClassNames = StringUtils.split(strApps, ",");
if (appClassNames == null || appClassNames.length == 0) {
appClassNames = new String[]{strApps};
}
for (String appClassName : appClassNames) {
try {
Application app = newApplication(appClassName,
Framework.getSystemClassLoader());
app.onCreate();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
final long timediff = System.currentTimeMillis() - time;
}
@Override
public void onCreate() {
super.onCreate();
Log.e(TAG, "onCreate " + (++initCount));
// 签名检查
SignatureUtils.checkSign(getApplicationContext()); // 注意:不要在attachBaseContext方法中调用,因为应用上下文还没初始化完成
if (!TextUtils.isEmpty(srcAppClassName)) {
Application app = changeTopApplication(srcAppClassName);
if (app != null) {
app.onCreate();
} else {
Log.e(TAG, "changeTopApplication failure!!!");
}
}
}
private void starting() {
Bundle bundle;
long currentTimeMillis = System.currentTimeMillis();
try {
bundle = RuntimeVariables.androidApplication.getPackageManager().getApplicationInfo(RuntimeVariables.androidApplication.getPackageName(), TBImageQuailtyStrategy.CDN_SIZE_128).metaData;
} catch (NameNotFoundException e) {
e.printStackTrace();
bundle = null;
}
if (bundle != null) {
String string = bundle.getString("application");
if (StringUtils.isNotEmpty(string)) {
if (log.isDebugEnabled()) {
log.debug("Found extra application: " + string);
}
String[] split = StringUtils.split(string, SymbolExpUtil.SYMBOL_COMMA);
if (split == null || split.length == 0) {
split = new String[]{string};
}
for (String str : r0) {
try {
Application newApplication = BundleLifecycleHandler.newApplication(str, Framework.getSystemClassLoader());
newApplication.onCreate();
DelegateComponent.apkApplications.put("system:" + str, newApplication);
} catch (Throwable e2) {
log.error("Error to start application", e2);
}
}
}
}
log.info("starting() spend " + (System.currentTimeMillis() - currentTimeMillis) + " milliseconds");
}
@Override
@SuppressWarnings("unchecked")
public void onCreate() {
super.onCreate();
String appClassName = getOriginApplicationName();
if (appClassName == null) {
loadXposedModule(this);
return;
}
//有值的话调用该Applicaiton
Object currentActivityThread = currentActivityThread();
Object mBoundApplication = XposedHelpers.getObjectField("currentActivityThread", "mBoundApplication");
Object loadedApkInfo = XposedHelpers.getObjectField(mBoundApplication, "info");
//把当前进程的mApplication 设置成了null
XposedHelpers.setObjectField(loadedApkInfo, "mApplication", null);
Application oldApplication = (Application) XposedHelpers.getObjectField(currentActivityThread, "mInitialApplication");
//http://www.codeceo.com/article/android-context.html
ArrayList<Application> mAllApplications = (ArrayList<Application>) XposedHelpers.getObjectField(currentActivityThread, "mAllApplications");
mAllApplications.remove(oldApplication);//删除oldApplication
ApplicationInfo appinfoInLoadedApk = (ApplicationInfo) XposedHelpers.getObjectField(loadedApkInfo, "mApplicationInfo");
ApplicationInfo appinfoInAppBindData = (ApplicationInfo) XposedHelpers.getObjectField(mBoundApplication, "appInfo");
appinfoInLoadedApk.className = appClassName;
appinfoInAppBindData.className = appClassName;
loadXposedModule(this);
//makeApplication 的时候,就会调用attachBaseContext方法
Application app = (Application) XposedHelpers.callMethod(loadedApkInfo, "makeApplication", false, null);
XposedHelpers.setObjectField(currentActivityThread, "mInitialApplication", app);
ArrayMap mProviderMap = (ArrayMap) XposedHelpers.getObjectField(currentActivityThread, "mProviderMap");
for (Object providerClientRecord : mProviderMap.values()) {
Object localProvider = XposedHelpers.getObjectField(providerClientRecord, "mLocalProvider");
XposedHelpers.setObjectField(localProvider, "mContext", app);
}
app.onCreate();
}
@Override
public void onCreate() {
// 如果源应用配置有Appliction对象,则替换为源应用Applicaiton,以便不影响源程序逻辑。
String appClassName = null;
//获取xml文件里配置的被加壳apk的Applicaiton
try {
ApplicationInfo ai = this.getPackageManager()
.getApplicationInfo(this.getPackageName(),
PackageManager.GET_META_DATA);
Bundle bundle = ai.metaData;
if (bundle != null
&& bundle.containsKey("APPLICATION_CLASS_NAME")) {
appClassName = bundle.getString("APPLICATION_CLASS_NAME");//className 是配置在xml文件中的。
} else {
return;
}
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//有值的话调用该Applicaiton
Object currentActivityThread = RefInvokeUtil.invokeStaticMethod(
"android.app.ActivityThread", "currentActivityThread",
new Class[]{}, new Object[]{});
Object mBoundApplication = RefInvokeUtil.getFieldOjbect(
"android.app.ActivityThread", currentActivityThread,
"mBoundApplication");
Object loadedApkInfo = RefInvokeUtil.getFieldOjbect(
"android.app.ActivityThread$AppBindData",
mBoundApplication, "info");
//把当前进程的mApplication 设置成了null
RefInvokeUtil.setFieldOjbect("android.app.LoadedApk", "mApplication",
loadedApkInfo, null);
Object oldApplication = RefInvokeUtil.getFieldOjbect(
"android.app.ActivityThread", currentActivityThread,
"mInitialApplication");
//http://www.codeceo.com/article/android-context.html
ArrayList<Application> mAllApplications = (ArrayList<Application>) RefInvokeUtil
.getFieldOjbect("android.app.ActivityThread",
currentActivityThread, "mAllApplications");
mAllApplications.remove(oldApplication);//删除oldApplication
ApplicationInfo appinfo_In_LoadedApk = (ApplicationInfo) RefInvokeUtil
.getFieldOjbect("android.app.LoadedApk", loadedApkInfo,
"mApplicationInfo");
ApplicationInfo appinfo_In_AppBindData = (ApplicationInfo) RefInvokeUtil
.getFieldOjbect("android.app.ActivityThread$AppBindData",
mBoundApplication, "appInfo");
appinfo_In_LoadedApk.className = appClassName;
appinfo_In_AppBindData.className = appClassName;
Application app = (Application) RefInvokeUtil.invokeMethod(
"android.app.LoadedApk", "makeApplication", loadedApkInfo,
new Class[]{boolean.class, Instrumentation.class},
new Object[]{false, null});//执行 makeApplication(false,null)
RefInvokeUtil.setFieldOjbect("android.app.ActivityThread",
"mInitialApplication", currentActivityThread, app);
HashMap mProviderMap = (HashMap) RefInvokeUtil.getFieldOjbect(
"android.app.ActivityThread", currentActivityThread,
"mProviderMap");
Iterator it = mProviderMap.values().iterator();
while (it.hasNext()) {
Object providerClientRecord = it.next();
Object localProvider = RefInvokeUtil.getFieldOjbect(
"android.app.ActivityThread$ProviderClientRecord",
providerClientRecord, "mLocalProvider");
RefInvokeUtil.setFieldOjbect("android.content.ContentProvider",
"mContext", localProvider, app);
}
app.onCreate();
}
private void started(Bundle bundle) {
BundleImpl bundleImpl = (BundleImpl) bundle;
long currentTimeMillis = System.currentTimeMillis();
if (OpenAtlasInternalConstant.CODE_ENABLE_COMPILE) {//no used OSGI.MF any more,disable compile this code
String mBundleApplicationNames = bundleImpl.getHeaders().get("Bundle-Application");
if (StringUtils.isNotEmpty(mBundleApplicationNames)) {
String[] bundleApplications;
String[] split = StringUtils.split(mBundleApplicationNames, ",");
if (split == null || split.length == 0) {
bundleApplications = new String[]{mBundleApplicationNames};
} else {
bundleApplications = split;
}
if (bundleApplications != null) {
for (String bundleApplication : bundleApplications) {
String trim = StringUtils.trim(bundleApplication);
if (StringUtils.isNotEmpty(trim)) {
try {
boolean needInit = true;
for (Application initedApplication : DelegateComponent.apkApplications.values()) {
if (initedApplication.getClass().getName().equals(trim)) {
needInit = false;
break;
}
}
if (needInit) {
Application newApplication = newApplication(trim, bundleImpl.getClassLoader());
newApplication.onCreate();
DelegateComponent.apkApplications.put("system:" + trim, newApplication);
}
} catch (Throwable th) {
log.error("Error to start application", th);
}
}
}
}
return;
}
}
{
PackageLite packageLite = DelegateComponent.getPackage(bundleImpl.getLocation());
if (packageLite != null) {
String applicationClassName = packageLite.applicationClassName;
if (StringUtils.isNotEmpty(applicationClassName)) {
try {
newApplication(applicationClassName, bundleImpl.getClassLoader()).onCreate();
} catch (Throwable throwable) {
log.error("Error to start application >>>", throwable);
}
}
}
}
log.info("started() spend " + (System.currentTimeMillis() - currentTimeMillis) + " milliseconds");
}
private void started(Bundle bundle) {
BundleImpl bundleImpl = (BundleImpl) bundle;
long currentTimeMillis = System.currentTimeMillis();
String str = (String) bundleImpl.getHeaders().get("Bundle-Application");
if (StringUtils.isNotEmpty(str)) {
String[] strArr;
String[] split = StringUtils.split(str, SymbolExpUtil.SYMBOL_COMMA);
if (split == null || split.length == 0) {
strArr = new String[]{str};
} else {
strArr = split;
}
if (strArr != null) {
for (String str2 : strArr) {
String trim = StringUtils.trim(str2);
if (StringUtils.isNotEmpty(trim)) {
try {
Application newApplication;
int i;
for (Application newApplication2 : DelegateComponent.apkApplications.values()) {
if (newApplication2.getClass().getName().equals(trim)) {
i = 1;
break;
}
}
i = 0;
if (i == 0) {
newApplication2 = newApplication(trim, bundleImpl.getClassLoader());
newApplication2.onCreate();
DelegateComponent.apkApplications.put("system:" + trim, newApplication2);
}
} catch (Throwable th) {
log.error("Error to start application", th);
}
}
}
}
} else {
PackageLite packageLite = DelegateComponent.getPackage(bundleImpl.getLocation());
if (packageLite != null) {
str2 = packageLite.applicationClassName;
if (StringUtils.isNotEmpty(str2)) {
try {
newApplication(str2, bundleImpl.getClassLoader()).onCreate();
} catch (Throwable th2) {
log.error("Error to start application >>>", th2);
}
}
}
}
log.info("started() spend " + (System.currentTimeMillis() - currentTimeMillis) + " milliseconds");
}