Android Monkey(转载)
這兩天在讀Android Monkey的源代碼.代碼不多,放出分享.
我現說一下,Monkey是干什么的:簡單的說就是,模擬用戶的touch screen和keyboard的輸入.其實這個功能就已經很恐怖了.? Google自己說的下面:
// Only bind this to local host.? This means that you can only
// talk to the monkey locally, or though adb port forwarding.
就是覬覦這個強大的力量.Monkey是用JAVA寫成的,但是我們確可以這樣運行:
$adb shell monkey ......
這是為什么呢?是因為在/system/bin目錄下有一個monkey的shell腳本.內容如下:
# Script to start "monkey" on the device, which has a very rudimentary
# shell.
#
base=/system
export CLASSPATH=$base/framework/monkey.jar
exec app_process $base/bin com.android.commands.monkey.Monkey $*
exec 會運行起/system/framework/monkey.jar這只Java程序.后面我們還會用到這個腳本.
先給出Monkey的架構圖:
又是我的手繪圖.哈哈.實際上,并不復雜.
Monkey.java 里面有main()函數.而main()->Run().Run()里面作了下面的操作:
1.processOptions()初始化參數(通過傳入入參來初始化參數).還有一些的操作函數如:nextOption() nextOptionLong()。。
2.做接口的檢查,也就是申請這些接口資源.
3.關鍵的一步:
if(mServerPort!=1)
{ try{
mEventSource = new MonkeySourceNetWork(mServerPort);
...省略
開始ServerSocket.監聽用戶輸入的command.
4.mNetworkMonitor.Start();開始監控網絡狀態
5.關鍵的一步:
runMonkeyCycles(),代碼如下:
while()
{
MonkeyEvent ev = mEventSource.getNextEvent();
ev.inject(....);
...省略
開始Event loop,把每個CommandQueue中的消息都執行.
6.mNetworkMonitor.Stop()
這里我們看到使用了SocketServer,所以理論上來說,可以在PC端發送command給device,但是必須透過USB的連接.這點我在上面已經說的很清楚了.(PC端,Android不可能幫你實現,我們只要在PC端使用Socket向device發送命令就可以了).
好了,我們接著往下分析:
MonkeyEvent的實現是典型的OO思想.
MonkeyEvent.java僅僅是一個abstract class.
最重要的方法都由子類去實現.(把Event放入當前的Activity去運行)
public abstract int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose);
monkey*Event.java都是MonkeyEvent.java的子類.
? ?
來講一下,MonkeySourceNetwork.java.
這個類相對較大,里面有許多的內嵌類.(ps. 我不是寫Java出身的,看到內嵌類就不符合我的審美習慣)
1.有一個MonkeyCommand的類,這是一個interface. *Command都是他的子類.
其中定義了一個很重要的方法:這個方法將string 類型的command轉換為MonkeyEvent對象,并放入
commandQueue.
MonkeyCommandReturn translateCommand(List<String> command, CommandQueue queue);
好了,首先MonkeyCommandReturn又是一個類,是命令執行成功還是失敗的一個類.
commandQueue是實際上是一個interface,然后它的實現是在CommandQueueImpl這個類中.
實現了如下的方法:
public void enqueueEvent(MonkeyEvent e) {
queuedEvents.offer(e);
}
將Event放入queueEvents隊列中.而queueEvents是這樣定義的:
private final Queue<MonkeyEvent> queuedEvents = new LinkedList<MonkeyEvent>();
無非就是一個LinkedList而已拉.
2.下面我在來說說MonkeySourceNetwork類中的方法:
private void translateCommand(String commandLine)
和上面的方法同名.實際上這個translateCommand是上面的封裝.我們來RTFS:
List<String> parts = commandLineSplit(commandLine);
if (parts.size() > 0) {
MonkeyCommand command = COMMAND_MAP.get(parts.get(0));
if (command != null) {
MonkeyCommandReturn ret = command.translateCommand(parts,commandQueue);
COMMAND_MAP這是個什么東西呢?
private static final Map<String, MonkeyCommand> COMMAND_MAP = new HashMap<String, MonkeyCommand>();
看了沒,是一個Map.以Command string作為Key, MonkeyCommand作為Value.這樣的話,就建立了,
輸入的命令和Command的關系。
static {
// Add in all the commands we support
COMMAND_MAP.put("flip", new FlipCommand());
COMMAND_MAP.put("touch", new TouchCommand());
COMMAND_MAP.put("trackball", new TrackballCommand());
COMMAND_MAP.put("key", new KeyCommand());
COMMAND_MAP.put("sleep", new SleepCommand());
COMMAND_MAP.put("wake", new WakeCommand());
COMMAND_MAP.put("tap", new TapCommand());
COMMAND_MAP.put("press", new PressCommand());
COMMAND_MAP.put("type", new TypeCommand());
COMMAND_MAP.put("listvar", new MonkeySourceNetworkVars.ListVarCommand());
COMMAND_MAP.put("getvar", new MonkeySourceNetworkVars.GetVarCommand());
}
但也不是所有的命令都放入COMMAND_MAP中.quit 和 done 就是例外,原因也很簡單,沒必要放進Map.
再來分析下這條語句:MonkeyCommandReturn ret = command.translateCommand(parts,commandQueue);
首先,command已經是MonkeyCommand的sub class了.so 調用translateCommand將會表現出不同的行為.
例如,command假設為PressCommand.則translateCommand的表現為:
queue.enqueueEvent(new MonkeyKeyEvent(....))
每一個MonkeyEvent又都代表了一些對AP GUI錯作.所以,也就是把操作放入了Queue.
okay.就這么多了.才不多這次就說這么多吧.我再附上我的手繪圖,希望有幫助.
? ?
轉載于:https://www.cnblogs.com/xiwix/archive/2012/04/15/2450976.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Android Monkey(转载)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 视频:easyhadoop聚会hive和
- 下一篇: 联想K系引领智能电视潮流,Android