【android免root腳本製作】基於控件的操作——auto.js進階

        在【android免root腳本製作】自動座標操作手機——京東金融程序金果搖錢樹自動收金果 之後,想要做進一步優化,因爲基於座標點擊如何屏幕被移動之類就會點擊錯位,不同手機還需去適配座標,甚是麻煩,所以改個改爲基於控件操作。

        基於控件的操作是一種穩定高效準確,適配效果強的操作功能,不同於按鍵精靈等其他軟件,基於控件的操作可以說是Auto.js獨特的功能。這個功能可以幫我們更高效的做出模擬操作行爲或者獲取當前頁面的信息等。這也是要做一個強大的模擬操作腳本必備的功能,所有安卓機型,安卓版本都適用,而且也無需root權限。

在正式進入腳本教程前,先給萌新們普及點概念:

(1)什麼是控件?        

 控件是指對數據和方法的封裝。控件可以有自己的屬性和方法,其中屬性是控件數據的簡單訪問者,方法則是控件的一些簡單而可見的功能、控件創建過程包括設計、開發、調試工作, 然後是控件的使用。  這樣理解可能有點難,萌新可以理解爲,控件就是頁面上的一個個內容,比如說一個圖片就是一個圖片控件,一個輸入框就是一個輸入框控件等等,常見的控件有:TextView,EditText,Button,CheckBox,RadioButton,ImageView,ImageButton,ProgressBar等。然後這些控件有着一定的屬性,我們可以通過他們的屬性用腳本獲取到他們,也可以通過控件類的函數對他進行一定的操作和獲取信息等,比如直接通過控件對齊進行點擊,設置輸入框控件內的文字,獲取某控件的位置等等。

(2)我們如何獲取到控件信息         

在auto.js軟件中有直接獲取到控件信息的功能,在auto.js軟件主頁面,點擊右上角,打開側拉菜單,大致中間位置的懸浮窗打開。這個auto.js的懸浮窗就含有獲取控件信息的功能。點擊懸浮窗我們可以看到有5個功能,中間藍色的就是用於查看控件信息的功能,點擊之後,會讓你選擇用佈局範圍分析和佈局層次分析。

                                                                 

                                                            

        佈局範圍分析,使用該功能,可以直接看到當前頁面上所有控件的邊框即控件位置,這樣可以清晰的瞭解各種控件的位置以及大小。但是這種方法也有缺點,就是比如有兩個完全相同大小的控件重疊在一起就看不見了,這時候就要用到佈局層次分析。         佈局層次分析,即根據軟件當前頁面的源碼佈局層次進行觀察,這樣可以看到所有控件及其層次等。但是這樣子對於比較複雜的佈局很難進行觀察,畢竟內容較多,距離遠的話難以比較。所以在佈局層次和佈局範圍中進行切換查看是比較好的獲取控件信息的方法。        

點擊選擇的控件即可查看控件信息,比較主要的控件信息有id即控件的id屬性,text控件的文本屬性,bounds控件的邊框位置,desc控件的desc值,有些控件會把text控件放空,並把上面的文本寫入desc值。clickable/longClickable控件是否可以點擊/長按,如果控件的clickable爲false那麼點擊也沒用。checked控件是否選中,depth在第幾層次,indexInParent在父控件中是第幾個,在教程文檔的選擇器那一欄中有更多屬性。這些信息對於以後寫腳本都有很大的幫助。        

生成代碼,這個功能可以直接人性化的智能幫你選出如何對一個控件進行操作的代碼,這個功能很好用,但是一般情況只會選擇最簡潔的代碼,和我們需要實現的功能可能會稍有偏差,需要我們人爲進行修改,但是大部分情況還是可以的。另外比較複雜的佈局暫時可能會有獲取失敗的情況。所以不要太依賴於次功能,只要學會了以下內容,自動生成出來的那些代碼,自己肯定都會寫。

