版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
【移動(dòng)應(yīng)用開發(fā)技術(shù)】MonkeyRunner源碼分析之與Android設(shè)備通訊方式
如前文《誰動(dòng)了我的截圖?--MonkeyrunnertakeSnapshot方法源碼跟蹤分析》所述,本文主要會(huì)嘗試描述android的自動(dòng)化測(cè)試框架MonkeyRunner究竟是如何和目標(biāo)設(shè)備進(jìn)行通信的。在上一篇文章中我們其實(shí)已經(jīng)描述了其中一個(gè)方法,就是通過adb協(xié)議發(fā)送adb服務(wù)器請(qǐng)求的方式驅(qū)動(dòng)android設(shè)備的adbd守護(hù)進(jìn)程去獲取FrameBuffer的數(shù)據(jù)生成屏幕截圖。那么MonkeyRunner還會(huì)用其他方式和目標(biāo)設(shè)備進(jìn)行通信嗎?答案是肯定的,且看我們一步步分析道來。MonkeyRunner和目標(biāo)設(shè)備打交道都是通過ChimpChat層進(jìn)行封裝分發(fā)但最終是在ddmlib進(jìn)行處理的,其中囊括的方法大體如下:以下是MonkeyDevice所有請(qǐng)求對(duì)應(yīng)的與設(shè)備通信方式請(qǐng)求是否需要和目標(biāo)設(shè)備通信通信方式注解發(fā)送adbshell命令getSystemProperty是發(fā)送adbshell命令installPackage是發(fā)送adbshell命令傳送數(shù)據(jù)時(shí)發(fā)送adb協(xié)議請(qǐng)求,發(fā)送安裝命令時(shí)使用adbshell命令startActivity是發(fā)送adbshell命令broadcastIntent是發(fā)送adbshell命令instrument是發(fā)送adbshell命令shell是發(fā)送adbshell命令命令為空,所以相當(dāng)于直接執(zhí)行”adbshell“removePackage是發(fā)送adbshell命令發(fā)送monkey命令getProperty是發(fā)送monkey命令
wake是發(fā)送monkey命令
dispose
是發(fā)送monkey命令
press是發(fā)送monkey命令
type是發(fā)送monkey命令
touch是發(fā)送monkey命令
drag是發(fā)送monkey命令
getViewIdList是發(fā)送monkey命令
getView是發(fā)送monkey命令
getViews是發(fā)送monkey命令
getRootView是發(fā)送monkey命令
發(fā)送adb協(xié)議請(qǐng)求takeSnapshot是發(fā)送adb協(xié)議請(qǐng)求reboot是發(fā)送adb協(xié)議命令installPackage是發(fā)送adb協(xié)議請(qǐng)求相當(dāng)于直接發(fā)送adb命令行命令’adbpush’分析之前請(qǐng)大家準(zhǔn)備好對(duì)應(yīng)的幾個(gè)庫的源碼:在剖析如何發(fā)送monkey命令之前,我們需要先去了解一個(gè)類,因?yàn)檫@個(gè)類是處理所有monkey命令的關(guān)鍵,這就是ChimpChat庫的ChimpManager類。我們先查看其構(gòu)造函數(shù),看它是怎么初始化的:/**/privateSocketmonkeySocket;/**//**/privateBufferedWritermonkeyWriter;/**//**/privateBufferedReadermonkeyReader;/**//**//**/publicChimpManager(SocketmonkeySocket)/**/throwsIOException/**/{/*62*/this.monkeySocket=monkeySocket;/*63*/this.monkeyWriter=newBufferedWriter(newOutputStreamWriter(monkeySocket.getOutputStream()));/**//*65*/this.monkeyReader=newBufferedReader(newInputStreamReader(monkeySocket.getInputStream()));/**/}/**/privateChimpManagermanager;/**//**/publicAdbChimpDevice(IDevicedevice)/**/{/*70*/this.device=device;/*71*/this.manager=createManager("",12345);/**//*73*/Preconditions.checkNotNull(this.manager);/**/}好,那么我們繼續(xù)看AdbChimpDevice里面的方法createManager是如何對(duì)ChimpManager進(jìn)行初始化的:/**/privateChimpManagercreateManager(Stringaddress,intport){/**/try{/*125*/this.device.createForward(port,port);/**/}catch(TimeoutExceptione){/*127*/LOG.log(Level.SEVERE,"Timeoutcreatingadbportforwarding",e);/*128*/returnnull;/**/}catch(AdbCommandRejectedExceptione){/*130*/LOG.log(Level.SEVERE,"Adbrejectedadbportforwardingcommand:"+e.getMessage(),e);/*131*/returnnull;/**/}catch(IOExceptione){/*133*/LOG.log(Level.SEVERE,"Unabletocreateadbportforwarding:"+e.getMessage(),e);/*134*/returnnull;/**/}/**//*137*/Stringcommand="monkey--port"+port;/*138*/executeAsyncCommand(command,newLoggingOutputReceiver(LOG,Level.FINE));/**//**/try/**/{/*142*/Thread.sleep(1000L);/**/}catch(InterruptedExceptione){/*144*/LOG.log(Level.SEVERE,"Unabletosleep",e);/**/}/**/InetAddressaddr;/**/try/**/{/*149*/addr=InetAddress.getByName(address);/**/}catch(UnknownHostExceptione){/*151*/LOG.log(Level.SEVERE,"UnabletoconvertaddressintoInetAddress:"+address,e);/*152*/returnnull;/**/}/**//**//**//**//**//*159*/booleansuccess=false;/*160*/ChimpManagermm=null;/*161*/longstart=System.currentTimeMillis();/**//*163*/while(!success){/*164*/longnow=System.currentTimeMillis();/*165*/longdiff=now-start;/*166*/if(diff>30000L){/*167*/LOG.severe("Timeoutwhiletryingtocreatechimpmananger");/*168*/returnnull;/**/}/**/try/**/{/*172*/Thread.sleep(1000L);/**/}catch(InterruptedExceptione){/*174*/LOG.log(Level.SEVERE,"Unabletosleep",e);/**/}/**/SocketmonkeySocket;/**/try/**/{/*179*/monkeySocket=newSocket(addr,port);/**/}catch(IOExceptione){/*181*/LOG.log(Level.FINE,"Unabletoconnectsocket",e);/*182*/success=false;}/*183*/continue;/**//**/try/**/{/*187*/mm=newChimpManager(monkeySocket);/**/}catch(IOExceptione){/*189*/LOG.log(Level.SEVERE,"Unabletoopenwriterandreadertosocket");}/*190*/continue;/**//**/try/**/{/*194*/mm.wake();/**/}catch(IOExceptione){/*196*/LOG.log(Level.FINE,"Unabletowakeupdevice",e);/*197*/success=false;}/*198*/continue;/**//*200*/success=true;/**/}/**//*203*/returnmm;/**/}通過上一篇文章《誰動(dòng)了我的截圖?--MonkeyrunnertakeSnapshot方法源碼跟蹤分析》的分析,我們知道MonkeyRunner分發(fā)不同的設(shè)備控制信息是在ChimpChat庫的AdbChimpDevice這個(gè)類里面進(jìn)行的。所以這里我就不會(huì)從頭開始分析我們是怎么進(jìn)入到這個(gè)類里面的了,大家不清楚的請(qǐng)先查看上一篇投石問路的文章再返回來看本文。這里我們嘗試以getSystemProperty這個(gè)稍微復(fù)雜點(diǎn)的方法為例子分析下MonkeyRunner是真么通過adbshell發(fā)送命令的,我們首先定位到AdbChimpDevice的該方法:/**/publicStringgetSystemProperty(Stringkey)/**/{/*224*/returnthis.device.getProperty(key);/**/}這里的device成員函數(shù)指的就是ddmlib庫里面的Device這個(gè)類(請(qǐng)查看上一篇文章),那么我們進(jìn)去該類看下getProperty這個(gè)方法:/**/publicStringgetProperty(Stringname)/**/{/*379*/return(String)this.mProperties.get(name);/**/}/*65*/privatefinalMap<String,String>mProperties=newHashMap();/**/voidaddProperty(Stringlabel,Stringvalue){/*779*/this.mProperties.put(label,value);/**/}/**/publicvoidprocessNewLines(String[]lines)/**/{/*49*/for(Stringline:lines){/*50*/if((!line.isEmpty())&&(!line.startsWith("#")))/**/{/**//**//*54*/Matcherm=GETPROP_PATTERN.matcher(line);/*55*/if(m.matches()){/*56*/Stringlabel=m.group(1);/*57*/Stringvalue=m.group(2);/**//*59*/if(!label.isEmpty()){/*60*/this.mDevice.addProperty(label,value);/**/}/**/}/**/}/**/}/**/}繼續(xù)之前我們先要了解下ddmlib這個(gè)庫里面的DeviceMonitor這個(gè)類,這個(gè)類會(huì)啟動(dòng)一個(gè)線程來監(jiān)控所有連接到主機(jī)的設(shè)備的狀態(tài)。/**/booleanstart()/**/{/*715*/if((this.mAdbOsLocation!=null)&&(sAdbServerPort!=0)&&((!this.mVersionCheck)||(!startAdb()))){/*716*/returnfalse;/**/}/**//*719*/this.mStarted=true;/**//**//*722*/this.mDeviceMonitor=newDeviceMonitor(this);/*723*/this.mDeviceMonitor.start();/**//*725*/returntrue;/**/}/**/booleanstart()/**/{/*715*/if((this.mAdbOsLocation!=null)&&(sAdbServerPort!=0)&&((!this.mVersionCheck)||(!startAdb()))){/*716*/returnfalse;/**/}/**//*719*/this.mStarted=true;/**//**//*722*/this.mDeviceMonitor=newDeviceMonitor(this);/*723*/this.mDeviceMonitor.start();/**//*725*/returntrue;/**/}privatevoiddeviceMonitorLoop()/**/{/**/do/**/{/**/try/**/{/*161*/if(this.mMainAdbConnection==null){/*162*/Log.d("DeviceMonitor","Openingadbconnection");/*163*/this.mMainAdbConnection=openAdbConnection();/*164*/if(this.mMainAdbConnection==null){/*165*/this.mConnectionAttempt+=1;/*166*/Log.e("DeviceMonitor","Connectionattempts:"+this.mConnectionAttempt);/*167*/if(this.mConnectionAttempt>10){/*168*/if(!this.mServer.startAdb()){/*169*/this.mRestartAttemptCount+=1;/*170*/Log.e("DeviceMonitor","adbrestartattempts:"+this.mRestartAttemptCount);/**/}/**/else{/*173*/this.mRestartAttemptCount=0;/**/}/**/}/*176*/waitABit();/**/}else{/*178*/Log.d("DeviceMonitor","Connectedtoadbfordevicemonitoring");/*179*/this.mConnectionAttempt=0;/**/}/**/}/**//*183*/if((this.mMainAdbConnection!=null)&&(!this.mMonitoring)){/*184*/this.mMonitoring=sendDeviceListMonitoringRequest();/**/}/**//*187*/if(this.mMonitoring)/**/{/*189*/intlength=readLength(this.mMainAdbConnection,this.mLengthBuffer);/**//*191*/if(length>=0)/**/{/*193*/processIncomingDeviceData(length);/**//**//*196*/this.mInitialDeviceListDone=true;/**/}/**/}/**/}/**/catch(AsynchronousCloseExceptionace){}catch(TimeoutExceptionioe)/**/{/*202*/handleExpectionInMonitorLoop(ioe);/**/}catch(IOExceptionioe){/*204*/handleExpectionInMonitorLoop(ioe);/**/}/*206*/}while(!this.mQuit);/**/}/**/privatevoidprocessIncomingDeviceData(intlength)throwsIOException/**/{/*298*/ArrayList<Device>list=newArrayList();/**//*300*/if(length>0){/*301*/byte[]buffer=newbyte[length];/*302*/Stringresult=read(this.mMainAdbConnection,buffer);/**//*304*/String[]devices=result.split("\n");/**//*306*/for(Stringd:devices){/*307*/String[]param=d.split("\t");/*308*/if(param.length==2)/**/{/*310*/Devicedevice=newDevice(this,param[0],IDevice.DeviceState.getState(param[1]));/**//**//**//*314*/list.add(device);/**/}/**/}/**/}/**//**//*320*/updateDevices(list);/**/}privatevoidupdateDevices(ArrayList<Device>newList)/**/{/*329*/synchronized()/**/{/**//**//*333*/ArrayList<Device>devicesToQuery=newArrayList();/*334*/synchronized(this.mDevices)/**/{/**//**//**//**//**//**//**//**//*344*/for(intd=0;d<this.mDevices.size();){/*345*/Devicedevice=(Device)this.mDevices.get(d);/**//**//*348*/intcount=newList.size();/*349*/booleanfoundMatch=false;/*350*/for(intdd=0;dd<count;dd++){/*351*/DevicenewDevice=(Device)newList.get(dd);/**//*353*/if(newDevice.getSerialNumber().equals(device.getSerialNumber())){/*354*/foundMatch=true;/**//**//*357*/if(device.getState()!=newDevice.getState()){/*358*/device.setState(newDevice.getState());/*359*/device.update(1);/**//**//**//*363*/if(device.isOnline()){/*364*/if((AndroidDebugBridge.getClientSupport())&&/*365*/(!startMonitoringDevice(device))){/*366*/Log.e("DeviceMonitor","Failedtostartmonitoring"+device.getSerialNumber());/**/}/**//**//**//**//*372*/if(device.getPropertyCount()==0){/*373*/devicesToQuery.add(device);/**/}/**/}/**/}/**//**//*379*/newList.remove(dd);/*380*/break;/**/}/**/}/**//*384*/if(!foundMatch)/**/{/**//*387*/removeDevice(device);/*388*/this.mServer.deviceDisconnected(device);/**/}/**/else{/*391*/d++;/**/}/**/}/**//**//**//*397*/for(DevicenewDevice:newList)/**/{/*399*/this.mDevices.add(newDevice);/*400*/this.mServer.deviceConnected(newDevice);/**//**//*403*/if((AndroidDebugBridge.getClientSupport())&&/*404*/(newDevice.isOnline())){/*405*/startMonitoringDevice(newDevice);/**/}/**//**//**//*410*/if(newDevice.isOnline()){/*411*/devicesToQuery.add(newDevice);/**/}/**/}/**/}/**//**//*417*/for(Deviced:devicesToQuery){/*418*/queryNewDeviceForInfo(d);/**/}/**/}/*421*/newList.clear();/**/}/**/privatevoidqueryNewDeviceForInfo(Devicedevice)/**/{/**/try/**/{/*446*/device.executeShellCommand("getprop",newGetPropReceiver(device));/**//**//*449*/queryNewDeviceForMountingPoint(device,"EXTERNAL_STORAGE");/*450*/queryNewDeviceForMountingPoint(device,"ANDROID_DATA");/*451*/queryNewDeviceForMountingPoint(device,"ANDROID_ROOT");/**//**//*454*/if(device.isEmulator()){/*455*/EmulatorConsoleconsole=EmulatorConsole.getConsole(device);/*456*/if(console!=null){/*457*/device.setAvdName(console.getAvdName());/*458*/console.close();/**/}/**/}/**/}catch(TimeoutExceptione){/*462*/Log.w("DeviceMonitor",String.format("Connectiontimeoutgettinginfofordevice%s",newObject[]{device.getSerialNumber()}));/**//**/}/**/catch(AdbCommandRejectedExceptione)/**/{/*467*/Log.w("DeviceMonitor",String.format("Adbrejectedcommandtogetdevice%1$sinfo:%2$s",newObject[]{device.getSerialNumber(),e.getMessage()}));/**//**/}/**/catch(ShellCommandUnresponsiveExceptione)/**/{/*472*/Log.w("DeviceMonitor",String.format("Adbshellcommandtooktoolongreturninginfofordevice%s",newObject[]{device.getSerialNumber()}));/**//**/}/**/catch(IOExceptione)/**/{/*477*/Log.w("DeviceMonitor",String.format("IOErrorgettinginfofordevice%s",newObject[]{device.getSerialNumber()}));/**/}/**/}但這里遺留了兩個(gè)問題各位看官不用著急,且看我們往下分析,很快就會(huì)水落石出了。我們繼續(xù)跟蹤executeShellCommand這個(gè)方法,在我們的例子中其以命令'getprop'和new的GetPropertyReceiver對(duì)象實(shí)例為參數(shù),最終會(huì)調(diào)用到Device這個(gè)類里面的executeShellCommand這個(gè)方法。注意這個(gè)GetPropertyReceiver很重要,我們往后會(huì)看到。/**/publicvoidexecuteShellCommand(Stringcommand,IShellOutputReceiverreceiver,intmaxTimeToOutputResponse)/**/throwsTimeoutException,AdbCommandRejectedExcep
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 老年糖尿病患者的個(gè)體化溝通方案
- 油制氫裝置操作工風(fēng)險(xiǎn)識(shí)別評(píng)優(yōu)考核試卷含答案
- 變壓器試驗(yàn)工操作評(píng)估測(cè)試考核試卷含答案
- 高壓試驗(yàn)工崗前決策判斷考核試卷含答案
- 膠印版材生產(chǎn)工崗前技術(shù)改進(jìn)考核試卷含答案
- 脂肪醇胺化操作工發(fā)展趨勢(shì)競(jìng)賽考核試卷含答案
- 棉花加工工崗前核心管理考核試卷含答案
- 玩具設(shè)計(jì)師崗前安全綜合考核試卷含答案
- 石作文物修復(fù)師創(chuàng)新思維能力考核試卷含答案
- 老年神經(jīng)外科手術(shù)麻醉風(fēng)險(xiǎn)評(píng)估工具
- 2025年大學(xué)旅游管理(旅游服務(wù)質(zhì)量管理)試題及答案
- 打捆機(jī)培訓(xùn)課件
- 清真生產(chǎn)過程管控制度
- 2026年淺二度燒傷處理
- 北京通州產(chǎn)業(yè)服務(wù)有限公司招聘考試備考題庫及答案解析
- 河北省NT名校聯(lián)合體2025-2026學(xué)年高三上學(xué)期1月月考英語(含答案)
- 2025-2026學(xué)年滬科版八年級(jí)數(shù)學(xué)上冊(cè)期末測(cè)試卷(含答案)
- 途虎養(yǎng)車安全培訓(xùn)課件
- 衛(wèi)生管理研究論文
- 2025-2026學(xué)年人教版(新教材)小學(xué)數(shù)學(xué)二年級(jí)下冊(cè)(全冊(cè))教學(xué)設(shè)計(jì)(附教材目錄P161)
- 委托市場(chǎng)調(diào)研合同范本
評(píng)論
0/150
提交評(píng)論