InstrumentationRegistry 类
一个暴露的注册实例,该实例持有对正在运行的instrumentaion的引用,以及instrumentation的参数。并且还提供的一些简单的方法去获得instrumentation, application context, 以及instrumentation 参数bundle.
Public methods |
|
---|---|
static Bundle |
getArguments() Returns a copy of instrumentation arguments Bundle. |
static Context |
getContext() Return the Context of this instrumentation's package. |
staticInstrumentation |
getInstrumentation() Returns the instrumentation currently running. |
static Context |
getTargetContext() Return a Context for the target application being instrumented. |
static void |
registerInstance(Instrumentation instrumentation, Bundle arguments) Records/exposes the instrumentation currently running and stores a copy of the instrumentation arguments Bundle in the registry. |
Instrumentation类
当instrumentation开启的话,它会在应用程序的任何组件创建之前初始化,可以用来监控系统与应用的所有交互。系统可以根据AndroidManifest.xml中的 instrumentation 标签来实现instrumentation。
android:targetPackage="com.motorola.avik.test">
查看其提供的方法,比如:callActivityOnCreate,callApplicationOnCreate,newActivity,callActivityOnNewIntent 等基本上在application和activity的所有生命周期调用中,都会先调用instrumentation的相应方法。并且针对应用内的所有activity都生效。为程序员提供了一个强大的能力,有更多的可能性进入android app框架执行流程.
对于每一个android app来说,它的总入口都是ActivityThread::main. 每一个应用的进程都有一个ActivityThread对象,而每一个ActivityThread对象都有一个Instrumentation mInstrumentation;成员变量。mInstrumentation的初始化在ActivityThread::handleBindApplication函数中:
if (data.instrumentationName !=null) {
...
Java.lang.ClassLoadercl = instrContext.getClassLoader();
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
...} else {mInstrumentation =newInstrumentation();
}
自定义的instrumentation只能通过调用Context.startInstrementation或者命令行am instrument启动,这个过程会将目标进程杀死再重启(声明instrumention的应用与目标应用签名必需一致)。如果应用不是通过上述方式启动而是正常情况下(通过launcher或者startActivity)启动,会默认new 一个系统的Instrumentation.
如果某应用要自定义instrumentation且用于跟踪本应用内的application及activity生命周期,通过继承实现Instrumentation并反射修改ActivityThread.mInstrumentation的方法可以做到。以下是具体做法:
1、自定义Instrumentation
class MyInstrumentation extends Instrumentation {
...
};
2、反射调用修改ActivityThread.mInstrumentation
MyInstrumentation ins = new MyInstrumentation();
Class cls = Class.forName("android.app.ActivityThread"); // ActivityThread被隐藏了,所以通过这种方式获得class对象
Method mthd = cls.getDeclaredMethod("currentActivityThread", (Class[]) null); // 获取当前ActivityThread对象引用
Object currentAT = mthd.invoke(null, (Object[]) null);
Field mInstrumentation = currentAT.getClass().getDeclaredField("mInstrumentation");
mInstrumentation.setAccessible(true);
mInstrumentation.set(currentAT, ins); // 修改ActivityThread.mInstrumentation值
至此即可通过MyInstrumentation来跟踪应用内application及activity的生命周期。
AndroidJUnitRunner
java.lang.Object | ||||
↳ | android.app.Instrumentation | |||
↳ | android.support.test.internal.runner.hidden.ExposedInstrumentationApi | |||
↳ | android.support.test.runner.MonitoringInstrumentation | |||
↳ | android.support.test.runner.AndroidJUnitRunner |
Running all tests: adb shell am instrument -w com.motorola.avik.test/android.support.test.runner.AndroidJUnitRunner
Running all tests in a class: adb shell am instrument -w -e class com.motorola.avik.test.FooTest com.motorola.avik.test/android.support.test.runner.AndroidJUnitRunner
Running a single test: adb shell am instrument -w -e class com.motorola.avik.test.FooTest#testFoo com.motorola.avik.test/android.support.test.runner.AndroidJUnitRunner
Running all tests in multiple classes: adb shell am instrument -w -e class com.motorola.avik.test.FooTest,com.android.foo.TooTes他com.motorola.avik.test/android.support.test.runner.AndroidJUnitRunner