## 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
~~~
輸出:

### 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
~~~
輸出:

### 3.2 分析
這里把兩個相似的方法放到一起來比較,他們都是獲得指定一個坐標的argb值,其中a就是alpha(透明度),rgb就是顏色三元組紅綠藍了。但前者返回的是一個元組,后者返回的是整型。
那么兩個類型的值是怎么對應起來的呢?其實就是第一個方法的元組的返回值(a,r,g,b)中的每個值轉換成8個bit的二進制值然后按順序從左到右排列起來再轉換成十進制整型就是第二個方法的返回值了。
以示例輸出為例,比如b在第一個返回值中是141,換成二進制就是1001101,其他雷同。

再看第二個方法的整型返回值是-7500403,轉換成二進制其實就是11111111100011011000110110001101(至于下圖calculator轉換后為什么前面那么多個1,其實不用管他,因為是負數所以前面要加上FF之類而已),那么最后的8個bit轉換成十進制其實就是上面的的141.

## 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',?¢èí??oú,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>
- 前言
- MonkeyRunner創建一個Note的實例
- MonkeyRunner在Windows下的Eclipse開發環境搭建步驟(兼解決網上Jython配置出錯的問題)
- MonkenRunner通過HierarchyViewer定位控件的方法和建議(Appium/UIAutomator/Robotium姊妹篇)
- MonkeyDevcie API 實踐全記錄
- MonkeyImage API 實踐全記錄
- EasyMonkeyDevice vs MonkeyDevice&amp;HierarchyViewer API Mapping Matrix
- adb概覽及協議參考
- MonkeyRunner源碼分析之-誰動了我的截圖?
- MonkeyRunner源碼分析之與Android設備通訊方式
- MonkeyRunner源碼分析之啟動
- Monkey源碼分析之運行流程
- Monkey源碼分析之事件源
- Monkey源碼分析番外篇之WindowManager注入事件如何跳出進程間安全限制
- Monkey源碼分析番外篇之Android注入事件的三種方法比較
- Monkey源碼分析之事件注入
- monkey源碼分析之事件注入方法變化
- MonkeyRunner源碼分析之工作原理圖
- Android自動化測試框架新書:&lt;&lt;MonnkeyRunner實現原理剖析&gt;&gt;交流