package com.qianfandu;
import android.annotation.TargetApi;
import android.app.Application;
import android.app.Instrumentation;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
import com.qianfandu.utils.ApkToolPlus;
import com.qianfandu.utils.DexProtector;
import com.qianfandu.utils.Reflect;
import com.qianfandu.utils.SignatureUtils;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
public class ProxyApplication extends Application {
private static final String TAG = ProxyApplication.class.getSimpleName();
private static int initCount = 0;
private String srcAppClassName = null;
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
ApkToolPlus.loadLibrary();
// 自定义ClassLoader
try {
Log.e(TAG, "init app " + (++initCount));
String[] dexName=getAssets().list("jiagu_data.bin");
ClassLoader classLoader = new DexProtector(this).loadEncryptDex(dexName);
if (classLoader == null) {
Log.e(TAG, "loadEncryptDex fail");
} else {
Log.e(TAG, "loadEncryptDex success");
String appClassName = getSrcAppClassName();
if (!TextUtils.isEmpty(appClassName)) {
srcAppClassName = appClassName;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取原来Applicatoin的类名
*
* @return
*/
private String getSrcAppClassName() {
try {
PackageManager packageManager = getPackageManager();
if (packageManager != null) {
ApplicationInfo applicationInfo = packageManager.getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
if (applicationInfo != null) {
if (applicationInfo.metaData != null) {
return applicationInfo.metaData.getString("apktoolplus_jiagu_app");
}
}
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return null;
}
/**
* 获取原来Application的实例
*
* @param classLoader
* @param appClassName
* @return
*/
private Application getSrcAppInstance(ClassLoader classLoader, String appClassName) {
try {
// 反射出原来的applicatoin
Class<?> appClass = classLoader.loadClass(appClassName);
return (Application) appClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// 修改应用上下文
// http://blog.csdn.net/jltxgcy/article/details/50540309
@TargetApi(Build.VERSION_CODES.KITKAT)
private Application changeTopApplication(String appClassName) {
//有值的话调用该Applicaiton
Object currentActivityThread = Reflect.invokeStaticMethod(
"android.app.ActivityThread", "currentActivityThread",
new Class[] {}, new Object[] {});
Object mBoundApplication = Reflect.getFieldValue(
"android.app.ActivityThread", currentActivityThread,
"mBoundApplication");
Object loadedApkInfo = Reflect.getFieldValue(
"android.app.ActivityThread$AppBindData",
mBoundApplication, "info");
//把当前进程的mApplication 设置成了null
Reflect.setFieldValue("android.app.LoadedApk", loadedApkInfo, "mApplication", null);
Object oldApplication = Reflect.getFieldValue(
"android.app.ActivityThread", currentActivityThread,
"mInitialApplication");
//http://www.codeceo.com/article/android-context.html
ArrayList<Application> mAllApplications = (ArrayList<Application>) Reflect
.getFieldValue("android.app.ActivityThread",
currentActivityThread, "mAllApplications");
mAllApplications.remove(oldApplication);//删除oldApplication
ApplicationInfo loadedApk = (ApplicationInfo) Reflect
.getFieldValue("android.app.LoadedApk", loadedApkInfo,
"mApplicationInfo");
ApplicationInfo appBindData = (ApplicationInfo) Reflect
.getFieldValue("android.app.ActivityThread$AppBindData",
mBoundApplication, "appInfo");
loadedApk.className = appClassName;
appBindData.className = appClassName;
Application app = (Application) Reflect.invokeMethod(
"android.app.LoadedApk", loadedApkInfo, "makeApplication",
new Object[]{false, null},
boolean.class, Instrumentation.class);//执行 makeApplication(false,null)
Reflect.setFieldOjbect("android.app.ActivityThread",
"mInitialApplication", currentActivityThread, app);
ArrayMap mProviderMap = (ArrayMap) Reflect.getFieldOjbect(
"android.app.ActivityThread", currentActivityThread,
"mProviderMap");
Iterator it = mProviderMap.values().iterator();
while (it.hasNext()) {
Object providerClientRecord = it.next();
Object localProvider = Reflect.getFieldOjbect(
"android.app.ActivityThread$ProviderClientRecord",
providerClientRecord, "mLocalProvider");
Reflect.setFieldOjbect("android.content.ContentProvider",
"mContext", localProvider, app);
}
return app;
}
@Override
public void onCreate() {
// 签名检查
SignatureUtils.checkSign(getApplicationContext()); // 注意:不要在attachBaseContext方法中调用,因为应用上下文还没初始化完成
if (!TextUtils.isEmpty(srcAppClassName)) {
Application app = changeTopApplication(srcAppClassName);
if (app != null) {
app.onCreate();
} else {
Log.e(TAG, "changeTopApplication failure!!!");
}
}
}
}