2.如何寫控件操作腳本,控件操作的腳本編程思想是什麼?        

 我們要對一個控件進行操作,首先我們要讓腳本識別的那個函數,在js的基於空間的操作中有三大類:控件選擇器,控件合集,控件。這三個類都有各自的方法,要理解這個可能有點難,這裏需要面向對象編程思想,有興趣的,可以百度瞭解一下。在寫這類腳本語句中,一般要多重調用的,比如:id("a").text("abc").findOne().click();可以看出一句話非常的長,這裏的id(),text(),.findOne(),.click()分別都是上面那三個類中的函數,比如id()這個函數是控件選擇器的函數,他們可以直接作爲腳本開頭(全局函數),他的返回值還是控件選擇器,所以後面接的函數還是控件選擇器的函數,text()這就也是一個控件選擇器的函數,他的返回值還是控件選擇器,所以後面繼續接控件選擇器的函數findOne()然後這個函數的返回值是控件,所以後面接控件的函數click()。  另外上面那句語句解釋一下,就是選擇id屬性爲a的,text屬性爲abc的控件,直到找到一個符合以上條件的控件,對其點擊。        

如果有連這個都無法理解的小白,我們偉大的開發者提供了一種非常簡單易懂的理解方式。其實你們可以直接把自己需要找的控件的屬性用選擇器篩選出來,如果有多個那就用英文的點將其連接即可。        

總結:我們寫控件操作的代碼時,不但·要實現需要實現的功能,還要注意返回值和之後使用的函數,以及如何切換來實現需要的功能。當然,如果你願意去學一下面向對象編程思想當然是更好的啦。

3.控件選擇器      

 控件選擇器即含有對控件進行篩選的功能,比如大部分控件選擇器都是用屬性來篩選控件的,並且他們的返回值都是控件選擇器,在這裏,返回控件選擇器本生是爲了,方便以後進行,鏈式調用,也就是將很多要篩選的屬性直接串聯,最後再用findOne轉換成控件。        

 我們來說幾個常用控件選擇器函數的使用方法。假如有desc屬性爲ab,abcd,abcde,cde,cd 那麼我們用教程中的選擇器desc()也就是匹配desc值爲傳入字符串的控件,比如desc("cd")這樣子的話只會匹配出上面desc值爲cd的一個控件,如果用descContains("cd"),desc屬性包含傳入的字符串的話,那就能匹配出desc值爲abcd,abcde,cde,cd的控件,還有的descStartsWith()和descEndsWith()即爲分別匹配以傳入的字符串開頭或者結尾的·desc值的控件,自己體會肯定能懂吧,除了這四種常用的,還有一個就是descMatches(正則表達式),這個用於傳入正則表達式,進行匹配,之後我會單獨寫一篇文章將正則表達式的匹配,這個在百度上也都有,應該來說是可以通過自己的嘗試自學會的。幾乎屬性數據類型是字符串的控件都有着五個選擇器函數進行選擇,例如:text() , textContains() , textStartsWith() , textEndsWith() , textMatches() , id() , idContains() , idStartsWith() , idEndsWith() , idMatches() ,還有className,package等就不一一舉例了。        

還有一些布爾值的屬性的篩選器,就很簡單了,比如說clickable屬性的選擇器函數clickable(要匹配的找值),同樣可可以作爲全局函數,比如clickable(true)這個函數就可以篩選當前頁面上所有可以點擊的控件,同樣的布爾值屬性的選擇器函數還有checkable()控件是否可以勾選,selected()控件是否已經勾選,longClickable()控件是否可以長按,另外還有enabled()控件是否已經啓用,scrollable()控件是否可以滑動,editable()控件是否可以編輯,等等。這些功能都大同小異,教程和示例都有詳細的使用方法。那我們要寫一個選擇器篩選當前頁面上可以點擊,長按的控件,就爲clickable(true).longClickable(true)。這個應該能理解,那我們繼續看一些稍微複雜咋一些的內容。        

有的時候真的會碰到一些奇葩的軟件,或者像QQ那種故意的,所有屬性要麼沒有,要麼都一樣,這個時候可以用控件的邊框位置來進行篩選,主要有兩個比較常用的函數,bounds()和boundsInside(),我們要傳入的變量就是控件的位置範圍,由四個整數值組成前兩個值爲控件長方形左上角的座標,後兩個值是控件右下角點的座標。簡單舉個例子,我們要篩選左上角座標233,233到右下角座標666,666內部的控件即爲boundsInside(233,233,666,666),這樣在這個框內部的所有·控件會全部篩選出來,與他不同的一個邊框選擇器是直接的bounds()這個函數相對來說不算很常用,因爲他的作用是匹配出邊框是傳入的四個值的控件,必須完全一樣,在很多屬性都一樣的時候,這個功能非常的常用,因爲bounds屬性完全相同的控件就是完全重疊的那些,一般都只有一個,但是這個功能也有個很大的缺點那就是做適配功能很難,在·兩個分辨率不同的手機上大部分控件的bounds是完全不一樣的,只要不是非常外層的普通控件,等比縮放這類方法肯定是不可取的,主要還要觀察控件的出現方式,就算寫出來了,計算機結果完全相同,沒有一點偏差也是幾乎不可能的。所以這個功能一般用於特定分辨率,不需要適配的腳本中。        

