Hook技术(四)对系统启动Activity进行Hook之偷梁换柱Activity

引出问题

我们如果要启动一个activity,我们的做法是1. 在AndroidManifest.xml中声明一个Activity 2. startActivity,如果不在AndroidManifest.xml中声明,启动activity会报错(android.content.ActivityNotFoundException)。但是我们想,我们使用插件化,按照正常的思维是不是要将插件化中的所有activity都要声明到清单文件中才可以。所以引出了我们今天的知识点:hook系统启动activity。通过hook我们对AndroidManifest.xml文件中的activity进行偷梁换柱,换成我们没有注册在清单文件中的activity,这样就达到了我们的目的。

系统源码流程

通过对系统源码的了解,我们才能知道从哪里hook合适。

对于系统源码这部分,我会随着经验的积累给这些方法里面添加一些核心的内容,但是这部分不影响我们今天的讲解,所以也可以不看这部分,直接看结论就好。

image

图片来自于(gityuan)

系统源码目录

frameworks/base/services/core/java/com/android/server/am/
  - ActivityManagerService.java
  - ActivityStackSupervisor.java
  - ActivityStack.java
  - ActivityRecord.java
  - ProcessRecord.java

frameworks/base/core/java/android/app/
  - IActivityManager.java
  - ActivityManagerNative.java (内含AMP)
  - ActivityManager.java

  - IApplicationThread.java
  - ApplicationThreadNative.java (内含ATP)
  - ActivityThread.java (内含ApplicationThread)

  - ContextImpl.java

1.1 Activity.startActivity

public void startActivity(Intent intent) {
    this.startActivity(intent, null);
}

public void startActivity(Intent intent, @Nullable Bundle options) {
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        startActivityForResult(intent, -1);//[见1.2]
    }
}

1.2 Activity.startActivityForResult

public void startActivityForResult(Intent intent, int requestCode) {
    startActivityForResult(intent, requestCode, null);
}

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
    if (mParent == null) {
        //[见1.3]
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);
        if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                ar.getResultData());
        }
        //此时requestCode =-1
        if (requestCode >= 0) {
            mStartedActivity = true;
        }
        cancelInputsAndStartExitTransition(options);
    } else {
        ...
    }
}

1.3 Instrumentation.execStartActivity()

  • caller: 当前应用的ApplicationThread对象mAppThread;
  • callingPackage: 调用当前ContextImpl.getBasePackageName(),获取当前Activity所在包名;
  • intent: 这便是启动Activity时,传递过来的参数;
  • resolvedType: 调用intent.resolveTypeIfNeeded而获取;
  • resultTo: 来自于当前Activity.mToken
  • resultWho: 来自于当前Activity.mEmbeddedID
  • requestCode = -1;
  • startFlags = 0;
  • profilerInfo = null;
  • options = null;
public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) {

    IApplicationThread whoThread = (IApplicationThread) contextThread;
    ...
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess();
        ...
        //[见1.4]
        int result = ActivityManagerNative.getDefault()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);
        //检查activity是否启动成功[1.3.1]
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

1.3.1 Instrumentation.checkStartActivityResult()

public class Instrumentation {
    /** @hide */
    public static void checkStartActivityResult(int res, Object intent) {
        if (!ActivityManager.isStartResultFatalError(res)) {
            return;
        }

        switch (res) {
            case ActivityManager.START_CLASS_NOT_FOUND:
                if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
                    throw new ActivityNotFoundException(
                            "Unable to find explicit activity class "
                            + ((Intent)intent).getComponent().toShortString()
                            + "; have you declared this activity in your AndroidManifest.xml?");
                throw new ActivityNotFoundException("No Activity found to handle " + intent);
            ...
        }
}

1.4 ActivityManagerProxy.startActivity()

class ActivityManagerProxy implements IActivityManager {
    ...
    public int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
        //通过Binder传递数据
        ...
        //[见2.1]
        intent.writeToParcel(data, 0);//将Intent写入Binder
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
        ...
        return result;
    }
    ...
}

==AMP经过binder IPC,进入ActivityManagerNative(简称AMN)。接下来程序进入了system_servr进程,开始继续执行==

