企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
## 1. 前言 本来这次文章的title是写成和前几篇类似的《EasyMonkeyDevice API实践全记录》,内容也打算把每个API的实践和建议给记录下来,但后来想了下觉得这样子并不是最好的方法,鉴于EasyMonkeyDevice其实就是在前几章描述的MonkeyDevice和HierarchyViewer的基础上加了一层Wrapper,把原来的通过接受坐标点或者ViewNode来操作控件的思想统一成通过控件ID来操作,其实最终它们都会转换成坐标点或ViewNode进行操作。以touch和visible这两个API为例子,大家看下以下的源码就很清楚了。 MonkeyDevice里面的touch是用坐标点作为参数的,而下面的EasyMonkeyDevice用得是id(By这个类里面就一个ID而已,有兴趣查其源码),最终还是转成坐标点: ~~~ public void touch(By selector, TouchPressType type) { Point p = getElementCenter(selector); mDevice.getImpl().touch(p.x, p.y, type); } ~~~ HierarchyViewer里面的Visible用的是ViewNode,EasyMonkeyDevice用得是id,最终还是转成ViewNode: ~~~ public boolean visible(By selector) { ViewNode node = selector.findView(mHierarchyViewer); return mHierarchyViewer.visible(node); } ~~~ 所以本文应该除了给出API的实践之外还应该把每个API和其与MonkeyDevice和HierarchyViewer的API所对应的API给列出来做一个对应的Map,方便我们参考。 实践中我们还是用SDK自带的NotePad APK,假设已经有一个Note存在的情况下,通过以下步骤来走一遍EasyMonkeyDevice的所有API: - 使用MonkeyDevice对象实例化EasyMonkeyDevice - 通过ID Touch一个Note - 获得进入NoteEditor activity后的WindowId并验证是否正确 - 通过ID检查Note的内容这个EditText是否存在和可见 - 通过Note的ID获得Text - 通过Note的ID Type进新Text - 通过Note的ID获得Location 以下是我们操作过程中会看到的两个Activity的截图,先贴上来给大家对以上步骤有一个感性认识,最后我会贴出实践验证性代码。 NotesList Activity截图: ![](https://box.kancloud.cn/2016-08-15_57b1755a4c165.jpg) NoteEditor Activity截图: ![](https://box.kancloud.cn/2016-08-15_57b1755a707eb.jpg) ## 2. EaysyMonkeyDevice API List and Sample EasyMonkeyDevice是在MonkeyDevice和HierarchyViewer的基础上出来的一个类,按照本人的理解,主要增加的功能就是: - 在MonkeyDevice和HierarchyViewer的基础上针对部分API增加了对控件ID的支持以操作控件 以下是个人整理的列表:尝试对所有的API进行一个描述和示例Demo <table border="1" cellspacing="0" cellpadding="0" width="613"><tbody><tr><td valign="top" style="background-color:rgb(191,191,191)"><p align="center"><strong>Return</strong></p></td><td valign="top" style="background-color:rgb(191,191,191)"><p align="center"><strong>EasyMonkeyDevice</strong></p></td><td valign="top" style="background-color:rgb(191,191,191)"><p align="center"><strong>Demo</strong></p></td><td style="background-color:rgb(191,191,191)"><p align="center"><strong>Comment</strong></p><p align="center"><strong> </strong></p></td></tr><tr><td valign="top"><p align="center"><strong><span style="color:rgb(49,132,155)"> </span></strong></p></td><td valign="top"><p><strong><span style="color:rgb(49,132,155)">EasyMonkeyDevice</span></strong><span style="color:rgb(34,34,34)">(</span></p><p><span style="color:rgb(34,34,34)">MonkeyDevice device)</span></p><p><em><span style="color:rgb(148,54,52)">Use Monkey device to construct</span></em></p><p><em><span style="color:rgb(148,54,52)">an EasyMonkeyDevice object,</span></em></p><p><em><span style="color:rgb(148,54,52)">note that it would instantiate a</span></em></p><p><em><span style="color:rgb(148,54,52)">HierarchyViewer member by</span></em></p><p><em><span style="color:rgb(148,54,52)">device within this constructor</span></em></p></td><td valign="top"><p><span style="color:rgb(34,34,34)"> </span></p><p><span style="color:rgb(34,34,34)">device = MonkeyRunner.waitForConnection()</span></p><p><span style="color:rgb(34,34,34)"> </span></p><p><span style="color:rgb(34,34,34)">eDevice=EasyMonkeyDevice(device)</span></p></td><td><p><span style="color:rgb(34,34,34)">Constructor</span></p></td></tr><tr><td valign="top"><p align="center"><span style="color:rgb(34,34,34)">Void</span></p></td><td><p><strong><span style="color:rgb(49,132,155)">touch</span></strong><span style="color:rgb(34,34,34)">(By selector,</span></p><p><span style="color:rgb(34,34,34)">TouchPressType type)</span></p><p><em><span style="color:rgb(148,54,52)">Sends a touch event specified</span></em></p><p><em><span style="color:rgb(148,54,52)">by ‘type’ to the screen location</span></em></p><p><em><span style="color:rgb(148,54,52)">specified by ‘by’</span></em></p></td><td valign="top"><p><span style="color:rgb(34,34,34)"> </span><span style="color:rgb(34,34,34)">触摸点击主窗口:</span></p><p><span style="color:rgb(34,34,34)">#Step 1: try touching on the first note</span></p><p><span style="color:rgb(34,34,34)">eDevice.touch(By.id('id/text1'),</span></p><p><span style="color:rgb(34,34,34)">              MonkeyDevice.DOWN_AND_UP)</span></p><p><span style="color:red">触摸弹出框或</span><span style="color:red">Menu Options</span><span style="color:red">会失败:</span></p><p><span style="color:rgb(34,34,34)">MonkeyRunner.sleep(2)</span></p><p><span style="color:rgb(34,34,34)">print 'Show Menu Options'</span></p><p><span style="color:rgb(34,34,34)">device.press('KEYCODE_MENU',</span></p><p><span style="color:rgb(34,34,34)">             MonkeyDevice.DOWN_AND_UP);</span></p><p><span style="color:rgb(34,34,34)"> </span></p><p><span style="color:rgb(34,34,34)">MonkeyRunner.sleep(3)</span></p><p><span style="color:rgb(34,34,34)">print 'Press on the menu entry of \</span></p><p><span style="color:rgb(34,34,34)"> \"Add note\"'</span></p><p><span style="color:rgb(34,34,34)">eDevice.touch(By.id('id/title'),</span></p><p><span style="color:rgb(34,34,34)">               MonkeyDevice.DOWN)</span></p><p> </p></td><td><p>参数By实际上</p><p>只有By.ID,从</p><p>其源码可以看</p><p>出来;</p><p>type参数跟</p><p>MonkeyDevice</p><p>一样就那几个</p><p>DOWN/UP之类的</p><p> </p><p><span style="color:red">根据个人实践</span></p><p><span style="color:red">和网上评论,</span></p><p><span style="color:red">对系统菜单和</span></p><p><span style="color:red">弹出框的支持</span></p><p><span style="color:red">有问题</span></p></td></tr><tr><td valign="top"><p align="center"><span style="color:rgb(34,34,34)">Void</span></p></td><td><p><strong><span style="color:rgb(49,132,155)">type</span></strong><span style="color:rgb(34,34,34)">(By selector, String text)</span></p><p><em><span style="color:rgb(148,54,52)">Types a string into the specified</span></em></p><p><em><span style="color:rgb(148,54,52)">object</span></em></p></td><td valign="top"><p><span style="color:rgb(34,34,34)"> </span></p><p><span style="color:rgb(34,34,34)">#Step 5: setText</span></p><p><span style="color:rgb(34,34,34)">eDevice.type(By.id(noteId), 'New')</span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p align="center"><span style="color:rgb(34,34,34)">Boolean</span></p></td><td valign="top"><p><strong><span style="color:rgb(49,132,155)">exists</span></strong><span style="color:rgb(34,34,34)">(By selector)</span></p><p><em><span style="color:rgb(148,54,52)">Checks if the specified object</span></em></p><p><em><span style="color:rgb(148,54,52)">exists.</span></em></p></td><td valign="top"><p><span style="color:rgb(34,34,34)"> </span></p><p><span style="color:rgb(34,34,34)">#Step3: is note EditText exist?</span></p><p><span style="color:rgb(34,34,34)">noteId = 'id/note'</span></p><p><span style="color:rgb(34,34,34)">if True == eDevice.exists(By.id(noteId)):</span></p><p><span style="color:rgb(34,34,34)">    print 'Note exist'</span></p><p><span style="color:rgb(34,34,34)">else:</span></p><p><span style="color:rgb(34,34,34)">    print 'Note not found!'</span></p><p><span style="color:rgb(34,34,34)">    exit(2)</span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p align="center"><span style="color:rgb(34,34,34)">Boolean</span></p></td><td valign="top"><p><strong><span style="color:rgb(49,132,155)">visible</span></strong><span style="color:rgb(34,34,34)">(By selector)</span></p><p><em><span style="color:rgb(148,54,52)">Checks if the specified object is visible.</span></em></p></td><td valign="top"><p><span style="color:rgb(34,34,34)"> </span></p><p><span style="color:rgb(34,34,34)">#Step4: is note EditText visible?</span></p><p><span style="color:rgb(34,34,34)">if True == eDevice.visible(By.id(noteId)):</span></p><p><span style="color:rgb(34,34,34)">    print 'Note is visible'</span></p><p><span style="color:rgb(34,34,34)">else:</span></p><p><span style="color:rgb(34,34,34)">    print 'Note is invisible'</span></p><p><span style="color:rgb(34,34,34)">    exit(3)</span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p align="center"><span style="color:rgb(34,34,34)">String</span></p></td><td valign="top"><p><strong><span style="color:rgb(49,132,155)">getText</span></strong><span style="color:rgb(34,34,34)">(By selector)</span></p><p><em><span style="color:rgb(148,54,52)">Obtain the text in the selected</span></em></p><p><em><span style="color:rgb(148,54,52)">input box.</span></em></p></td><td valign="top"><p><span style="color:rgb(34,34,34)"> </span></p><p><span style="color:rgb(34,34,34)">#Step 4: getText</span></p><p><span style="color:rgb(34,34,34)">text = eDevice.getText(By.id(noteId))</span></p><p><span style="color:rgb(34,34,34)">print 'Note text:',text.encode('utf-8')</span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p align="center"><span style="color:rgb(34,34,34)">String</span></p></td><td valign="top"><p><strong><span style="color:rgb(49,132,155)">getFocusedWindowId</span></strong><span style="color:rgb(34,34,34)">()</span></p><p><em><span style="color:rgb(148,54,52)">Gets the id of the focused window.</span></em></p><p><span style="color:rgb(152,72,6)">returns = "</span><span style="color:rgb(0,176,80)">The symbolic id of the</span></p><p><span style="color:rgb(0,176,80)">focused window or None."</span></p></td><td valign="top"><p><span style="color:rgb(34,34,34)"> </span></p><p><span style="color:rgb(34,34,34)">#Step 2: Get the window ID</span></p><p><span style="color:rgb(34,34,34)">winId = 'com.example.android.notepad/\</span></p><p><span style="color:rgb(34,34,34)">    com.example.android.notepad.NoteEditor'</span></p><p><span style="color:rgb(34,34,34)">#Need to sleep a while till ready</span></p><p><span style="color:rgb(34,34,34)">MonkeyRunner.sleep(3)</span></p><p><span style="color:rgb(34,34,34)">winId = eDevice.getFocusedWindowId()</span></p><p><span style="color:rgb(34,34,34)">if(winId == winId):</span></p><p><span style="color:rgb(34,34,34)">    print "Edit Note WinId is:",\</span></p><p><span style="color:rgb(34,34,34)">        winId.encode('utf-8')</span></p><p><span style="color:rgb(34,34,34)">else:</span></p><p><span style="color:rgb(34,34,34)">    print "Failed"</span></p><p><span style="color:rgb(34,34,34)">    exit(1)</span></p><p><span style="color:rgb(34,34,34)"><br/><br/></span></p></td><td><p><span style="color:rgb(34,34,34)"> </span><span style="color:rgb(34,34,34)">结果跟</span></p><p><span style="color:rgb(34,34,34)">HierarchyViewer</span></p><p><span style="color:rgb(34,34,34)">的</span></p><p><span style="color:rgb(34,34,34)">getFocusedWin</span></p><p><span style="color:rgb(34,34,34)">dowName</span></p><p><span style="color:rgb(34,34,34)">返回值一模</span></p><p><span style="color:rgb(34,34,34)">一样,所以</span></p><p><span style="color:red">猜想</span><span style="color:red">WindowID</span></p><p><span style="color:red">和</span><span style="color:red">WindowName</span></p><p><span style="color:red">是同一回事</span></p></td></tr><tr><td valign="top"><p align="center"><span style="color:rgb(34,34,34)">PyTuple</span></p></td><td valign="top"><p><strong><span style="color:rgb(49,132,155)">locate</span></strong><span style="color:rgb(34,34,34)">(By selector)</span></p><p><span style="color:rgb(148,54,52)">Locates the coordinates of the</span></p><p><span style="color:rgb(148,54,52)">selected object</span></p><p><span style="color:rgb(148,54,52)">returns = "</span><span style="color:rgb(0,176,80)">Tuple containing</span></p><p><span style="color:rgb(0,176,80)">(x,y,w,h) location and size</span><span style="color:rgb(148,54,52)">.")</span></p></td><td valign="top"><p><span style="color:rgb(34,34,34)"> </span></p><p><span style="color:rgb(34,34,34)">#Step 6: locate</span></p><p><span style="color:rgb(34,34,34)">locate = eDevice.locate(By.id(noteId))</span></p><p><span style="color:rgb(34,34,34)">print 'Location(x,y,w,h) is:',locate</span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr></tbody></table> ## 3. EasyMonkeyDevice vs MonkeyDevice API Mapping Matrix 这里会列出MonkeyDevice的所有API已经EasyMonkeyDevice与其对应的API,没有去掉冗余是因为方便今后Reference的时候知道EasyMonkeyDevice并不是完全把所有MonkeyDevice的API都进行Wrap的,只有以下两个。下面一章理同。 - **touch**:MonkeyDevice通过坐标点touch;EasyMonkeyDevice通过控件ID去touch - **type**:MonkeyDevice往当前focused地方输入;EasyMonkeyDevice往由ID指定控件输入 <table border="1" cellspacing="0" cellpadding="0" width="685"><tbody><tr><td width="559" colspan="2" valign="top" style="background-color:rgb(191,191,191)"><p><strong>EasyMonkeyDevice API vs MonkeyDevice API</strong></p></td><td><p> </p></td></tr><tr><td valign="top" style="background-color:rgb(191,191,191)"><p align="center"><strong>MonkeyDevice</strong></p></td><td valign="top" style="background-color:rgb(191,191,191)"><p><strong><span style="color:rgb(34,34,34)">EasyMonkeyDevice</span></strong></p></td><td style="background-color:rgb(191,191,191)"><p align="center"><strong>Comment</strong></p><p align="center"><strong> </strong></p></td></tr><tr><td valign="top"><p><span style="color:rgb(34,34,34)">Void </span><a target="_blank" href="http://developer.android.com/tools/help/MonkeyDevice.html#broadcastIntent"><strong><span style="color:rgb(37,138,175)">broadcastIntent</span></strong></a><span style="color:rgb(34,34,34)"> (<em>string</em> uri, <em>string</em> action,</span></p><p><span style="color:rgb(34,34,34)"> <em>string</em> data, <em>string</em> mimetype, </span></p><p><em><span style="color:rgb(148,54,52)">iterable</span></em><span style="color:rgb(148,54,52)"> categories <em>dictionary</em> extras, </span></p><p><em><span style="color:rgb(148,54,52)">component</span></em><span style="color:rgb(148,54,52)"> component, <em>iterable</em> flags)</span></p><p><span style="color:rgb(148,54,52)">Broadcasts an Intent to this device, as if the</span></p><p><span style="color:rgb(148,54,52)">Intent were coming from an application.</span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p><span style="color:rgb(34,34,34)">Void </span><a target="_blank" href="http://developer.android.com/tools/help/MonkeyDevice.html#drag"><span style="color:rgb(34,34,34)">drag</span></a><span style="color:rgb(34,34,34)"> (tuple start, tuple end, float duration, </span></p><p><span style="color:rgb(34,34,34)">integer steps)</span></p><p><em><span style="color:rgb(148,54,52)">Simulates a drag gesture (touch, hold, and</span></em></p><p><em><span style="color:rgb(148,54,52)">move) on this device's screen.</span></em></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p><span style="color:rgb(34,34,34)">Object</span><a target="_blank" href="http://developer.android.com/tools/help/MonkeyDevice.html#getProperty"><strong><span style="color:rgb(37,138,175)">getProperty</span></strong></a><span style="color:rgb(34,34,34)"> (string key)</span></p><p><em><span style="color:rgb(148,54,52)">Given the name of a system environment</span></em></p><p><em><span style="color:rgb(148,54,52)">variable, returns its value for this device.</span></em></p><p><em><span style="color:rgb(148,54,52)">The available variable names are listed in</span></em></p><p><em><span style="color:rgb(148,54,52)">the </span></em><a target="_blank" href="http://developer.android.com/tools/help/MonkeyDevice.html#getProperty"><em><span style="color:rgb(148,54,52)">detailed description</span></em></a><em><span style="color:rgb(148,54,52)"> of this method.</span></em></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p><span style="color:rgb(34,34,34)">Object</span><a target="_blank" href="http://developer.android.com/tools/help/MonkeyDevice.html#getSystemProperty"><strong><span style="color:rgb(37,138,175)">getSystemProperty</span></strong></a><span style="color:rgb(34,34,34)"> (string key)</span></p><p><em><span style="color:rgb(0,176,80)">. </span><span style="color:rgb(148,54,52)">The API equivalent of adb shell getprop</span></em></p><p><em><span style="color:rgb(148,54,52)">&lt;key&gt;. This is provided for</span></em></p><p><em><span style="color:rgb(148,54,52)">use by platform developers.</span></em></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p><span style="color:rgb(34,34,34)">Void </span><a target="_blank" href="http://developer.android.com/tools/help/MonkeyDevice.html#installPackage"><strong><span style="color:rgb(37,138,175)">installPackage</span></strong></a><span style="color:rgb(34,34,34)"> (string path)</span></p><p><em><span style="color:rgb(148,54,52)">Installs the Android application or test package</span></em></p><p><em><span style="color:rgb(148,54,52)"> contained in packageFile onto this device.</span></em></p><p><em><span style="color:rgb(148,54,52)">If the application or test package is already</span></em></p><p><em><span style="color:rgb(148,54,52)">installed, it is replaced.</span></em></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p><span style="color:rgb(34,34,34)">Dictionary</span><a target="_blank" href="http://developer.android.com/tools/help/MonkeyDevice.html#instrument"><strong><span style="color:rgb(37,138,175)">instrument</span></strong></a><span style="color:rgb(34,34,34)"> (string className, dictionary args)</span></p><p><em><span style="color:rgb(148,54,52)">Runs the specified component under</span></em></p><p><em><span style="color:rgb(148,54,52)">Android instrumentation, and returns the results</span></em></p><p><em><span style="color:rgb(148,54,52)"> in a dictionary whose exact format is dictated</span></em></p><p><em><span style="color:rgb(148,54,52)">by the component being run.</span></em></p><p><em><span style="color:rgb(148,54,52)"> The component must already be present on</span></em></p><p><em><span style="color:rgb(148,54,52)">this device.</span></em></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p><span style="color:rgb(34,34,34)">Void </span><a target="_blank" href="http://developer.android.com/tools/help/MonkeyDevice.html#press"><strong><span style="color:rgb(37,138,175)">press</span></strong></a><span style="color:rgb(34,34,34)"> (<em>string</em> name, <em>dictionary</em> type)</span></p><p><em><span style="color:rgb(148,54,52)">Sends the key event specified by type to the</span></em></p><p><em><span style="color:rgb(148,54,52)">key specified by keycode.</span></em></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p><span style="color:rgb(34,34,34)">Void </span><a target="_blank" href="http://developer.android.com/tools/help/MonkeyDevice.html#reboot"><strong><span style="color:rgb(37,138,175)">reboot</span></strong></a><span style="color:rgb(34,34,34)"> (<em>string</em> into)</span></p><p><em><span style="color:rgb(148,54,52)">Reboots this device into the bootloader</span></em></p><p><em><span style="color:rgb(148,54,52)">specified by bootloadType.</span></em></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p><span style="color:rgb(34,34,34)">Void </span><a target="_blank" href="http://developer.android.com/tools/help/MonkeyDevice.html#removePackage"><strong><span style="color:rgb(37,138,175)">removePackage</span></strong></a><span style="color:rgb(34,34,34)"> (<em>string</em> package)</span></p><p><em><span style="color:rgb(148,54,52)">Deletes the specified package from this device,</span></em></p><p><em><span style="color:rgb(148,54,52)"> including its data and cache.</span></em></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p><em><span style="color:rgb(34,34,34)">Object</span></em><a target="_blank" href="http://developer.android.com/tools/help/MonkeyDevice.html#shell"><strong><span style="color:rgb(37,138,175)">shell</span></strong></a><span style="color:rgb(34,34,34)"> (<em>string</em> cmd)</span></p><p><em><span style="color:rgb(148,54,52)">Executes an adb shell command and returns</span></em></p><p><em><span style="color:rgb(148,54,52)">the result, if any.</span></em></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p><span style="color:rgb(34,34,34)">Void </span><a target="_blank" href="http://developer.android.com/tools/help/MonkeyDevice.html#startActivity"><strong><span style="color:rgb(37,138,175)">startActivity</span></strong></a><span style="color:rgb(34,34,34)"> (string uri, string action, </span></p><p><span style="color:rgb(34,34,34)">string</span><span style="color:rgb(34,34,34)"> data, string mimetype, iterable categories </span></p><p><span style="color:rgb(34,34,34)">dictionary</span><span style="color:rgb(34,34,34)"> extras, component component, flags)</span></p><p><em><span style="color:rgb(148,54,52)">Starts an Activity on this device by sending an</span></em></p><p><em><span style="color:rgb(148,54,52)">Intent constructed from the supplied arguments</span><span style="color:rgb(0,176,80)">.</span></em></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p><a target="_blank" href="http://developer.android.com/tools/help/MonkeyImage.html"><span style="color:rgb(34,34,34)">MonkeyImage</span></a><a target="_blank" href="http://developer.android.com/tools/help/MonkeyDevice.html#takeSnapshot"><strong><span style="color:rgb(37,138,175)">takeSnapshot</span></strong></a><span style="color:rgb(34,34,34)">()</span></p><p><em><span style="color:rgb(148,54,52)">Captures the entire screen buffer of this device,</span></em></p><p><em><span style="color:rgb(148,54,52)">yielding a <a target="_blank" href="http://developer.android.com/tools/help/MonkeyImage.html"><span style="color:rgb(148,54,52)">MonkeyImage </span></a>object containing</span></em></p><p><em><span style="color:rgb(148,54,52)">a screen capture of the current display.</span></em></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p><span style="color:rgb(34,34,34)">Void </span><a target="_blank" href="http://developer.android.com/tools/help/MonkeyDevice.html#touch"><strong><span style="color:rgb(37,138,175)">touch</span></strong></a><span style="color:rgb(34,34,34)"> (<em>integer</em> x, <em>integer</em> y, <em>integer</em> type)</span></p><p><em><span style="color:rgb(148,54,52)">Sends a touch event specified by type to the</span></em></p><p><em><span style="color:rgb(148,54,52)">screen location specified by x and y.</span></em></p></td><td><p><span style="color:rgb(34,34,34)">Void</span><strong><span style="color:rgb(49,132,155)"> touch</span></strong><span style="color:rgb(34,34,34)">(By selector, TouchPressType type)</span></p><p><em><span style="color:rgb(148,54,52)">Sends a touch event specified by</span></em></p><p><em><span style="color:rgb(148,54,52)">‘type’ to the screen location specified</span></em></p><p><em><span style="color:rgb(148,54,52)"> by ‘by’</span></em></p></td><td><p><span style="color:red">MonkeyDevice</span><span style="color:red">通过坐标点</span><span style="color:red">touch</span><span style="color:red">;</span></p><p><span style="color:red">EasyMonkeyDevice</span><span style="color:red">通过控件</span><span style="color:red">ID</span><span style="color:red">去</span><span style="color:red">touch</span></p></td></tr><tr><td valign="top"><p><span style="color:rgb(34,34,34)">Void </span><a target="_blank" href="http://developer.android.com/tools/help/MonkeyDevice.html#touch"><strong><span style="color:rgb(37,138,175)">type</span></strong></a><span style="color:rgb(34,34,34)"> (<em>string</em> message)</span></p><p><span style="color:rgb(148,54,52)">Sends the characters contained in message to</span></p><p><span style="color:rgb(148,54,52)">this device, as if they had been typed on</span></p><p><span style="color:rgb(148,54,52)">the device's keyboard. This is equivalent to</span></p><p><span style="color:rgb(148,54,52)">calling </span><a target="_blank" href="http://developer.android.com/tools/help/MonkeyDevice.html#press"><span style="color:rgb(148,54,52)">press()</span></a><span style="color:rgb(148,54,52)"> for each keycode in <strong>message</strong> </span></p><p><span style="color:rgb(148,54,52)">using the key event type <strong>DOWN_AND_UP.</strong></span></p></td><td><p><span style="color:rgb(34,34,34)">Void </span><strong><span style="color:rgb(49,132,155)">type</span></strong><span style="color:rgb(34,34,34)">(By selector, String text)</span></p><p><span style="color:rgb(148,54,52)">Types a string into the specified</span></p><p><span style="color:rgb(148,54,52)">object</span></p></td><td><p><span style="color:red">MonkeyDevice</span><span style="color:red">往当前</span><span style="color:red">focused</span><span style="color:red">地方输入;</span></p><p><span style="color:red">EasyMonkeyDevice</span><span style="color:red">往由</span><span style="color:red">ID</span><span style="color:red">指定控件输入</span></p></td></tr><tr><td valign="top"><p><span style="color:rgb(34,34,34)">Void </span><a target="_blank" href="http://developer.android.com/tools/help/MonkeyDevice.html#touch"><strong><span style="color:rgb(37,138,175)">wake</span></strong></a><span style="color:rgb(34,34,34)"> ()</span></p><p><span style="color:rgb(148,54,52)">Wakes the screen of this device.</span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p><span style="color:rgb(34,34,34)">HierarchyViewer</span> <strong><span style="color:rgb(37,138,175)">getHierarchyViewer</span></strong>()</p><p><span style="color:rgb(148,54,52)">Get the HierarchyViewer object for the device.</span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p><span style="color:rgb(34,34,34)">PyList</span><strong><span style="color:rgb(37,138,175)">getPropertyList</span></strong>()</p><p><span style="color:rgb(148,54,52)">Retrieve the properties that can be queried</span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p><span style="color:rgb(34,34,34)">PyList</span><strong><span style="color:rgb(37,138,175)">getViewIdList</span></strong>()</p><p><span style="color:rgb(148,54,52)">Retrieve the view ids for the current application</span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p><span style="color:rgb(34,34,34)">MonkeyView</span><strong><span style="color:rgb(37,138,175)">getViewById</span></strong>(String id)</p><p><span style="color:rgb(148,54,52)">doc = "Obtains the view with the specified id.",</span></p><p><span style="color:rgb(148,54,52)">args = {"id"},</span></p><p><span style="color:rgb(148,54,52)">argDocs = {"The id of the view to retrieve."},</span></p><p><span style="color:rgb(148,54,52)">returns = "The view object with the specified id."</span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p><span style="color:rgb(34,34,34)">MonkeyView</span><strong><span style="color:rgb(37,138,175)">getViewByAccessibilityIds</span></strong>(String WinId, String accessId)</p><p><span style="color:rgb(148,54,52)">args = {"windowId", "accessibility id"}</span></p><p><span style="color:rgb(148,54,52)">argDocs = {"The window id of the view to</span></p><p><span style="color:rgb(148,54,52)">retrieve.", "The accessibility id of the view to</span></p><p><span style="color:rgb(148,54,52)">retrieve."},</span></p><p><span style="color:rgb(148,54,52)">returns = "The view object with the specified id.")</span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p><span style="color:rgb(34,34,34)">MonkeyView</span><strong><span style="color:rgb(37,138,175)">getRootView</span></strong>()</p><p><span style="color:rgb(148,54,52)">Obtains current root view</span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p><span style="color:rgb(34,34,34)">PyList</span><strong><span style="color:rgb(37,138,175)">getViewsByText</span></strong>(String text)</p><p><span style="color:rgb(148,54,52)">Obtains a list of views that contain the specified</span></p><p><span style="color:rgb(148,54,52)">text.",</span></p><p><span style="color:rgb(148,54,52)">args = {"text"},</span></p><p><span style="color:rgb(148,54,52)">returns = "A list of view objects that contain the specified text.")</span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr></tbody></table> ## 4. EasyMonkeyDevice vs HierarchyViewer Mapping Matrix EasyMonkeyDevice Wrap了HiearchyViewer 的相应API而得到以下这些API - getFocusedWindowId:Wrap了hierarchyviewer的getFocusedWindowName,不再使用ViewNode而使用ID来的获得Window id/Name,其实根据我的实践id/name是同一回事 - locate:其实就是把HierarchyViewer的getAbsolutePositionOfView和getAbsoluteCenterOfView整合在一起获得起始坐标和Width/Hight,前者获得其实坐标,后者获得中心位置,相减后乘以2就是EasyMonkeyDevice想要的Width/Hight了 - visible: 同样是把参数由ViewNode改成id - getText:同上 <table border="1" cellspacing="0" cellpadding="0" width="685"><tbody><tr><td width="559" colspan="2" valign="top" style="background-color:rgb(191,191,191)"><p><strong>EasyMonkeyDevice API vs HierarchViewer API</strong></p></td><td><p> </p></td></tr><tr><td valign="top" style="background-color:rgb(191,191,191)"><p align="center"><strong>HierarchyViewer</strong></p></td><td valign="top" style="background-color:rgb(191,191,191)"><p><strong><span style="color:rgb(34,34,34)">EasyMonkeyDevice</span></strong></p></td><td style="background-color:rgb(191,191,191)"><p align="center"><strong>Comment</strong></p><p align="center"><strong> </strong></p></td></tr><tr><td valign="top"><p><span style="color:rgb(0,0,136)">public</span> <span style="color:rgb(102,0,102)">ViewNode</span> findViewById<span style="color:rgb(102,102,0)">(</span><span style="color:rgb(102,0,102)">String</span> id<span style="color:rgb(102,102,0)">)</span></p><div><p><span style="color:rgb(136,0,0)">/**</span></p><p><a target="_blank" name="66" class=" "/><span style="color:rgb(136,0,0)">* Find a view by id.</span><a target="_blank" name="67" class=" "/></p><p><a target="_blank" name="68" class=" "/><span style="color:rgb(136,0,0)">* @param id id for the view.</span></p><p><a target="_blank" name="69" class=" "/><span style="color:rgb(136,0,0)">* @return view with the specified ID, or {@code null} if no view found.</span></p><p><a target="_blank" name="70" class=" "/><span style="color:rgb(136,0,0)">*/</span></p></div><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p><span style="color:rgb(0,0,136)">public</span> <span style="color:rgb(102,0,102)">ViewNode</span> findViewById<span style="color:rgb(102,102,0)">(</span><span style="color:rgb(102,0,102)">String</span> id<span style="color:rgb(102,102,0)">,</span> <span style="color:rgb(102,0,102)">ViewNode</span> rootNode<span style="color:rgb(102,102,0)">)</span></p><div><p><span style="color:rgb(136,0,0)">/**</span></p><p><a target="_blank" name="82" class=" "/><span style="color:rgb(136,0,0)">* Find a view by ID, starting from the given root node</span></p><p><a target="_blank" name="83" class=" "/><span style="color:rgb(136,0,0)">* @param id ID of the view you're looking for</span></p><p><a target="_blank" name="84" class=" "/><span style="color:rgb(136,0,0)">* @param rootNode the ViewNode at which to begin the traversal</span></p><p><a target="_blank" name="85" class=" "/><span style="color:rgb(136,0,0)">* @return view with the specified ID, or {@code null} if no view found.</span></p><p><a target="_blank" name="86" class=" "/><span style="color:rgb(136,0,0)">*/</span></p></div></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p><span style="color:rgb(0,0,136)">public</span> <span style="color:rgb(102,0,102)">String</span> getFocusedWindowName<span style="color:rgb(102,102,0)">()</span></p><div><p><span style="color:rgb(136,0,0)">/**</span></p><p><a target="_blank" name="103" class=" "/><span style="color:rgb(136,0,0)">* Gets the window that currently receives the focus.</span><a target="_blank" name="104" class=" "/></p><p><a target="_blank" name="105" class=" "/><span style="color:rgb(136,0,0)">* @return name of the window that currently receives the focus.</span></p><p><a target="_blank" name="106" class=" "/><span style="color:rgb(136,0,0)">*/</span></p></div><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(102,0,102)">String </span><span style="color:rgb(34,34,34)">getFocusedWindowId()</span></p><p><span style="color:rgb(148,54,52)">Gets the id of the focused window.</span></p><p><span style="color:rgb(148,54,52)">returns = "The symbolic id of the focused window or None</span><span style="color:rgb(152,72,6)">."</span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><div><p><span style="color:rgb(0,0,136)">public</span> <span style="color:rgb(0,0,136)">static</span> <span style="color:rgb(102,0,102)">Point</span> getAbsolutePositionOfView<span style="color:rgb(102,102,0)">(</span><span style="color:rgb(102,0,102)">ViewNode</span> node<span style="color:rgb(102,102,0)">)</span><span style="color:rgb(136,0,0)">/**</span></p></div><div><p><a target="_blank" name="118" class=" "/><span style="color:rgb(136,0,0)">* Gets the absolute x/y position of the view node.</span></p><p><a target="_blank" name="119" class=" "/><span style="color:rgb(136,0,0)">*</span></p><p><a target="_blank" name="120" class=" "/><span style="color:rgb(136,0,0)">* @param node view node to find position of.</span></p><p><a target="_blank" name="121" class=" "/><span style="color:rgb(136,0,0)">* @return point specifying the x/y position of the node.</span></p><p><a target="_blank" name="122" class=" "/><span style="color:rgb(136,0,0)">*/</span></p></div><p><span style="color:rgb(34,34,34)"> </span></p></td><td rowspan="2"><p><span style="color:rgb(0,0,136)">PyTuple</span><span style="color:rgb(34,34,34)"> locate(By selector)</span></p><p><span style="color:rgb(148,54,52)">Locates the coordinates of the selected object</span></p><p><span style="color:rgb(148,54,52)">returns = "Tuple containing (x,y,w,h) location and size.")</span></p></td><td rowspan="2"><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p><span style="color:rgb(0,0,136)">public</span> <span style="color:rgb(0,0,136)">static</span> <span style="color:rgb(102,0,102)">Point</span> getAbsoluteCenterOfView<span style="color:rgb(102,102,0)">(</span><span style="color:rgb(102,0,102)">ViewNode</span> node<span style="color:rgb(102,102,0)">)</span></p><div><p><span style="color:rgb(136,0,0)">/**</span></p><p><a target="_blank" name="136" class=" "/><span style="color:rgb(136,0,0)">* Gets the absolute x/y center of the specified view node.</span></p><p><a target="_blank" name="137" class=" "/><span style="color:rgb(136,0,0)">*</span></p><p><a target="_blank" name="138" class=" "/><span style="color:rgb(136,0,0)">* @param node view node to find position of.</span></p><p><a target="_blank" name="139" class=" "/><span style="color:rgb(136,0,0)">* @return absolute x/y center of the specified view node.</span></p><p><a target="_blank" name="140" class=" "/><span style="color:rgb(136,0,0)">*/</span></p></div></td></tr><tr><td valign="top"><p><span style="color:rgb(0,0,136)">public</span> <span style="color:rgb(0,0,136)">boolean</span> visible<span style="color:rgb(102,102,0)">(</span><span style="color:rgb(102,0,102)">ViewNode</span> node<span style="color:rgb(102,102,0)">)</span></p><div><p><span style="color:rgb(136,0,0)">/**</span></p><p><a target="_blank" name="148" class=" "/><span style="color:rgb(136,0,0)">* Gets the visibility of a given element.</span><a target="_blank" name="149" class=" "/></p><p><a target="_blank" name="150" class=" "/><span style="color:rgb(136,0,0)">* @param selector selector for the view.</span></p><p><a target="_blank" name="151" class=" "/><span style="color:rgb(136,0,0)">* @return True if the element is visible.</span></p><p><a target="_blank" name="152" class=" "/><span style="color:rgb(136,0,0)">*/</span></p></div><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(0,0,136)">boolean</span><span style="color:rgb(34,34,34)"> visible(By selector)</span></p><p><span style="color:rgb(148,54,52)">Checks if the specified object is visible.</span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr><tr><td valign="top"><p><span style="color:rgb(0,0,136)">public</span> <span style="color:rgb(102,0,102)">String</span> getText<span style="color:rgb(102,102,0)">(</span><span style="color:rgb(102,0,102)">ViewNode</span> node<span style="color:rgb(102,102,0)">)</span></p><div><p><span style="color:rgb(136,0,0)">/**</span></p><p><a target="_blank" name="163" class=" "/><span style="color:rgb(136,0,0)">* Gets the text of a given element.</span></p><p><a target="_blank" name="164" class=" "/><span style="color:rgb(136,0,0)">*</span></p><p><a target="_blank" name="165" class=" "/><span style="color:rgb(136,0,0)">* @param selector selector for the view.</span></p><p><a target="_blank" name="166" class=" "/><span style="color:rgb(136,0,0)">* @return the text of the given element.</span></p><p><a target="_blank" name="167" class=" "/><span style="color:rgb(136,0,0)">*/</span></p></div><p><span style="color:rgb(34,34,34)"> </span></p></td><td><p><span style="color:rgb(0,0,136)">String</span><span style="color:rgb(34,34,34)"> getText(By selector)</span></p><p><span style="color:rgb(148,54,52)">Obtain the text in the selected input box.</span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr></tbody></table> ## 5. EasyMonkeyDevice Standalone API 剩下一个API是没有跟以上的MonkeyDevice和HierarchyViewer有任何对应关系的: - visible:通过id检查该控件是否存在,猜想应该是google在代码重构的时候增加的一个方法方便大家判断而已 <table border="1" cellspacing="0" cellpadding="0" width="685"><tbody><tr><td valign="top" style="background-color:rgb(191,191,191)"><p><strong>EasyMonkeyDevice Standalone API</strong></p></td><td><p> </p></td></tr><tr><td valign="top" style="background-color:rgb(191,191,191)"><p align="center"><strong>EasyMonkeDevice</strong></p></td><td style="background-color:rgb(191,191,191)"><p align="center"><strong>Comment</strong></p><p align="center"><strong> </strong></p></td></tr><tr><td valign="top"><p><span style="color:rgb(0,0,136)">boolean</span><span style="color:rgb(34,34,34)"> exists(By selector)</span></p><p><span style="color:rgb(148,54,52)">Checks if the specified object exists.</span></p></td><td><p><span style="color:rgb(34,34,34)"> </span></p></td></tr></tbody></table> ## 6. 验证性代码 ~~~ from com.android.monkeyrunner import MonkeyRunner,MonkeyDevice,MonkeyImage from com.android.monkeyrunner.easy import EasyMonkeyDevice,By from com.android.chimpchat.hierarchyviewer import HierarchyViewer from com.android.hierarchyviewerlib.models import ViewNode, Window from java.awt import Point #from com.android.hierarchyviewerlib.device import #Connect to the target device device = MonkeyRunner.waitForConnection() eDevice=EasyMonkeyDevice(device) device.startActivity(component="com.example.android.notepad/com.example.android.notepad.NotesList") ''' MonkeyRunner.sleep(2) print 'Show Menu Options' device.press('KEYCODE_MENU', MonkeyDevice.DOWN_AND_UP); MonkeyRunner.sleep(3) print 'Press on the menu entry of \ \"Add note\"' eDevice.touch(By.id('id/title'), MonkeyDevice.DOWN) MonkeyRunner.sleep(2) device.press('KEYCODE_MENU', MonkeyDevice.DOWN_AND_UP); ''' #Step 1: try touching on the first note eDevice.touch(By.id('id/text1'), MonkeyDevice.DOWN_AND_UP) #Step 2: Get the window ID winId = 'com.example.android.notepad/\ com.example.android.notepad.NoteEditor' #Need to sleep a while till ready MonkeyRunner.sleep(3) winId = eDevice.getFocusedWindowId() if(winId == winId): print "Edit Note WinId is:",\ winId.encode('utf-8') else: print "Failed" exit(1) #Step3: is note EditText exist? noteId = 'id/note' if True == eDevice.exists(By.id(noteId)): print 'Note exist' else: print 'Note not found!' exit(2) #Step4: is note EditText visible? if True == eDevice.visible(By.id(noteId)): print 'Note is visible' else: print 'Note is invisible' exit(3) #Step 4: getText text = eDevice.getText(By.id(noteId)) print 'Note text:',text.encode('utf-8') #Step 5: setText eDevice.type(By.id(noteId), 'New') #Step 6: locate locate = eDevice.locate(By.id(noteId)) print 'Location(x,y,w,h) is:',locate ~~~ ## 7. EasyMonkeyDevice Source Code for Your Reference  ~~~ /*jadclipse*/// Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov. package com.android.monkeyrunner.easy; import com.android.chimpchat.hierarchyviewer.HierarchyViewer; import com.android.hierarchyviewerlib.models.ViewNode; import com.android.monkeyrunner.JythonUtils; import com.google.common.base.Preconditions; import org.python.core.*; public class By extends PyObject implements ClassDictInit { public static void classDictInit(PyObject dict) { JythonUtils.convertDocAnnotationsForClass(com/android/monkeyrunner/easy/By, dict); } By(String id) { this.id = id; } public static By id(PyObject args[], String kws[]) { ArgParser ap = JythonUtils.createArgParser(args, kws); Preconditions.checkNotNull(ap); String id = ap.getString(0); return new By(id); } public static By id(String id) { return new By(id); } public ViewNode findView(HierarchyViewer viewer) { return viewer.findViewById(id); } private String id; } /* DECOMPILATION REPORT Decompiled from: D:\Projects\Workspace\JarPackages\monkeyrunner.jar Total time: 69 ms Jad reported messages/errors: The class file version is 50.0 (only 45.3, 46.0 and 47.0 are supported) Exit status: 0 Caught exceptions: */ ~~~ ## 8. By Class Source Code for Your Better Reference ~~~ /*jadclipse*/// Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov. package com.android.monkeyrunner.easy; import com.android.chimpchat.core.IChimpDevice; import com.android.chimpchat.core.TouchPressType; import com.android.chimpchat.hierarchyviewer.HierarchyViewer; import com.android.hierarchyviewerlib.models.ViewNode; import com.android.monkeyrunner.JythonUtils; import com.android.monkeyrunner.MonkeyDevice; import com.google.common.base.Preconditions; import java.util.Set; import org.eclipse.swt.graphics.Point; import org.python.core.*; // Referenced classes of package com.android.monkeyrunner.easy: // By public class EasyMonkeyDevice extends PyObject implements ClassDictInit { public static void classDictInit(PyObject dict) { JythonUtils.convertDocAnnotationsForClass(com/android/monkeyrunner/easy/EasyMonkeyDevice, dict); } public EasyMonkeyDevice(MonkeyDevice device) { mDevice = device; mHierarchyViewer = device.getImpl().getHierarchyViewer(); } public void touch(PyObject args[], String kws[]) { ArgParser ap = JythonUtils.createArgParser(args, kws); Preconditions.checkNotNull(ap); By selector = getSelector(ap, 0); String tmpType = ap.getString(1); TouchPressType type = TouchPressType.fromIdentifier(tmpType); Preconditions.checkNotNull(type, (new StringBuilder()).append("Invalid touch type: ").append(tmpType).toString()); touch(selector, type); } public void touch(By selector, TouchPressType type) { Point p = getElementCenter(selector); mDevice.getImpl().touch(p.x, p.y, type); } public void type(PyObject args[], String kws[]) { ArgParser ap = JythonUtils.createArgParser(args, kws); Preconditions.checkNotNull(ap); By selector = getSelector(ap, 0); String text = ap.getString(1); type(selector, text); } public void type(By selector, String text) { Point p = getElementCenter(selector); mDevice.getImpl().touch(p.x, p.y, TouchPressType.DOWN_AND_UP); mDevice.getImpl().type(text); } public PyTuple locate(PyObject args[], String kws[]) { ArgParser ap = JythonUtils.createArgParser(args, kws); Preconditions.checkNotNull(ap); By selector = getSelector(ap, 0); ViewNode node = selector.findView(mHierarchyViewer); Point p = HierarchyViewer.getAbsolutePositionOfView(node); PyTuple tuple = new PyTuple(new PyObject[] { new PyInteger(p.x), new PyInteger(p.y), new PyInteger(node.width), new PyInteger(node.height) }); return tuple; } public boolean exists(PyObject args[], String kws[]) { ArgParser ap = JythonUtils.createArgParser(args, kws); Preconditions.checkNotNull(ap); By selector = getSelector(ap, 0); return exists(selector); } public boolean exists(By selector) { ViewNode node = selector.findView(mHierarchyViewer); return node != null; } public boolean visible(PyObject args[], String kws[]) { ArgParser ap = JythonUtils.createArgParser(args, kws); Preconditions.checkNotNull(ap); By selector = getSelector(ap, 0); return visible(selector); } public boolean visible(By selector) { ViewNode node = selector.findView(mHierarchyViewer); return mHierarchyViewer.visible(node); } public String getText(PyObject args[], String kws[]) { ArgParser ap = JythonUtils.createArgParser(args, kws); Preconditions.checkNotNull(ap); By selector = getSelector(ap, 0); return getText(selector); } public String getText(By selector) { ViewNode node = selector.findView(mHierarchyViewer); return mHierarchyViewer.getText(node); } public String getFocusedWindowId(PyObject args[], String kws[]) { return getFocusedWindowId(); } public String getFocusedWindowId() { return mHierarchyViewer.getFocusedWindowName(); } public PyObject __findattr_ex__(String name) { if(!EXPORTED_METHODS.contains(name)) return mDevice.__findattr_ex__(name); else return super.__findattr_ex__(name); } private By getSelector(ArgParser ap, int i) { return (By)ap.getPyObject(i).__tojava__(com/android/monkeyrunner/easy/By); } private Point getElementCenter(By selector) { ViewNode node = selector.findView(mHierarchyViewer); if(node == null) { throw new PyException(Py.ValueError, String.format("View not found: %s", new Object[] { selector })); } else { Point p = HierarchyViewer.getAbsoluteCenterOfView(node); return p; } } private MonkeyDevice mDevice; private HierarchyViewer mHierarchyViewer; private static final Set EXPORTED_METHODS = JythonUtils.getMethodNames(com/android/monkeyrunner/easy/EasyMonkeyDevice); } /* DECOMPILATION REPORT Decompiled from: D:\Projects\Workspace\JarPackages\monkeyrunner.jar Total time: 920 ms Jad reported messages/errors: The class file version is 50.0 (only 45.3, 46.0 and 47.0 are supported) Exit status: 0 Caught exceptions: */ ~~~ <table cellspacing="0" cellpadding="0" width="539" class=" " style="margin:0px 0px 10px; padding:0px; border-collapse:collapse; width:668px; max-width:100%; word-wrap:break-word!important"><tbody style="margin:0px; padding:0px; max-width:100%; word-wrap:break-word!important"><tr style="margin:0px; padding:0px; max-width:100%; word-wrap:break-word!important"><td valign="top" width="112" height="39" style="border-style:solid; border-color:rgb(0,0,0); margin:0px; padding:4px; word-break:break-all; max-width:100%; word-wrap:break-word!important"> </td></tr><tr style="margin:0px; padding:0px; max-width:100%; word-wrap:break-word!important"><td valign="top" width="111" height="13" style="border-style:solid; border-color:rgb(0,0,0); margin:0px; padding:4px; word-break:break-all; max-width:100%; word-wrap:break-word!important; background-color:rgb(190,192,191)"><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; max-width:100%; clear:both; min-height:1em; white-space:pre-wrap; word-wrap:break-word!important"><span style="margin:0px; padding:0px; max-width:100%; word-wrap:break-word!important">作者</span></p></td><td valign="top" width="112" height="13" style="border-style:solid; border-color:rgb(0,0,0); margin:0px; padding:4px; word-break:break-all; max-width:100%; word-wrap:break-word!important; background-color:rgb(190,192,191)"><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; max-width:100%; clear:both; min-height:1em; white-space:pre-wrap; word-wrap:break-word!important"><span style="margin:0px; padding:0px; max-width:100%; word-wrap:break-word!important">自主博客</span></p></td><td valign="top" width="111" height="13" style="border-style:solid; border-color:rgb(0,0,0); margin:0px; padding:4px; word-break:break-all; max-width:100%; word-wrap:break-word!important; background-color:rgb(190,192,191)"><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; max-width:100%; clear:both; min-height:1em; white-space:pre-wrap; word-wrap:break-word!important"><span style="margin:0px; padding:0px; max-width:100%; word-wrap:break-word!important">微信</span></p></td><td valign="top" width="112" height="13" style="border-style:solid; border-color:rgb(0,0,0); margin:0px; padding:4px; word-break:break-all; max-width:100%; word-wrap:break-word!important; background-color:rgb(190,192,191)"><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; max-width:100%; clear:both; min-height:1em; white-space:pre-wrap; word-wrap:break-word!important"><span style="margin:0px; padding:0px; max-width:100%; font-family:Helvetica; letter-spacing:0px; word-wrap:break-word!important">CSDN</span></p></td></tr><tr style="margin:0px; padding:0px; max-width:100%; word-wrap:break-word!important"><td valign="top" width="111" height="39" style="border-style:solid; border-color:rgb(0,0,0); margin:0px; padding:4px; word-break:break-all; max-width:100%; word-wrap:break-word!important; background-color:rgb(227,228,228)"><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; max-width:100%; clear:both; min-height:1em; white-space:pre-wrap; word-wrap:break-word!important"><span style="margin:0px; padding:0px; max-width:100%; word-wrap:break-word!important">天地会珠海分舵</span></p></td><td valign="top" width="112" height="39" style="border-style:solid; border-color:rgb(0,0,0); margin:0px; padding:4px; word-break:break-all; max-width:100%; word-wrap:break-word!important"><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; max-width:100%; clear:both; min-height:1em; white-space:pre-wrap; word-wrap:break-word!important"><span style="margin:0px; padding:0px; max-width:100%; font-size:11px; font-family:Helvetica; letter-spacing:0px; word-wrap:break-word!important"><a target="_blank" href="http://techgogogo.com/">http://techgogogo.com</a></span><span style="margin:0px; padding:0px; max-width:100%; font-family:Helvetica; font-size:11px; letter-spacing:0px; word-wrap:break-word!important"/></p><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; max-width:100%; clear:both; min-height:14px; white-space:pre-wrap; font-family:Helvetica; word-wrap:break-word!important"><br style="margin:0px; padding:0px; max-width:100%; word-wrap:break-word!important"/></p></td><td valign="top" width="111" height="39" style="border-style:solid; border-color:rgb(0,0,0); margin:0px; padding:4px; word-break:break-all; max-width:100%; word-wrap:break-word!important"><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; max-width:100%; clear:both; min-height:1em; white-space:pre-wrap; word-wrap:break-word!important"><span style="margin:0px; padding:0px; max-width:100%; word-wrap:break-word!important">服务号</span><span style="margin:0px; padding:0px; max-width:100%; font-size:10px; font-family:Helvetica; letter-spacing:0px; word-wrap:break-word!important">:TechGoGoGo</span></p><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; max-width:100%; clear:both; min-height:1em; white-space:pre-wrap; word-wrap:break-word!important"><span style="margin:0px; padding:0px; max-width:100%; word-wrap:break-word!important">扫描码</span><span style="margin:0px; padding:0px; max-width:100%; font-size:10px; font-family:Helvetica; letter-spacing:0px; word-wrap:break-word!important">:</span></p><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; max-width:100%; clear:both; min-height:14px; white-space:pre-wrap; font-family:Helvetica; word-wrap:break-word!important"><img src="image/47cf4f9ec59b0ef1f807a6c33ab5ce5f.jpg" alt="" style="max-width:100%; margin:0px; padding:0px; height:auto!important; word-wrap:break-word!important; width:auto!important; visibility:visible!important"/></p></td><td valign="top" width="112" height="39" style="border-style:solid; border-color:rgb(0,0,0); margin:0px; padding:4px; word-break:break-all; max-width:100%; word-wrap:break-word!important"><p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; max-width:100%; clear:both; min-height:1em; white-space:pre-wrap; color:rgb(62,62,62); font-family:'Helvetica Neue',Helvetica,'Hiragino Sans GB','Microsoft YaHei',΢ÈíÑźÚ,Arial,sans-serif; font-size:18px; line-height:28.7999992370605px; word-wrap:break-word!important"><span style="margin:0px; padding:0px; max-width:100%; color:rgb(0,0,0); font-size:11px; font-family:Helvetica; letter-spacing:0px; word-wrap:break-word!important"><a target="_blank" href="http://blog.csdn.net/zhubaitian">http://blog.csdn.net/zhubaitian</a></span><span style="margin:0px; padding:0px; max-width:100%; color:rgb(0,0,0); font-family:Helvetica; font-size:11px; letter-spacing:0px; line-height:28.7999992370605px; word-wrap:break-word!important"/></p><div><span style="margin:0px; padding:0px; max-width:100%; color:rgb(0,0,0); font-family:Helvetica; font-size:11px; letter-spacing:0px; line-height:28.7999992370605px; word-wrap:break-word!important"><br/></span></div></td></tr></tbody></table>