還有些沒說的選擇器函數一個是drawingOrder();這個控件用於篩選控件在其父控件中是否是第某個,另外他可以作爲全局函數使用,如果使用drawingOrder(0),篩選出所有在父控件中的第一個控件。當然最外層的佈局也是第0個,並且從篩選觸來的內容角度來說,最外層控件肯定在第一個·,那直接使用findOne()就可以直接獲取到UI外層控件了。        

最後要介紹的是 一個最強的萬能選擇器函數-過濾函數,他傳入的內容是一個返回布爾值的匿名函數,函數的傳入值是當前符合的所有控件。他會把會讓函數返回值爲false的內容全部過濾掉。我們直接用文檔中的一個例子來對齊進行解釋,假如我們要寫的是過濾出text屬性有10個字符的控件,他的代碼是filter(function(w){return w.text().length==10}),我們知道function是新函數的意思,return在函數中即是函數的結束也是函數返回內容的代碼,這個函數中先獲取了控件w,即傳入進來的控件的一個,的·text屬性(即後面要講的控件.text(),獲取控件信息的函數)這個屬性值是字符串,可以用length屬性來獲取到他的長度,然後用關係運算符 == (作用是比較左右兩邊內容是否相同,相同返回true,不同false)把他和我們要過濾出來的10進行比較,即他最後返回的布爾值數據類型。然後他會過濾出那些所有返回值爲true,即符合的控件。        

說了這麼久,控件用於過濾選擇器算是說完了。還有就是通過各種功能讓控件選擇器轉換成控件或者控件合集,注意:現在開始說的函數都不能作爲全局函數放在開頭使用,最主要常見的函數就是findOne()了,他的作用是尋找屏幕上符合前面控件選擇器的函數,直到出現,並返回第一個出現的控件,另外他還可以傳入一個參數—最大查找時間,即位,如果到了時間還沒有找到的話,直接返回undifined,以繼續腳本。和他相似的還有一個函數是findOnce(),不同於之前那個函數,這個函數只會尋找一次,如果當前屏幕上沒有,則直接返回null,他也可以傳入一個參數,用於寫,需要獲取當前屏幕上第幾個符合條件的內容,如果當前屏幕上的個數,不夠獲取的個數,則返回null。這兩個函數是比較簡單的函數,就先不舉例子了。         還有find()函數會把選擇器轉換成合集,他的功能是在當前屏幕上搜索所有符合條件的控件並且都放入控件合集,一起返回,如果當前頁面沒有,那就會直接返回一個空的控件合集。和他有一個相似的函數untilFind()同樣是返回控件合集,但是不同在於,他會循環尋找,至少要找到一個纔會返回合集。也就是說不會返回空合集。      

  還有一些控件選擇器函數,返回的是其他數據類型,例如函數 選擇器.exists(),他返回的就是當前屏幕上是否存在符合條件的控件選擇器。         甚至還有一些函數沒有返回值,只有一些運行效果,比如 選擇器.waitFor(),他會一直等待符合條件的控件出現。

4.控件        