2.1 ActivityManagerNative.onTransact()

public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
    switch (code) {
    case START_ACTIVITY_TRANSACTION:
    {  
      ...
      Intent intent = Intent.CREATOR.createFromParcel(data);
      ...
      //[见2.2]
      int result = startActivity(app, callingPackage, intent, resolvedType,resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
      ...
      return true;
    }
    ...
    }    
}

2.2 ActivityManagerService.startActivity

public final int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options) {
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
        resultWho, requestCode, startFlags, profilerInfo, options,
        UserHandle.getCallingUserId());
}

public final int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
    userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
            false, ALLOW_FULL_ONLY, "startActivity", null);
    //[2.3]
    return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
            resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
            profilerInfo, null, null, options, false, userId, null, null);
}

2.3 ActivityStackSupervisor.startActivityMayWait()

  • caller = ApplicationThreadProxy, 用于跟调用者进程ApplicationThread进行通信的binder代理类.
  • callingUid = -1;
  • callingPackage = ContextImpl.getBasePackageName(),获取调用者Activity所在包名
  • intent: 这是启动Activity时传递过来的参数;
  • resolvedType = intent.resolveTypeIfNeeded
  • voiceSession = null;
  • voiceInteractor = null;
  • resultTo = Activity.mToken, 其中Activity是指调用者所在Activity, mToken对象保存自己所处的ActivityRecord信息
  • resultWho = Activity.mEmbeddedID, 其中Activity是指调用者所在Activity
  • requestCode = -1;
  • startFlags = 0;
  • profilerInfo = null;
  • outResult = null;
  • config = null;
  • options = null;
  • ignoreTargetSecurity = false;
  • userId = AMS.handleIncomingUser, 当调用者userId跟当前处于同一个userId,则直接返回该userId;当不相等时则根据调用者userId来决定是否需要将callingUserId转换为mCurrentUserId.
  • iContainer = null;
  • inTask = null;
final int startActivityMayWait(IApplicationThread caller, int callingUid, String callingPackage, Intent intent, String resolvedType, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, WaitResult outResult, Configuration config, Bundle options, boolean ignoreTargetSecurity, int userId, IActivityContainer iContainer, TaskRecord inTask) {
    ...
    boolean componentSpecified = intent.getComponent() != null;
    //创建新的Intent对象,即便intent被修改也不受影响
    intent = new Intent(intent);
    ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);
    synchronized (mService) {
        //[见2.4]
        int res = startActivityLocked(caller, intent, resolvedType, aInfo,
                voiceSession, voiceInteractor, resultTo, resultWho,
                requestCode, callingPid, callingUid, callingPackage,
                realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
                componentSpecified, null, container, inTask);
    }
    ...
    return res;
}

2.4 ActivityStackSupervisor.startActivityLocked()

这里要注意的是如果err = ActivityManager.START_INTENT_NOT_RESOLVED;就会有1.3.1所述代码的异常。

final int startActivityLocked(IApplicationThread caller, Intent intent, String resolvedType, ActivityInfo aInfo, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, int realCallingPid, int realCallingUid, int startFlags, Bundle options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container, TaskRecord inTask) {
    ...
    if (err == ActivityManager.START_SUCCESS && aInfo == null) {
        //从Intent中无法找到相应的ActivityInfo
        err = ActivityManager.START_INTENT_NOT_RESOLVED;
    }
    ...
   //[见2.5]
    err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
            startFlags, true, options, inTask);
    ...
    return err;
}

2.5 ActivityStackSupervisor.startActivityUncheckedLocked()

// sourceRecord是指调用者, r是指本次将要启动的Activity
final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, Bundle options, TaskRecord inTask) {
    ...
    //创建activity [见2.6]
    targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);   
    ...
}

2.6 ActivityStack.startActivityLocked()

final void startActivityLocked(ActivityRecord r, boolean newTask, boolean doResume, boolean keepCurTransition, Bundle options) {
    if (doResume) {
        //[见2.7]
        mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
    }
}

2.7 ActivityStackSupervisor.resumeTopActivitiesLocked()

boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target, Bundle targetOptions) {
    ...
    if (isFrontStack(targetStack)) {
        //[见流程2.8]
        result = targetStack.resumeTopActivityLocked(target, targetOptions);
    }
    ...
}

2.8 AS.resumeTopActivityLocked

final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
    ...
    //[见2.9]
    result = resumeTopActivityInnerLocked(prev, options);
    return result;
}

2.9 AS.resumeTopActivityInnerLocked()

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
    ...
    //[2.10]
    mStackSupervisor.startSpecificActivityLocked(next, true, true);
    ...
}

2.10 ASS.startSpecificActivityLocked()

void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,r.info.applicationInfo.uid, true);
    //真正的启动Activity【见流程2.11】
    realStartActivityLocked(r, app, andResume, checkConfig);
    //当进程不存在则创建进程 [见2.12]
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false, false, true);
}

2.11 ASS.realStartActivityLocked()

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException {
    //[见2.12]
    app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
            System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
            new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
            task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
            newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);

}

2.12 ApplicationThreadProxy.scheduleLaunchActivity()

public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, Configuration overrideConfig, CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) throws RemoteException {

    //[见3.1]
    mRemote.transact(SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION, data, null,IBinder.FLAG_ONEWAY);
}

3.1 ApplicationThreadNative.onTransact()

public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException{
    //[见3.1]
    scheduleLaunchActivity(intent, b, ident, info, curConfig, overrideConfig, compatInfo,
            referrer, voiceInteractor, procState, state, persistentState, ri, pi,
            notResumed, isForward, profilerInfo);
}

3.1 ApplicationThread.scheduleLaunchActivity()

public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, Configuration overrideConfig, CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
     //[见3.2]
     sendMessage(H.LAUNCH_ACTIVITY, r);
 }

3.2 ActivityThread.java::H.handleMessage

public void handleMessage(Message msg) {
    switch (msg.what) {
        case LAUNCH_ACTIVITY: {
            final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
            r.packageInfo = getPackageInfoNoCheck(
                    r.activityInfo.applicationInfo, r.compatInfo);
            //[见3.3]
            handleLaunchActivity(r, null);
        } break;
        ...
    }
}

3.3 ActivityThread.handleLaunchActivity()

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ...
    //最终回调目标Activity的onCreate
    //见[3.4]
    Activity a = performLaunchActivity(r, customIntent);
    if (a != null) {
        //最终回调目标Activity的onStart,onResume.
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished && !r.startsNotResumed);

        if (!r.activity.mFinished && r.startsNotResumed) {
            r.activity.mCalled = false;
            mInstrumentation.callActivityOnPause(r.activity);
            r.paused = true;
        }
    } else {
        //存在error则停止该Activity
        ActivityManagerNative.getDefault()
            .finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
    }
}

3.4 ActivityThread.performLaunchActivity()

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
        //见[3.5]
        activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
        ...
    } catch (Exception e) {
        ...
    }
}

3.5 Instrumentation.newActivity()

public Activity newActivity(ClassLoader cl, String className,
        Intent intent)
        throws InstantiationException, IllegalAccessException,
        ClassNotFoundException {
    return (Activity)cl.loadClass(className).newInstance();
}

image

我们最后看到在ActivityThread.performLaunchActivity()方法中创建了Activity,在这个过程中我分别用1.2.3标记不同的进程,1.3分别是app进程,2是system_server进程。

  • 1标记的进程也就是app进程,主要将要启动的Activity信息(Activity名称,当前所在包名),当前应用的ApplicationThread对象,intent(传递进去的参数)等。
  • 2标记的进程也就是system_server进程,进行各种判断检查,信息保存,组件调度等等
  • 3标记的进程还是app进程,此时主要是创建Activity对象,回调各种回调方法,根据2标记的进程来的信息。

其中ActivityManagerNative.getDefault()得到的是AMS的代理,与AMS进行通信。代码如下:


private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
    protected IActivityManager create() {
        //获取名为"activity"的服务,服务都注册到ServiceManager来统一管理
        IBinder b = ServiceManager.getService("activity");
        IActivityManager am = asInterface(b);
        return am;
    }
};
public abstract class Singleton<T> {
    public final T get() {
        synchronized (this) {
            if (mInstance == null) {
                //首次调用create()来获取AMP对象
                mInstance = create();
            }
            return mInstance;
        }
    }
}

