uiautomator运行中获取运行状态
需求描述:
在手机平板端拷贝文件过程中需要在python端做些事情,比如在平板拷贝学习资料的过程中python端发个表情包:
需求分析:
因此需要在开始拷贝的时候告知python开始,在拷贝结束的时候告知python结束,方能精准控制过程并进行某些操作
已知情报:
uiautomator只有在test用例执行完毕之后方才打印信息(那些比如log.i()、System.out.println()什么的根正苗红才不会显示呢~)如下图所示:
解决思路:
宏观可知uiautomator是可以打印数据到cmd终端的(cmd终端输出映射到python主进程的管道中,因此python中方能poll得到数据),因此肯定是有方法可以打印中间过程的,此为总纲。
具体如何操作?
step1:尝试log.i()方式和System.out.println();后发现uiautomator是不支持打印数据到终端的(仅在androidstudio的log console界面显示打印信息);
step2:考虑打印到终端、打印到log文件、打印到管道,等等,这些都是可以重定向的,因此,把uiautomator里导向log文件的索引重新导向终端,这也是一个解决思路(源码不熟,找到接口艰难~摔~);
step3:继续仔细观察上述打印信息可知,打印信息来自于instrument,因此搜索它是如何实现的为解决线索,从stackoverflow找到的接口为instrumentation.sendStatus(),就是上述的打印信息!
step4:后续,当然可以继续深挖uiautomator、instrument框架的原理以及设计理念!(这是7月份战略目标!7月底希望能交付总结心得报告。)
解决方案1:
拷贝大文件,在开始拷贝后,直接退出,相当于告诉python,我跑完了,场景开始了,请开始你的表演!此时由于文件很大,拷贝时间很长,因此可以保证在场景开始后,进行用例的测试,但无法获知场景何时结束,也就是说是个半开半闭集合。
优点:简单粗暴直接方便···
缺点:不可预知结束点。
解决方案2:
将uiautomator部分拆开,先写场景开始部分,场景一开始就立马结束,然后python获知后马上开进程运行场景结束监测部分,也可实现需求。但是实时性会打折扣,比如后面监测部分可能会导致场景开始好几秒后方才开始监测,不过这都是小问题,最重要的是代码量增多了,写起来很麻烦。
优点:你就说问题解决没有!!!昂?
缺点:实时性要求高的场合可能不太适合,代码量有点多。
解决方案3:
python开启一个线程专门用来监控log文件(log cat),通过设置一些关键字来识别,可以实现。但是,可能存在这样的风险:由于buffer有限,且log cat是存全局的信息的,所以时间一长,可能会有部分log信息丢失。
优点:实时性较高;功能齐全。
缺点:读取log文件有点麻烦啊~同时解析log文件涉及到底层的io操作,这样比读内存还是慢上至少一个数量级的~
解决方案4:
java端直接通过 instrumentation.sendStatus(0,bundle);把关键信息实时打印到cmd,从而被python获取到(实测实时性约为0.5s),从而省去读log文件的过程,编写用例将会比较简洁。
优点:实时性好,python源代码无需修改即可实现中间过程监控,减少代码量。
缺点:放在最后面明显是主角啊,显然剧透了啊~
java代码demo:
@Before
public voidsetUp(){
instrumentation= InstrumentationRegistry.getInstrumentation();
device= UiDevice.getInstance(instrumentation);
}
@Test
public synchronized voidpingpong()throwsUiObjectNotFoundException,RemoteException,InterruptedException,IOException {
System.out.println("enter time"+ System.currentTimeMillis());
device.pressHome();
/*重定向的方式来实现,但是想一下觉得还是不行!为什么不行呢?因为我不会啊~~~~~*/
System.out.println("quit time"+ System.currentTimeMillis());
Bundle bundle =newBundle();
bundle.putString("MyResult","0"+System.currentTimeMillis());
instrumentation.sendStatus(0,bundle);
}
实际的效果:
实时性:
# coding=utf-8
importsubprocess
importtime
cmd ="adb shell am instrument -w -r -e debug false -e class com.softwinner.uiautomator.scene.Scene#pingpong\ com.softwinner.uiautomator.scene.test/android.support.test.runner.AndroidJUnitRunner"
p = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
whilep.poll() is None:
out =str(p.stdout.readline())
if"MyResult"inout:
printout,time.time()
#INSTRUMENTATION_STATUS: MyResult=01498564332025
#1498564332.52
#1498564332.52 - 1498564332.025 = 0.495s
总结:四种解决方法各有各的优势,反正就是解决问题的工具而已,选个称手的就好啦~
最后,强烈感谢小组成员的帮助及指点,上述如若出现任何螺旋劈叉,有问题请出门左转直接@小南@小媚@小俊@小乐~