Android plug-in development hook startactivity method

Source: Internet
Author: User

The first step, the first explosion of the project demo photos, not much code, don't be afraid

The second step, should know the Java reflection related knowledge if you do not know or forget the small partners please rub here, Android plug-in development based on the Java reflection Mechanism research http://blog.csdn.net/u011068702/article/details/49863931

The third step, should know the Java static Agent knowledge If you do not know or forget the small partners please rub here, Android plug-in development of the basic static proxy mode http://blog.csdn.net/u011068702/article/details/51765578
Fourth, should know the Java Dynamic Agent knowledge If you do not know or forget the small partners please rub here, Android plug-in development based on the Java Dynamic Agent (proxy) mechanism of a simple example http://blog.csdn.net/u011068702/ article/details/53185210 above only the explanation of the code, if not very clear small partners can go to the Internet to search the relevant knowledge.
Fifth step, you should know Android Activitythread class and Instrumentation class if you do not know or forget the small partners please rub here, Android plug-in development of AMS and Applications (client Activitythread, instrumentation, Activity) communication model analysis http://blog.csdn.net/u011068702/article/details/53207039
Hope to look seriously, know Activitythread and instrumentation is why, convenient analysis below.
Sixth step, understand the hook, and analyze the source code if we create the proxy object ourselves, and then replace the original object with our proxy object, then we can do anything in this proxy object, modify the parameters, replace the return value, we call the hook.
Next we implement hook off startactivity this method, when each call this method to do what we need to do, I here to print some information, the reader can have their own needs to modify, our purpose is to intercept the StartActivity method, A little class is the idea of the AOP inside spring.
1. Where is the hook usually hook? First analyze what we need to hook which objects, that is, where we want to hook, what kind of object is better hook? Generally easy to find and not easy to change the object, this idea comes, does not change the general in our class the Singleton object is the only object, static variables we generally with the final static modification, with the final will not change, the invariant pattern inside such as the string class, inside a lot of final, We even find the place where the hooks are.

2, we hook startactivity, analysis startactivity exactly how to achieve every time we context.startactivity, because the context of the implementation is actually CONTEXTIMPL to achieve,; Let's look at the StartActivity method of the Conetxtimpl class:
@Overridepublic void StartActivity (Intent Intent, Bundle options) {    warnifcallingfromsystemprocess ();    if ((Intent.getflags () &intent.flag_activity_new_task) = = 0) {        throw NEW androidruntimeexception (                " Calling StartActivity () from outside of a Activity "                +" context requires the Flag_activity_new_task FLAG. "                + "are this really what do you want?");    }    Mmainthread.getinstrumentation (). Execstartactivity (        getoutercontext (), Mmainthread.getapplicationthread (), NULL,        (Activity) NULL, intent,-1, options);}

We can see that the StartActivity method is finally implemented by the instrumentation object to execute the execstartactivity, if you take a serious look at the Android plug-in development of the AMS and the application ( Client Activitythread, Instrumentation, Activity) communication model Analysis "Above this blog, we know that Activitythread is the main thread, which is what we often say UI thread, can go to update the UI, A process with only one main thread, we can hook here.
We need to hook off our main thread object and replace the minstrumentation in the main thread object with the proxy object we modified; To replace the field inside the main thread object1) First we have to get a reference to the main thread object, how to get it? The Activitythread class has a static method Currentactivitythread can help us get to this object class, but Activitythread is a hidden class, we need to use reflection to obtain, the code is as follows:

First get to the current Activitythread object class<?> activitythreadclass = Class.forName ("Android.app.ActivityThread"); Method Currentactivitythreadmethod = Activitythreadclass.getdeclaredmethod ("Currentactivitythread"); Currentactivitythreadmethod.setaccessible (true); Object Currentactivitythread = Currentactivitythreadmethod.invoke (null);


2) After getting this currentactivitythread, we need to modify its minstrumentation this field for our proxy object, we implement this proxy object first, because the JDK dynamic agent only supports the interface, And this instrumentation is a class, we can manually write static proxy class, overwriting the original method, the code is as follows