關於控件是什麼上面已經介紹過了,這裏我們一樣來介紹幾個控件的函數,首先是可以獲取到控件信息的函數,最主要有text(),desc(),id(),當熱其他所有屬性也是行的,他們的返回值都是自己屬性對應的類型。相同的還有classname,clickable,packagename等等,所有懸浮窗中有的屬性都可以直接這樣用函數獲取到。另外還有childCount()用來返回這個控件有多少個子控件;drawingOrder()用語返回他他在父控件中的繪製順序, 等比較少用的功能在app內文檔中都有使用說明。         其次我們可以對控件做出操作,就是有操作效果的函數,比如函數click()就可以直接點擊一個控件。注:如果clickable的值爲false,那點擊效果是沒有用的,如果明明是個按鈕控件,clickable值卻是false那,一般,切換到佈局層次可以看到有和他重疊的clickable值爲true的控件。還有longClick()長按,setText()設置輸入框內內容,等等。那我們來舉個例子,我們要把id爲edit的輸入框控件內的文字改爲123456,他的代碼爲id("edit").findOne().setText("123456");  非常簡單,自己理解吧。還有很多類似的例如選中,等函數,文檔裏都有使用方法,大同小異,這裏就不一一介紹了。      

  還有一些可以用來找到與這個控件有關的控件的函數,比如他的父控件和他的子控件,我們知道安卓的控件是由控件多層嵌套出來的,所以控件可以含有他的子控件,也有他的父控件(最外層不算)。我們通過控件函數.parent()可以獲得到這個函數的父控件函數,通過child(第幾個),獲取到他的第幾個子控件,注意序號從零開始。        

還有個函數children()用於返回這個控件的所有子控件,另一個比較常用的函數findByText(str)需要傳入一段文,這個函數返回他所有子控件或者孫控件中text或者desc屬性中包含這段文字的所有控件。這時候細心的朋友肯定就能注意到,前面返回控件類,只有一個,是怎麼返回多個的呢。這裏涉及到一個新的類那就是控件集合。他的底層類似於一個控件數組,可以存放多個控件,也可以用上一章講的中括號下標的方法來獲取到其中第幾個控件,也可以用控件合集裏的get(下標)函數來獲取,還有就是size()獲取合集大小,即爲裏面有多少個控件,和數組的length屬性相同。下面就來詳細講講控件合集吧。

5.控件合集        

 首先它是一個類,繼承上一章數組類,也就是有所有數組裏的功能和屬性。他自然也有自己的新函數,我們獲取到一個控件合集後肯定是要對它做出操作的。上面對控件的操作,比如點擊 長按 選中之類的功能,這裏控件合集也能用,比如點擊一個控件合集,他會自動按順序點擊控件合集裏的每一個控件。內部有一個自動遍歷數組的功能each(遍歷函數) 裏面傳入一個函數,寫對每個控件的操作,這個函數的參數是控件。這樣不需要自己寫循環來遍歷方便了很多。        

附註:其實控件選擇器後面也可以直接根操作函數,功能會是直接對當前界面上所有符合選擇器條件的控件進行該操作。運行時控件選擇器會調用自己的find()函數在頁面上找出符合條件的所有控件的合集,再用控件合集內的遍歷並對每個控件進行操作。要是你確定你想要的控件已經出現在這個界面了,那麼這樣子寫,代碼會簡潔很多咯。        

如何·獲取到一個控件合集。除了上面說的兩種方法,還有可以通過控件選擇器獲得,之前說的選擇器內的函數find()就可以返回調用這個函數的選擇器,也就是前面的所有限定條件,全部符合的所有控件。這個控件合集中也有一個find(控件選擇器)函數,但是和控件選擇器中的不同。他需要傳入一個控件選擇器,然後返回這個控件合集中符合該控件選擇器的所有控件及其子孫控件的合集。比如說我們要返回一個合集中所有控件和他們子孫控件,text屬性是abc,desc屬性是def的控件合集,那隻要再那個合集後面接.find(text("abc").desc("def"))就行啦。還有一個用法差不多的findOne()這個是用來返回合集中所有控件及其子孫控件中第一個符合傳入的選擇器的控件。        

還有兩個相對來說不常用的功能,就是判斷合集是否爲空和判斷合集是否不是空的。函數名爲empty()和nonEmpty()。其實判斷控件合集長度用length屬性或者get()函數也可以做出類似效果。

總結         

至此控件的所有功能已經講完了,要是能學熟練本章的內容,做出模擬人操作(或者更快速)的腳本幾乎是沒問題了。再來彙總一下我們寫控件操作的代碼思路:首先,最基本的就是通過控件選擇器根據控件的獨特特點是篩選出要操作的控件,再用函數轉換成合集或者控件,最後再用控件的函數對其進行操作或者獲取信息,具體方法根據實際情況而定咯。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章