启动流程图参照Activity插件化(一)之hookIActivityManager
根据流程图可看出Instrumentation这个类在AMS检查前和检查后都会调用到这个类,所以我们看下那里持有这个类的实例,通过流程图看了Instrumentation调用前后几个类发现ActivityThread和Activity都持有这个类的实例,所以有两种方法可以hook ActivityThread和hook Activity。下面分析ActivityThread的
public final class ActivityThread extends ClientTransactionHandler {
private static volatile ActivityThread sCurrentActivityThread;
Instrumentation mInstrumentation;
String mInstrumentationPackageName = null;
String mInstrumentationAppDir = null;
String[] mInstrumentationSplitAppDirs = null;
String mInstrumentationLibDir = null;
String mInstrumentedAppDir = null;
String[] mInstrumentedSplitAppDirs = null;
String mInstrumentedLibDir = null;
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
.....
return activity;
}
}
Instrumentation类
public class Instrumentation {
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
Uri referrer = target != null ? target.onProvideReferrer() : null;
if (referrer != null) {
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
ActivityResult result = null;
if (am.ignoreMatchingSpecificIntents()) {
result = am.onStartActivity(intent);
}
if (result != null) {
am.mHits++;
return result;
} else if (am.match(who, null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
String pkg = intent != null && intent.getComponent() != null
? intent.getComponent().getPackageName() : null;
return getFactory(pkg).instantiateActivity(cl, className, intent);
}
}
实现:
public static void hookActivityThread(){
try{
//获取ActivityThread
Class<?> atClass = Class.forName("android.app.ActivityThread");
//获取Activity里面的sCurrentActivityThread
Field sCurrentActivityThreadField = atClass.getDeclaredField("sCurrentActivityThread");
sCurrentActivityThreadField.setAccessible(true);
//由于是static 所以get的时候不用object传null就可以了
Object sCurrentActivityThread = sCurrentActivityThreadField.get(null);
//获取ActivityThread的mInstrumentation
Field mInstrumentationField = atClass.getDeclaredField("mInstrumentation");
mInstrumentationField.setAccessible(true);
//获取mInstrumentation对象 设置静态代理
Instrumentation mInstrumentation = (Instrumentation) mInstrumentationField.get(sCurrentActivityThread);
Instrumentation proxy = new InstrumentationProxy(mInstrumentation);
//把代理对象设置到ActivityThread里面
mInstrumentationField.set(sCurrentActivityThread,proxy);
}catch (Exception e){
e.printStackTrace();
}
}
静态代理Instrumentation类
public class InstrumentationProxy extends Instrumentation {
private static final String TARGET_INTENT = "target_intent";
private Instrumentation mInstrumentation;
private PackageManager mPackageManager;
private static final String TAG = "=======";
public InstrumentationProxy(Instrumentation instrumentation,PackageManager packageManager){
mInstrumentation = instrumentation;
mPackageManager = packageManager;
}
public InstrumentationProxy(Instrumentation instrumentation) {
mInstrumentation = instrumentation;
}
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
Log.e(TAG, "execStartActivity start" );
try {
intent.putExtra(TARGET_INTENT, intent.getComponent().getClassName());
// //设置为占坑Activity
intent.setClassName(who, "com.bzm.hook.StubActivity");
boolean intentIsNull = intent == null;
Log.e(TAG, "execStartActivity: " + intent.getComponent().toString() + intentIsNull );
Method execStartActivityMethod = Instrumentation.class.getDeclaredMethod(
"execStartActivity",Context.class,IBinder.class,IBinder.class,Activity.class
,Intent.class,int.class,Bundle.class);
execStartActivityMethod.setAccessible(true);
Log.e(TAG, "execStartActivity: " + execStartActivityMethod.getName() );
ActivityResult result = (ActivityResult)execStartActivityMethod.invoke
(mInstrumentation,who,contextThread,token,target,intent,requestCode,options);
return result;
} catch (Exception e) {
Log.e(TAG, "execStartActivity Exception: " + e.getMessage() );
e.printStackTrace();
}
Log.e(TAG, "return null ");
return null;
}
public Activity newActivity(ClassLoader cl, String className,
Intent intent) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
Log.e(TAG, "newActivity: " );
String clazName = intent.getStringExtra(TARGET_INTENT);
if (!TextUtils.isEmpty(clazName)){
return mInstrumentation.newActivity(cl,clazName,intent);
}
return mInstrumentation.newActivity(cl,className,intent);
}
}
启动Activity
public void hookAt(View view) {
//第二种方法
HookActivityUtils.hookActivityThread();
Intent intent = new Intent(this, TargetActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//需要Context来启动Activity
getApplicationContext().startActivity(intent);
}