Package Com.example.hookstartactivity;import Java.lang.reflect.method;import Android.app.activity;import Android.app.instrumentation;import Android.app.instrumentation.activityresult;import Android.content.Context; Import Android.content.intent;import android.os.bundle;import Android.os.ibinder;import android.util.Log;public Class Instrumentationproxy extends Instrumentation {public static final String TAG = ' instrumentationproxy '; public Stati  C final String exec_start_activity = "execstartactivity"; Activitythread inside the original instrumentation object, here must not be written minstrumentation, so write/throw exception, has been pro-test, so this place will pay attention to public      Instrumentation oldinstrumentation; Pass the object through the constructor public Instrumentationproxy (instrumentation minstrumentation) {oldinstrumentation = minstrumentation;} This method is due to the original method inside the instrumentation has execstartactivity method to set the public Activityresult execstartactivity (the Context who, IBinder Contextthread, IBinder token, Activity target, Intent Intent, int requestcode, Bundle options) {log.d (TAG, "\ n Print Call Startactivity related parameters: \ n "+" who = ["+" + "]," + "\ncontextthread = [" + Contextthread + "], \ntoken = [" + token + "]," + "\ntarget = [" + Target + "], \nintent = [" + Intent + "], \nrequestcode = [" + Requestcode + "], \no ptions = ["+ Options +"] "); LOG.I (TAG, "------------hook success------------->"); LOG.I (TAG, "Here's what you can do before you open the StartActivity method"); LOG.I (TAG, "------------hook success------------->"); LOG.I (TAG, "");//Because this method is hidden, it needs reflection to call, first find this method try {method execstartactivity = Instrumentation.class.getDeclaredMetho                 D (exec_start_activity, Context.class, Ibinder.class, Ibinder.class, Activity.class,        Intent.class, Int.class, Bundle.class);        Execstartactivity.setaccessible (TRUE); Return (Activityresult) Execstartactivity.invoke (Oldinstrumentation, who, Contextthread, token, target        , intent, Requestcode, options); } catch (Exception e) {//If you write a wrong instance of the member variable instrumentation in this classMinstrument, the code is going to execute here to throw the new RuntimeException ("If instrumentation paramerter is minstrumentation, Hook will        Fail "); } }}


3) Then replace the proxy object with the following code

Package Com.example.hookstartactivity;import Java.lang.reflect.field;import Java.lang.reflect.method;import Android.app.application;import Android.app.instrumentation;import Android.util.log;public class MyApplication Extends application {public static final string TAG = "MyApplication";p ublic static final String activit_thread = "Android . App. Activitythread ";p ublic static final String current_activity_thread =" Currentactivitythread ";p ublic static final string instrumentation = "Minstrumentation"; @Overridepublic void OnCreate () {try {//This method is generally written in the OnCreate function of application, if you write in The activity inside the Oncrate function inside is already late attachcontext ();} catch (Exception e) {e.printstacktrace ();}} public static void Attachcontext () throws exception{//Get current Activitythread object class<?> Activitythreadclass = Cl    Ass.forname (Activit_thread);    Method Currentactivitythreadmethod = Activitythreadclass.getdeclaredmethod (Current_activity_thread);    Currentactivitythreadmethod.setaccessible (TRUE); Object Currentactivitythread = Currentactivitythreadmethod.invoke (null); Get the original Minstrumentation object in the Activitythread class Field Minstrumentationfield = Activitythreadclass.getdeclaredfield (    instrumentation);    Minstrumentationfield.setaccessible (TRUE);    Instrumentation minstrumentation = (instrumentation) minstrumentationfield.get (currentactivitythread);        Build our proxy object instrumentation evilinstrumentation = new Instrumentationproxy (minstrumentation); By reflection, replace the field, note that here is the code of reflection, not the method inside the instrumentation Minstrumentationfield.set (Currentactivitythread,        Evilinstrumentation); Make a mark to see LOG.I (tag, "have go in MyApplication Attachcontext method") at the back;}}

Note that this substitution in the application inside of the OnCreate method inside to execute, if the activity method inside to execute the words are late, the program will not error, but the hook is not.


Then I wrote a button on the main page and clicked to trigger the startactivity.
Mainactivity.java files are as follows
Package Com.example.hookstartactivity;import Android.content.intent;import Android.os.bundle;import Android.support.v7.app.actionbaractivity;import Android.util.log;import Android.view.menu;import Android.view.menuitem;import Android.view.view;import Android.view.view.onclicklistener;import Android.widget.textview;public class Mainactivity extends Actionbaractivity {public static final String TAG = "MainA Ctivity ";p ublic TextView TV; @Overrideprotected void OnCreate (Bundle savedinstancestate) {super.oncreate ( Savedinstancestate); Setcontentview (r.layout.activity_main); TV = (TextView) Findviewbyid (R.id.start); Tv.setonclicklistener (New Onclicklistener () {@Overridepublic void OnClick (View v) {try {Intent Intent = new Intent ( Mainactivity.this, Secondactivity.class); Bundle bundle = new bundle (); LOG.I (TAG, "-------------------------------->"); LOG.I (TAG, "startactivity before"); LOG.I (TAG, "-------------------------------->"); startactivity (intent, bundle); LOG.I (TAG, "--------------------------------> "); LOG.I (TAG, "startactivity after"); LOG.I (TAG, "-------------------------------->");} catch (Exception e) {e.printstacktrace ();}}} );}}


Jump to the Second.java file as follows
Package Com.example.hookstartactivity;import Android.os.bundle;import android.support.v7.app.ActionBarActivity; public class Secondactivity extends actionbaractivity{@Overrideprotected void OnCreate (Bundle savedinstancestate) { Super.oncreate (savedinstancestate); Setcontentview (R.layout.activity_second);}}


The seventh step, run the Code startup item in the Ubuntu terminal print the log picture as follows:


Then I click on the icon to call the StartActivity method after the Ubuntu terminal Print log picture as follows:

Log above See, hook success saw the Ubuntu terminal log print, the front shows the class, convenient through the log to find the bug, I use the pidcat, download Pidcat and then run on Ubuntu
pidcat.py Package Name

can be very convenient to look at the log to find a bug.
Eighth step, summarize through this log, hope that the attack can better understand hook, Java reflection, static agent, dynamic agent, Activitythread, instrumentation finally attached source code, the need for small partners please rub here Hookstartactivitydemo

Android plug-in development hook startactivity method

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.