手把手教你_android自己主動化實踐方案選型

來源:互聯網
上載者:User

標籤:des   android   io   os   ar   使用   java   for   sp   


 

 

接到一個android自己主動化的任務,看了看手中的傢伙:ranorex,appium,uiautomator

當然先撿商用的試試,簡單呀,能夠錄製回放,只是不是抱特別大的期望,這個爺比較嬌氣,要是androidproject中有第三方庫可能就會instrument失敗。這次運氣不錯,instrument成功了,錄製了一下經常使用的操作,一切OK。想想還要準備一些啥:

 

先說手勢:搜搜協助:

public void Swipe(

         Location startLocation,

         GestureDirection direction,

         int distance,

         Duration swipeDuration,

         int steps

)

 


好吧,照抄寫一個函數出來,留著備用:

public void myUp2Down(string argument1)

{

       int iparam1=Convert.ToInt32(argument1);

       for (int i=1;i<=iparam1;i++){

     

      Report.Log(ReportLevel.Info, "Touch Gestures", "Swipe gesture with direction ‘Up (270°)‘ starting from ‘Center‘ with distance ‘100‘ with swipe duration‘500ms‘ and step count ‘0‘ on item ‘ComWumiiAndroidMimi.ListView‘.", repo.xxx.ListViewInfo, new RecordItemIndex(1));

      repo.xxx.ListView.Swipe(Location.Center, 270, 100, 500, 4);

      Delay.Milliseconds(500);

       }

}

 

這個凝視已經說的非常清楚了,就是從下往上滑動,270度是向上,180度是左面,0度是右面,90度是以下。100是距離,500是期間,4是步驟

 

 

 

拷屏:

pc:

Report.Screenshot();

 

android手機:

Report.Screenshot(ReportLevel.Info, "User", "", repo.xx.Self, false);   

Report.Screenshot(ReportLevel.Info, "User", "", repo.xx.MyHomeActivity, false);

 

都是資料倉儲中的對象,非常easy吧

 

 

再往下做的時候,發現一個問題,ranorex不能跨應用,而這個被測程式要分享給什麼,新浪微博一類的。得,換刀。

 

用啥呢,appium是最全面的,就他吧。開始的時候總是非常愉快的:

拷屏:

public static void takeScreenShot(WebDriver driver,String s1)

         { 

            File screenShotFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); 

            try {  

               FileUtils.copyFile(screenShotFile, new File(s1)); 

               }

            catch (IOException e) {e.printStackTrace();} 

         }

         public static String getCurrentDateTime(){

            SimpleDateFormat df = new SimpleDateFormat("HHmmss");//yyyyMMddHHmmss

            return df.format(new Date());

         }

調用方法:

private WebDriver driver;

takeScreenShot(driver,"/sdcard/"+getCurrentDateTime()+"main.png");

 

暴力等待:

         public void mysleep(int i1){

                   try {

                            Thread.sleep(i1);

                   } catch (InterruptedException e) {

                            // TODO Auto-generated catch block

                            e.printStackTrace();

                   }

         }

調用:等待5s:mysleep(5000);

 

想想,要是能夠用控制項id引用,不是來的直接可靠得多。好像真機上hierarchyviewer.bat(D:\Android\android-sdk\tools)抓不到布局,用模擬器試試,提醒如今是monitor.bat時代了,直接使用管理員權限開啟monitor.bat(右鍵該檔案,選擇管理員權限啟動)。啟動模擬器,等了半天,總算得到了布局檔案,是不是一大堆東西,沒事,僅僅須要點擊到幾個主幹節點上,就能夠看到這幾個節點所相應的元素圖片,非常easy找到吧,還能夠用來調優喲,留心看看有個三個圓圈的button,會顯示每一個view的載入時間。

 

然後非常悲劇的,花了非常長時間才試出來怎樣引用id:

//WebElement el = driver.findElement(By.id("btnImsi"));   //error

//WebElement el = driver.findElement(By.id("@+id/btnImsi"));   //error

//WebElement el = driver.findElement(By.id("id/btnImsi"));   //error

//WebElement el = driver.findElement(By.id("1"));   //error

//WebElement el = driver.findElement(By.id("漢字一"));   //error

WebElement el = driver.findElement(By.id("com.example.aimsi:id/btnImsi"));  //ok

el.click();

 

本來也算不錯了,老是不停的切換真機和模擬器,hierarchyviewer這個破東西又慢的要死,中間又要啟動appium.exe,並且要引用對象又要tagname,還得list裡面去找時第幾個,真是非常煩人,等待的策略也沒搜到讓人爽一點的。並且那個sendkey在這台機器上每次都是抽風狀態的,發個123,他能輸出個321,肚臍眼都能被氣歪。

 

 

得,再次換刀,uiautomator但是google的親生兒子,一開頭就弄了一個下馬威:

拷屏:死活不行,最終明確了,就倆字:版本號碼!

         //for >=android4.2

    public void TakeScreenShotsGE42(String s1) {

        File storePath = new File(s1);

        getUiDevice().takeScreenshot(storePath);

    }

 

    private void runShellCommand(String command) throws IOException, InterruptedException {

        Process p = null;

        BufferedReader resultReader = null;

        try {

            p = Runtime.getRuntime().exec(command);

            int status = p.waitFor();

            if (status != 0) {

                throw new RuntimeException(String.format("Run shell command: %s, status: %s",

                        command, status));

            }

        } finally {

            if (resultReader != null) {

                resultReader.close();

            }

            if (p != null) {

                p.destroy();

            }

        }

    }

 

         //for <android4.2

    public void TakeScreenShotsL42(String s1) {

//      adb shell screencap -p /data/local/tmp/screen-capture.png

//      adb pull /data/local/tmp/screen-capture.png <localfile.png>

//      adb shell rm /data/local/tmp/screen-capture.png

            

    try {

                            runShellCommand("screencap -p "+s1);

                   } catch (IOException e) {

                            // TODO Auto-generated catch block

                            e.printStackTrace();

                   } catch (InterruptedException e) {

                            // TODO Auto-generated catch block

                            e.printStackTrace();

                   }

    }

看到了吧,啥叫作孽,低版本號碼的就得去調用底層的命令列,高版本號碼的就倆句

調用方法就都差點兒相同:

 

import java.util.Date;

import java.text.SimpleDateFormat;

public String getNowPng(){

         SimpleDateFormat df = new SimpleDateFormat("MMddHHmmss");  //yyyy-MM-dd HH:mm:ss

         return "/sdcard/"+df.format(new Date())+".png";

}

 

TakeScreenShotsL42(getNowPng());

TakeScreenShotsGE42(getNowPng());

 

總算搞定了,看著有人說能夠繞過那個破東西hierarchyviewer,能夠在執行過程中儲存即時版面配置,心下大爽,看,多簡單呀,就這麼兩句:

public void dump(String s1) {

    UiDevice uiDevice = getUiDevice();

    uiDevice.dumpWindowHierarchy(s1);

}

調用也簡單:dump(“d1.xml”);

會寫入: /data/local/tmp檔案夾,回頭adb pull /data/local/tmp/d1.xml 拖下來就是了

 

理想黑豐滿,現實超骨幹,運行沒報錯,可是就是沒產生,再次從真機(4.1.1)切換為模擬器(4.4.2),果然模擬器上運行正常,八成又是版本號碼問題。你妹的

 

再次嘗試id引用:

UiObject ac1=new UiObject(new UiSelector().resourceId("com.xx.android.xxx:id/menu"));

哇,多爽呀,能夠精確定位啦!大不了麻煩一點,先在模擬器中取得各個介面的布局檔案,然後想操作那個對象都能夠直接引用了,超級爽呀!

別整天做夢娶媳婦想得美了。這個也是高版本號碼才行!真是讓人抓狂!

 

 

好了,迄今為止,uiautomator基本上是夠用了,整理思路,能夠這樣,每次開始前刪除指定檔案夾的檔案,回頭每次動作都儲存圖片進去。對象的引用方法也別想id了,又不支援中文,contentDescription更沒指望,直接classname加index來吧,沒啥搞不定的。對象等待也簡單統一寫法。好,一樣樣的來說吧:

先刪除sd卡中的一個檔案夾:

public void deletefile(String s1)

{

         File file =new File(s1);

         File files[] = file.listFiles();

         if (files != null) {

                   for (int i = 0; i < files.length; i++) { // 遍曆檔案夾下全部的檔案

                            files[i].delete();

                   }

         }

}

 

調用方法:deletefile("/sdcard/xxx/");

 

對象引用方法,直接ddms(留心看有個小表徵圖:Dump View for hierarchyviewer UI Automator),你不會連ddms怎麼開啟都不會吧?(window-openperspective,假設有ddms就直接開啟,沒有就選擇other…,這下總該看到了吧):

UiObject ac02_1 = new UiObject(new UiSelector().className(android.widget.LinearLayout.class.getName()).index(0));

UiObject ac02_2 = ac02_1.getChild(new UiSelector().className(android.widget.FrameLayout.class.getName()).index(0));

UiObject ac02_3 = ac02_2.getChild(new UiSelector().className(android.widget.ImageView.class.getName()).index(0));

 

你可能奇怪,為啥引用這麼多層,原因是這種,當前頁面中,有非常多ImageView,並且index都是0,你要是直接那麼引用,就會有反覆的ImageView,無法定位到唯一的對象,即便你加上了上一層的FrameLayout,index=0,也未必就是唯一的。這種引用方法非常是麻煩。可是唯一可靠,邏輯統一。

 

缺點嗎,寫出來的代碼,我自己都看不出來是引用的啥對象。

 

就在已經差點兒相同結束的時候,又冒出來一個小插曲,共用給qqclient,沒想到開啟了一個老版本號碼的,竟然是webview,tnnd,uiautomator對付不了webview,無法引用到webview內部的對象,就算絕對位置後,點擊了控制項也沒法輸入username和password。事實上這樣說是不公道的,UIAutomator是能夠對付webview,只是,預計看官已經猜到了,又是你妹的高版本號碼就能夠!咆哮!

我總不能又繞回來使用appium,江湖傳言,Appium在4.1以上使用uiautomator, 4.1下面使用selendroid,而selendroid擅長這個東東。我去。

 

得,終於敲定方案:

大部分簡易功能都用ranorex,簡單有用才是王道;

共用部分使用uiautomator,親生的比appium還是更簡單一些。

Webview怎麼搞?裝一個client即可了,沒興趣花時間去為了這麼點功能啃骨頭。

 

 

 同學們看著玩吧。

 

 

 

 

手把手教你_android自己主動化實踐方案選型

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.