ActivityManagerNative.getDefault()

static public IActivityManager getDefault() {
    return gDefault.get();
}

gDefault为Singleton类型对象,此次采用单例模式,mInstance为IActivityManager类的代理对象,即ActivityManagerProxy。


那什么从AMS给APP通信呢?

Activity.startActivity()

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
    if (mParent == null) {
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), ...);...
    } else {
        ...
    }
}

我们看到调用startActivityForResult()这个方法的时候使用mMainThread.getApplicationThread()作为参数,这个参数得到的是什么?

public class Activity extends ... {
    ActivityThread mMainThread;
}

ActivityThread.java

public final class ActivityThread {
    final ApplicationThread mAppThread = new ApplicationThread();
    final H mH = new H();

    public ApplicationThread getApplicationThread()
    {
        return mAppThread;
    }

    /*内部类*/
    private class ApplicationThread extends IApplicationThread.Stub {
        private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
            Message msg = Message.obtain();
            msg.what = what;
            msg.obj = obj;
            msg.arg1 = arg1;
            msg.arg2 = arg2;
            if (async) {
                msg.setAsynchronous(true);
            }
            mH.sendMessage(msg);
        }
        ...
    }

    /*内部类*/
    private class H extends Handler {
        public void handleMessage(Message msg) {
            ...
        }
    }
}

从结构上看出来,是将ActivityThread的内部类ApplicationThread的对象传入AMS中。这个对象处理IApplicationThread接口所有方法都是利用ActivityThread类的成员变量H进行发送消息。也就是AMS通过ApplicationThread对象控制APP进程这端。所以app进程这边的实现逻辑全部在H类中

寻找hook点

我们并没有办法通过hook改变别的进程信息,比如AMS。而且通过源码我们知道最后创建Activity对象也是回归到App进程,所以我们就可以在app进程真正创建Activity对象的时候偷梁换柱。

比如我们有个废掉的Activity叫做StubActivity,这个Activity是在我们清单文件中声明了的,我们要启动TargetActivity。我们需要在Activity检查之前进行拦截,将我们的TargetActivity替换成StubActivity,这样系统就认为我们要启动StubActivity。而我们在hook的时候将TargetActivity信息保存下来,当系统确定要创建Activity的时候,我们在将信息还原。这个时候就创建的是TargetActivity。

所以我们hook点如下:

  1. 对ActivityManagerNative的Singleton gDefault对象中的mInstance进行hook,他是IActivityManager与AMS交互的Binder代理。
  2. 我们队ActivityThread.mH对象进行hook,更换mCallback,使得在LAUNCH_ACTIVITY这种情况偷换为TargetActivity的Intent信息。
项目代码解析

一:需要在清单文件中声明

<application>
    <!--随便声明一个替身Activity-->
    <activity android:name=".StubActivity"/>
</application>

二:一个空的Activity

public class StubActivity extends Activity{
    // dummy
}

三:对两个hook点进行hook

public class AMSHookHelper {

    public static final String EXTRA_TARGET_INTENT = "extra_target_intent";

