💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
## 1.背景 鉴于网上使用MonkeyImage的实例除了方法sameAs外很难找到,所以本人把实践各个API的过程记录下来然自己有更感性的认识,也为往后的工作打下更好的基础。同时也和上一篇文章《[MonkeyDevcie API 实践全记录](http://blog.csdn.net/zhubaitian/article/details/39926209)》起到相互呼应的作用。 因为并没有MonkeyRunner的项目背景,所以这里更多的是描述各个API是怎么一回事,而不是描述在什么场景下需要用到。也就是说是去回答What,而不是How。 首先我们先看下官方给出的MonkeyImage的API描述,对比我现在反编译的最新的源码是一致的: <table border="1" cellspacing="0" cellpadding="0" width="697"><tbody><tr><td valign="top" style="background-color:rgb(191,191,191)"><p align="center"><strong><span style="color:rgb(34,34,34)">Return Type</span></strong></p></td><td valign="top" style="background-color:rgb(191,191,191)"><p align="center"><strong>Methods</strong></p></td><td style="background-color:rgb(191,191,191)"><p align="center"><strong>Comment</strong></p></td></tr><tr><td valign="top"><p align="right"><em><span style="color:rgb(34,34,34)">string</span></em></p></td><td valign="top"><nobr><p><span style="color:rgb(34,34,34)"><a target="_blank" href="http://developer.android.com/tools/help/MonkeyImage.html#convertToBytes"><span style="color:rgb(37,138,175)">convertToBytes</span></a></span><span style="color:rgb(34,34,34)"> </span><span style="color:rgb(34,34,34)">(<em>string</em> </span>format)</p></nobr><p><span style="color:rgb(34,34,34)">Converts the current image to a particular format and returns it as a </span><em>string</em> that you can then access as an <em>iterable</em> of binary bytes.</p></td><td><p> </p></td></tr><tr><td valign="top"><p align="right"><em><span style="color:rgb(34,34,34)">tuple</span></em></p></td><td valign="top"><nobr><p><span style="color:rgb(34,34,34)"><a target="_blank" href="http://developer.android.com/tools/help/MonkeyImage.html#getRawPixel"><span style="color:rgb(37,138,175)">getRawPixel</span></a></span><span style="color:rgb(34,34,34)"> </span><span style="color:rgb(34,34,34)">(<em>integer</em> </span>x, <em>integer</em> y)</p></nobr><p><span style="color:rgb(34,34,34)">Returns the single pixel at the image location (x,y), as an a </span><em>tuple</em> of <em>integer</em>, in the form (a,r,g,b).</p></td><td><p> </p></td></tr><tr><td valign="top"><p align="right"><em><span style="color:rgb(34,34,34)">integer</span></em></p></td><td valign="top"><nobr><p><span style="color:rgb(34,34,34)"><a target="_blank" href="http://developer.android.com/tools/help/MonkeyImage.html#getRawPixelInt"><span style="color:rgb(37,138,175)">getRawPixelInt</span></a></span><span style="color:rgb(34,34,34)"> </span><span style="color:rgb(34,34,34)">(<em>integer</em> </span>x, <em>integer</em> y)</p></nobr><p><span style="color:rgb(34,34,34)">Returns the single pixel at the image location (x,y), as a 32-bit </span><em>integer</em>.</p></td><td><p> </p></td></tr><tr><td valign="top"><p align="right"><code><span style="color:rgb(0,102,0)"><a target="_blank" href="http://developer.android.com/tools/help/MonkeyImage.html"><span style="color:rgb(37,138,175)">MonkeyImage</span></a></span></code></p></td><td valign="top"><nobr><p><span style="color:rgb(34,34,34)"><a target="_blank" href="http://developer.android.com/tools/help/MonkeyImage.html#getSubImage"><span style="color:rgb(37,138,175)">getSubImage</span></a></span><span style="color:rgb(34,34,34)"> </span><span style="color:rgb(34,34,34)">(<em>tuple</em> </span>rect)</p></nobr><p><span style="color:rgb(34,34,34)">Creates a new </span><code><span style="color:rgb(0,102,0)">MonkeyImage</span></code><span style="color:rgb(34,34,34)"> </span><span style="color:rgb(34,34,34)">object from a rectangular selection of the current image.</span></p></td><td><p> </p></td></tr><tr><td valign="top"><p align="right"><em><span style="color:rgb(34,34,34)">boolean</span></em></p></td><td valign="top"><nobr><p><span style="color:rgb(34,34,34)"><a target="_blank" href="http://developer.android.com/tools/help/MonkeyImage.html#sameAs"><span style="color:rgb(37,138,175)">sameAs</span></a></span><span style="color:rgb(34,34,34)"> </span><span style="color:rgb(34,34,34)">(</span><code><span style="color:rgb(0,102,0)"><a target="_blank" href="http://developer.android.com/tools/help/MonkeyImage.html"><span style="color:rgb(37,138,175)">MonkeyImage</span></a></span></code><span style="color:rgb(34,34,34)"> </span><span style="color:rgb(34,34,34)">other, </span><em>float</em> percent)</p></nobr><p><span style="color:rgb(34,34,34)">Compares this </span><code><span style="color:rgb(0,102,0)">MonkeyImage</span></code><span style="color:rgb(34,34,34)"> </span><span style="color:rgb(34,34,34)">object to another and returns the result of the comparison. The</span><code><span style="color:rgb(0,102,0)">percent</span></code><span style="color:rgb(34,34,34)"> </span><span style="color:rgb(34,34,34)">argument specifies the percentage difference that is allowed for the two images to be "equal".</span></p></td><td><p> </p></td></tr><tr><td valign="top"><p align="right"><em><span style="color:rgb(34,34,34)">void</span></em></p></td><td valign="top"><nobr><p><span style="color:rgb(34,34,34)"><a target="_blank" href="http://developer.android.com/tools/help/MonkeyImage.html#writeToFile"><span style="color:rgb(37,138,175)">writeToFile</span></a></span><span style="color:rgb(34,34,34)"> </span><span style="color:rgb(34,34,34)">(<em>string</em> </span>path, <em>string</em> format)</p></nobr><p><span style="color:rgb(34,34,34)">Writes the current image to the file specified by </span><code><span style="color:rgb(0,102,0)">filename</span></code><span style="color:rgb(34,34,34)">, in the format specified by </span><code><span style="color:rgb(0,102,0)">format</span></code><span style="color:rgb(34,34,34)">.</span></p></td><td><p> </p></td></tr></tbody></table> ## 2.String convertToBytes(string format) ### 2.1  示例 ~~~ img = device.takeSnapshot() png1 = img.convertToBytes() png2 = img.convertToBytes() bmp = img.convertToBytes('bmp') jpg = img.convertToBytes('JPG') gif = img.convertToBytes('gif') raw = img.convertToBytes('raw') invalid = img.convertToBytes('xxx') #is the 2 pngs equal? print "Two png is equal in bytes:",png1 == png2 #is the png equals to bmp? print "png and bmp is equal in bytes:", png1 == bmp #is the jpg eqals to the raw? print "jpg and bmp is equals in bytes:",jpg == bmp #is the jpg eqals to the xxx? print "jpg is a valid argument:",jpg != invalid #is the gif eqals to the xxx? print "gif is a valid argument:",gif != invalid #is the bmp eqals to the xxx? print "bmp is a valid argument:",bmp != invalid #is the raw equas to xxxx? aims at checking whether argument 'raw' is invalid like 'xxx' print 'raw is a valid argument:',raw != invalid #would invalid argument drop to png by default? print 'Would invalid argument drop to png by default:',png1 == invalid ~~~ 输出: ![](https://box.kancloud.cn/2016-08-15_57b17559701d2.jpg) ### 2.2 分析 除了默认的png,常用格式jpg,gif都支持,但bmp格式无效,至于还支持什么其他格式,尝试跟踪了下代码,没有找到想要的结果 ## 3. tuple getRawPixel(integer x, integer y)和Integer getRawPixelInt (integer x, integer y) ### 3.1 示例 ~~~ viewer = device.getHierarchyViewer() note = viewer.findViewById('id/title') text = viewer.getText(note) print text.encode('utf-8') point = viewer.getAbsoluteCenterOfView(note) x = point.x y = point.y img = device.takeSnapshot() pixelTuple = img.getRawPixel(x,y) pixelInt = img.getRawPixelInt(x,y) print "Pixel in tuple:",pixelTuple print "Pixel in int:", pixelInt ~~~ 输出: ![](https://box.kancloud.cn/2016-08-15_57b17559bc80d.jpg) ### 3.2 分析 这里把两个相似的方法放到一起来比较,他们都是获得指定一个坐标的argb值,其中a就是alpha(透明度),rgb就是颜色三元组红绿蓝了。但前者返回的是一个元组,后者返回的是整型。 那么两个类型的值是怎么对应起来的呢?其实就是第一个方法的元组的返回值(a,r,g,b)中的每个值转换成8个bit的二进制值然后按顺序从左到右排列起来再转换成十进制整型就是第二个方法的返回值了。 以示例输出为例,比如b在第一个返回值中是141,换成二进制就是1001101,其他雷同。 ![](https://box.kancloud.cn/2016-08-15_57b17559dcc86.jpg) 再看第二个方法的整型返回值是-7500403,转换成二进制其实就是11111111100011011000110110001101(至于下图calculator转换后为什么前面那么多个1,其实不用管他,因为是负数所以前面要加上FF之类而已),那么最后的8个bit转换成十进制其实就是上面的的141. ![](https://box.kancloud.cn/2016-08-15_57b1755a1c028.jpg) ## 4. MonkeyImage getSubImage(tuple rect) ### 4.1 示例 ~~~ 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 targetDevice targetDevice = MonkeyRunner.waitForConnection() easy_device = EasyMonkeyDevice(targetDevice) #touch a button by id would need this targetDevice.startActivity(component="com.example.android.notepad/com.example.android.notepad.NotesList") #invoke the menu options MonkeyRunner.sleep(6) #targetDevice.press('KEYCODE_MENU', MonkeyDevice.DOWN_AND_UP); ''' public ViewNode findViewById(String id) * @param id id for the view. * @return view with the specified ID, or {@code null} if no view found. ''' #MonkeyRunner.alert("Continue?", "help", "Ok?") pic = targetDevice.takeSnapshot() pic = pic.getSubImage((0,38,480,762)) newPic = targetDevice.takeSnapshot() newPic = newPic.getSubImage((0,38,480,762)) print (newPic.sameAs(pic,1.0)) newPic.writeToFile('./shot1.png','png') ~~~ ### 4.2 分析 以上示例流程是 - 打开NotePad的NotesList Activity - 按下Menu Options按钮弹出“Add note”这个Menu Entry - 截取一个屏幕 - 调用getSubImage来取得去掉屏幕最上面的状态栏(因为有时间不断变化,所以每截屏一次可能都会有所改变)和最下面的Menu Options的一个Image - 再重复以上两个步骤取得另外一个Image - 比较以上两个image是否相同 - 把第二个image写到本地。 ## 5 boolean sameAs(MonkeyImage other, float percent) ### 5.1 示例 见4.1 ### 5.2 分析 流程见4.1,这里要注意第二个浮点型的参数是从0.0到1.0, 1.0代表必须100%相同,0.5代表可以有50%的Error Tolerance. ## 6. void writeToFile (string path, string format) ### 6.1 示例 请参见第4章节 ### 6.2 分析 参数很明了,这里需要提一下的是第一个参数路径,如果你填写的是相对路径的话,base用得是MonkeyRunner。也就是说示例中的图片最终是保存在我的monkeyrunner可执行程序的上一层目录。 <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>