    /**
     * 主要完成的操作是  "把真正要启动的Activity临时替换为在AndroidManifest.xml中声明的替身Activity"
     */
    public static void hookActivityManagerNative() throws Exception {
         Field gDefaultField =null;
        if (Build.VERSION.SDK_INT >= 26) {
            Class<?> activityManager = Class.forName("android.app.ActivityManager");
             gDefaultField = activityManager.getDeclaredField("IActivityManagerSingleton");
        }else{
            Class<?> activityManagerNativeClass = Class.forName("android.app.ActivityManagerNative");
             gDefaultField = activityManagerNativeClass.getDeclaredField("gDefault");
        }
        gDefaultField.setAccessible(true);
        Object gDefault = gDefaultField.get(null);
        // gDefault是一个 android.util.Singleton对象; 我们取出这个单例里面的字段
        Class<?> singleton = Class.forName("android.util.Singleton");
        Field mInstanceField = singleton.getDeclaredField("mInstance");
        mInstanceField.setAccessible(true);
        // ActivityManagerNative 的gDefault对象里面原始的 IActivityManager对象
        Object rawIActivityManager = mInstanceField.get(gDefault);
        // 创建一个这个对象的代理对象, 然后替换这个字段, 让我们的代理对象帮忙干活
        Class<?> iActivityManagerInterface = Class.forName("android.app.IActivityManager");
        Object proxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                new Class<?>[] { iActivityManagerInterface }, new IActivityManagerHandler(rawIActivityManager));
        mInstanceField.set(gDefault, proxy);
    }

    public static void hookActivityThreadHandler() throws Exception {

        // 先获取到当前的ActivityThread对象
        Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
        Field currentActivityThreadField = activityThreadClass.getDeclaredField("sCurrentActivityThread");
        currentActivityThreadField.setAccessible(true);
        Object currentActivityThread = currentActivityThreadField.get(null);

        // 由于ActivityThread一个进程只有一个,我们获取这个对象的mH
        Field mHField = activityThreadClass.getDeclaredField("mH");
        mHField.setAccessible(true);
        Handler mH = (Handler) mHField.get(currentActivityThread);
        Field mCallBackField = Handler.class.getDeclaredField("mCallback");
        mCallBackField.setAccessible(true);

        mCallBackField.set(mH, new ActivityThreadHandlerCallback(mH));

    }
}

四:拦截方法实现

class IActivityManagerHandler implements InvocationHandler {

    private static final String TAG = "IActivityManagerHandler";
    Object mBase;

    public IActivityManagerHandler(Object base) {
        mBase = base;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if ("startActivity".equals(method.getName())) {
            Intent raw;
            int index = 0;
            for (int i = 0; i < args.length; i++) {
                if (args[i] instanceof Intent) {
                    index = i;
                    break;
                }
            }
            raw = (Intent) args[index];
            Intent newIntent = new Intent();
            String stubPackage = "com.hookactivity.cn";
            ComponentName componentName = new ComponentName(stubPackage, StubActivity.class.getName());
            newIntent.setComponent(componentName);
            newIntent.putExtra(AMSHookHelper.EXTRA_TARGET_INTENT, raw);
            args[index] = newIntent;
            Log.d(TAG, "hook success");
            return method.invoke(mBase, args);

        }
        return method.invoke(mBase, args);
    }
}
class ActivityThreadHandlerCallback implements Handler.Callback {

    Handler mBase;
    public ActivityThreadHandlerCallback(Handler base) {
        mBase = base;
    }
    @Override
    public boolean handleMessage(Message msg) {
        switch (msg.what) {
            // ActivityThread里面 "LAUNCH_ACTIVITY" 这个字段的值是100
            case 100:
                handleLaunchActivity(msg);
                break;
        }
        mBase.handleMessage(msg);
        return true;
    }

    private void handleLaunchActivity(Message msg) {
        Object obj = msg.obj;
        try {
            // 把替身恢复成真身
            Field intent = obj.getClass().getDeclaredField("intent");
            intent.setAccessible(true);
            Intent raw = (Intent) intent.get(obj);
            Intent target = raw.getParcelableExtra(AMSHookHelper.EXTRA_TARGET_INTENT);
            raw.setComponent(target.getComponent());
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

五:主入口

public class MainActivity extends Activity {
    @Override
    protected void attachBaseContext(Context newBase) {
        super.attachBaseContext(newBase);

        try {
            AMSHookHelper.hookActivityManagerNative();
            AMSHookHelper.hookActivityThreadHandler();
        } catch (Throwable throwable) {
            throw new RuntimeException("hook failed", throwable);
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Button button = new Button(this);
        button.setText("启动TargetActivity");

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // TargetActivity并没有在AndroidManifest.xml中声明
                startActivity(new Intent(MainActivity.this, TargetActivity.class));
            }
        });
        setContentView(button);
    }
}

六:目标Activity

不能再清单中注册

public class TargetActivity extends Activity {
    private static final String TAG = "TargetActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView tv = new TextView(this);
        tv.setText("TargetActivity 启动成功!!!");
        setContentView(tv);

    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值