官方網站:官方網站地址
官網文檔提取鏡像網址:官方文檔提取鏡像
寫在前面
該筆記是為了防止以后遺忘掉,所以記錄下基礎的知識方便以后可以快速上手。
快速上手牢記三個方法:
1:翻看以前的autojs寫過的腳本的源碼,都是自己寫的,很快就能想起來。
2:查找官方函數文檔的相關函數說明,很快就能找到一些解釋。
3:牢記最基礎也是最核心的操作也就是如何確定要操作的控件(唯一性),總結有以下三個方法基本可滿足日常:
①depth-desc-id-classname等控件的常規的唯一屬性.
②findone.parent().child(xx)等控件的父子依存順序關系.
③最后實在無法確定可用坐標法bounds,click(x,y)操作控件
一、基礎知識和使用方法
1.1 基本常識
Auto.JS作為一款基於JavaScript語言的一款腳本,基本語法和結構可通過學習JavaScript來了解。要知道,安卓的app界面就是由一堆控件組成的,這些父子控件相互嵌套,組成了我們熟悉的app界面,因此,你要執行自動化操作,那么最常用的就是先精確的找到這個控件(唯一性),再來說下一步對其進行操作,而我個人認為Auto.JS之所以方便好用,最大的一點就是查找你想要操作的控件(包括但不限於點擊、設置文本等)時特別方便明了,一眼就能看懂並能迅速定位。
比如,在Auto.JS懸浮窗點擊[探測]按鈕(圖1.1),選擇[布局范圍分析],之后Auto.JS會自動分析當前范圍界面的控件組成,在分析探測完成后(圖1.2),可以點擊[查看控件信息]來查看想要操作的控件的各種屬性,控件最基本也最常見的屬性有:
id(“XXX”),className(“XXX”),depth(xx),text(“XXX”),desc(“XXX”)等




在這里以右上角的【⋮】按鈕為例,我想要點擊它,那么先查看其控件屬性(圖1.3),如其所示,在該控件的諸多屬性里,有此控件的bounds(),id(),className(),depth(),desc()等(圖1.4),這就是該按鈕所有的特性,同樣的,其他控件也同此控件一樣,具有這些屬性,我們要利用Auto.JS執行自動化操作,核心無非就是利用各種方法先找到這個控件,其次再操作這個控件。因此,學習Auto.JS的基礎部分就是學習如何唯一的確定想要操作的控件。
1.2 基於控件屬性確定控件
通過查看這些屬性,我們不難發現有其中一項屬性desc("更多選項"),很可能是不和其他控件相同的,也就是此控件屬性具有唯一性,能唯一的確定此控件,這個屬性就是我們要找的。因此,我們想要對其進行操作只需要:
if(desc("更多選項").exists())
{
sleep(1000);
desc("更多選項").findonce().click();
}
上述代碼執行后,在該界面時,desc("更多選項")首先會被查找(findonce),查找后執行點擊(click),從而【⋮】按鈕也就被點擊了。總結下無非就是我們找到了此按鈕的唯一控件屬性desc("更多選項")從而再對其操作,僅此而已。
另外,加上“.exist()”是為了增加程序魯棒性,萬一控件不存在或者沒找到,則程序不會執行,否則對不存在(或沒找到)的控件操作會拋出異常。基於此,往往要判定控件存在與否后再進行操作,而“.exist()”返回的是一個布爾值,方便后續進行判斷和操作。另外一個常用的操作就是加上“while(!)”死循環等待控件出現,如:
//當"更多選項"不存在等價於此按鈕還沒出現
while(!desc("更多選項").exists())
{
//繼續循環等待,直到按鈕出現
sleep(1000);
}
//執行到這里說明"更多選項"存在了,對該按鈕執行點擊操作
desc("更多選項").findonce().click();
return;
當分析了很多控件后不難發現,控件的文本信息往往是以desc或text屬性來呈現的,比如一個該按鈕名為"更多選項",其控件的desc屬性或text屬性就是其按鈕名字,確定其名字也就確定了此控件,針對此按鈕具體來說,就是其desc屬性是"更多選項"。(此處要說的意思就是要具體問題具體分析,文本信息不是desc就是text,如果是desc屬性就操作desc,是text屬性就操作text)但是,往往就有時候我們只知道包含的部分desc或text,這時候可用這四個函數來確定:
//descContains即desc包含部分信息即可匹配
if(descContains("選項").exists())
{
//需要執行的操作
}
//descStartsWith即desc以此信息開頭即可匹配
if(descStartsWith("更多").exists())
{
//需要執行的操作
}
///////同理,text也有對應的兩個函數,比如一個按鈕text屬性為("我的學習積分")/////
//textContains即text包含部分信息即可匹配
if(textContains("學習積分").exists())
{
//需要執行的操作
}
//textStartsWith即text以此信息開頭即可匹配
if(textStartsWith("我的").exists())
{
//需要執行的操作
}
當然,更多情況是desc和text屬性並不能唯一確定要操作的控件,我們往往用其他屬性(常用的有className、id、depth等)一起疊加使用來盡可能的使之唯一,比如:
//往往是諸多控件屬性一起才可唯一確定待操作的控件
var myObject = className(“XXX”).depth(xx).id(“XXX”).text(“XXX”).findone();
myObject.click();
需要注意的是:在不同的Android系統上,同一版本的app的控件屬性可能會變化。同樣,app版本更新后,控件屬性、布局也可能發生變化,所以,若要對不同版本不同系統具有兼容性,應盡可能選擇不變化的控件屬性。
1.3 基於控件父子關系確定控件
有時候,控件屬性是變化的、隨機的,這時候我們便不能通過控件的本身固有屬性如id,className,depth等來唯一的確定出需要的控件,這時候我們可以通過控件之間的上下級關系(也叫父子關系)來確定出需要操作的控件。
首先需要了解的是控件間的依存關系,還是以之前的app界面為例,我們這次來分析右下角的的“+”號按鈕,和之前一樣利用Auto.JS分析控件布局,我們點擊右下角的“+”號按鈕,點擊[在布局層次中查看],便可以查看當前控件在整個布局層次中的上下級關系(父子關系),如圖1.6所示,不難發現,從上到下,左側五顏六色的豎棍丨就代表着其層級關系,豎棍丨越多也就越處於底層,該“+”號按鈕控件名為“ImageButton”,對應着擁有8根豎棍丨,所以其是在第八級。
另外,和“ImageButton”平級的控件是圖1.6所示的8.2—“ImageView”控件,“ImageButton”的父控件也就是它的上級控件是圖1.6所示的7.3—“android.view.View”控件,所以我們可以建立以下關系:
8.1中“ImageButton”的parent() = 7.3中“android.view.View”
7.3中“android.view.View”的child(0) = 8.1中“ImageButton”
7.3中“android.view.View”的child(1) = 8.2中“ImageView”
7.3中“android.view.View”的parent() = 6中“android.view.View”
6中“android.view.View”的child(0) = 7.1中“LinearLayout”
6中“android.view.View”的child(1) = 7.2中“android.view.View”
6中“android.view.View”的child(2) = 7.3中“android.view.View”
建立了以上隸屬關系,我們就可以通過唯一確定任意其中一個不變的固定控件,便可通過控件間的隸屬關系來確定我們想要的控件,從而規避了我們要找的控件屬性動態變化這一情況。


在這里,我們假定以之前右上角的【⋮】按鈕為固定控件(因為"更多選項"這幾個字基本不會變化),通過【⋮】按鈕來和控件間的父子關系來確定出右下角的“+”號按鈕。
首先分析右上角的【⋮】按鈕的層級關系,如圖1.7所示,【⋮】按鈕位於第10級,它的父級parent是圖1.7所示的9.3—“android.support.v7.widget.LinearLayoutCompat”,9.3的父級是8—“android.view.View”,以此類推,發現我們想要操作的控件也就是“ImageButton”控件(8.1)和右上角的【⋮】按鈕即“ImageView”控件(10)關系是:
“ImageView”控件(10)是從7.1—“LinearLayout”繼承下來的;
“ImageButton”控件(8.1)是從7.3—“android.view.View”繼承下來的;
而7.1和7.3是平級關系,擁有共同的父級6—“android.view.View”

明白了這一點,我們便可通過【⋮】按鈕(10)來確定右下角的“+”號按鈕(8.1),如下所示:
//首先,通過desc屬性確定出【⋮】按鈕(圖1.7所示的10)
//屬性.findone()首先找到一個控件,再在此基礎上加.parent等
var moreButton = desc("更多選項").findone();
//其次,找到【⋮】按鈕和右下角“+”號按鈕共同的父級parent
//在這里是一層層往上找是為了方便理解,實際操作可一步到位
var 9_3Supportv7 = moreButton.parent(); //找到圖1.7所示的9.3控件
var 8viewView = moreButton.parent().parent(); //找到圖1.7所示的8控件
var 7_1LinearLayout = moreButton.parent().parent().parent(); //找到圖1.7所示的7.1控件
var 6viewView = moreButton.parent().parent().parent().parent(); //找到圖1.7所示的6控件
//最后,通過共同的父級parent找到右下角“+”號按鈕
//在這里是一層層往下找是為了方便理解,實際操作可一步到位
var 7_3viewView = 6viewView.child(2); //找到圖1.7所示的7.3控件
var plusButton = 6viewView.child(2).child(0); //找到圖1.7所示的8.1控件(也就是+號按鈕)
//所以,如果一步到位,總結如下:
var plusButton = moreButton.parent().parent().parent().parent().child(2).child(0);
//再對+號按鈕進行點擊
plusButton.click();
此處例子里的的兩個控件【⋮】按鈕(10)和右下角的“+”號按鈕(8.1)之間相差了很多層,因此顯着有些復雜,在實際情況中,我們往往不需要跨越這么多的層級來確定控件,一般情況下不會那么復雜。實際上,父子關系嵌套兩三層往往即可確定出另一控件。最后,在這里需要注意的是,確定控件時要加上“.findone()”,此方法調用后會返回所有符合條件的控件集合。因此,首先要找到一個不容易變化的或容易找的控件“.findone()”后再在此基礎上進行“.parent()”“.child(index)”操作找到另一控件。
1.4 基於坐標來確定控件
如果一個控件本身無法通過click()點擊,那么我們可以利用bounds()函數獲取其坐標,再利用坐標點擊。總體來說,基於坐標來確定要操作的控件比較簡單,核心是確定要操作的控件的坐標即可。Auto.JS里可以直接獲取控件的坐標,每一個控件包含其“.bounds()”屬性,bounds()其實表示的是一個范圍矩陣。此處還是以右下角的“+”號按鈕為例,查看控件屬性信息,包含“.bounds()”屬性如下圖:

從上圖看,bounds()屬性是四個坐標值,其分別為(left, top, right, buttom),各值含義如圖1.9所示:
left:控件左邊緣與屏幕左邊的距離
top:控件上邊緣與屏幕上邊的距離
right:控件右邊緣與屏幕左邊的距離
buttom : 控件下邊緣與屏幕上邊的距離

因此,在獲得控件的坐標bounds()屬性后,就可以對控件執行基於坐標的操作,常見的操作有:
bounds().left:長方形左邊界的x坐標
bounds().right:長方形右邊界的x坐標
bounds().top:長方形上邊界的y坐標
bounds().bottom:長方形下邊界的y坐標
bounds().centerX():長方形中點x坐標
bounds().centerY():長方形中點y坐標
bounds().width():長方形寬度也就是控件寬度
bounds().height():長方形高度也就是控件高度
click(x,y):坐標(x,y)處執行點擊操作 //注意:安卓7以下點擊需要root權限且函數為Tap(x,y)
bounds(left, right, top, bottom).clickable().click():點擊該長方形區域
另外,因為不同設備的分辨率大小是不同的,那么我們click(x,y)在不同分辨率下就會出錯,Auto.JS針對這一問題內置了一個函數"setScreenMetrics(width, height)",具體用法如下:
//設置在特定屏幕分辨率下要點擊的坐標值(x,y)
setScreenMetrics(1080, 1920); //聲明是基於分辨率1080,1920的點擊
click(800, 200); //分辨率1080,1920下點擊(800,200)
longClick(300, 500); //分辨率1080,1920下長點擊(300,500)
當我們使用540,960分辨率的設備(x,y各縮小了一半)后執行上述代碼時,他會自動計算縮放的比例,從而實際點擊的是坐標(400,100)和(150,250)這兩個坐標值。
當然,基於坐標的操作不僅有click()操作,常用的還有swipe()滑動操作,gesture()手勢滑動操作等,具體可查看官方文檔,在這里僅對swipe(),gesture()這兩個函數進行介紹。
swipe(x1,y1,x2,y2,time):(x1,y1)代表起始點坐標,(x2,y2)代表終點坐標,time代表滑動所需要的時間
//注意:安卓7以下的滑動需要root權限,且函數名變為Swipe(x1,y1,x2,y2,time)
gesture(time,[x1,y1],[x2,y2],[x3,y3]...):time同,(x1,y1)是起始點坐標,(x2,y2)是途徑點坐標,最后一個坐標是終點
下面以一個某APP注冊時的滑動驗證為例(為防止被人惡意利用,在此打上碼。再次聲明,此處做僅舉例用,所有代碼僅供學習交流!),如圖2.0所示,當我們輸入手機號點擊注冊時,此時需要將滑塊拖動到指定位置處才可以發送驗證碼從而進行下一步的注冊。在這里,我們將想要拖動的滑塊稱為控件①,想要拖到的目標處稱為控件②。那么,如果想要實現一個自動化拖動首先就要確定的是控件①和控件②的坐標,又因為其坐標每次都是隨機的,所以只需要根據兩個控件的特有屬性唯一確定出控件①和控件②,再每次獲取其坐標即可。
通過對兩個控件的屬性分析,如圖2.1所示,我們不難發現,控件①和控件②的indexInParent()不同,因此可通過此分別唯一的定位出兩個控件,確定控件后,我們再調用swipe()或gesture()函數來執行滑動,從而實現自動滑動的操作。


具體實現代碼如下:
//首先判斷是否進入了"滑動驗證"界面
if(text("滑動驗證").exists())
{
sleep(2000);
//判斷控件1是否存在
if(className("android.widget.Button").depth(8).indexInParent(1).exists())
{
//控件1存在,獲取其坐標bounds()屬性
var Button1 = className("android.widget.Button").depth(8).indexInParent(1).findOne().bounds();
sleep(500);
console.log("Button1的坐標為:"+ Button1);
}
//判斷控件2是否存在
if(className("android.widget.Button").depth(8).indexInParent(3).exists())
{
var Button2 = className("android.widget.Button").depth(8).indexInParent(3).findOne().bounds();
sleep(500);
console.log("Button2的坐標為:"+ Button2);
}
//兩個控件的坐標都獲取到后,執行swipe或gesture操作
sleep(2000);
//swipe(x1,y1,x2,y2,[time])
swipe(Button1.left, Button1.top, Button2.left, Button2.top, [random(500,1200)]);
sleep(2000);
//gesture(time,[x1,y1],[x2,y2])
console.log("Swipe完成!");
gesture(random(500,1200), [Button1.left, Button1.top], [Button2.left, Button2.top]);
console.log("gesture完成!");
//結束
}
二、其他的一些方法和函數
2.1 點擊click的一些說明
click是點擊操作,實際上,使用click函數我們可以對坐標進行點擊,也可以對控件進行點擊,最后也可以對某些特定字符點擊,總結如下:
//一:根據控件屬性唯一確定出控件后,再對控件進行點擊click操作
desc("更多選項").depth(9).findone().click();
text("注冊").click();
//二:根據坐標來實現基於坐標的點擊
setScreenMetrics(1080, 1920); //聲明是基於分辨率1080,1920的點擊
click(800, 200); //分辨率1080,1920下點擊(800,200)
//三:有時候控件可能是個Image或是不可點擊的(clickable=false),這時我們可以對屏幕進行點擊
click("2020-07-15"); //點擊"2020-07-15"
click("2020-07-15",0); //點擊第一個"2020-07-15"
click("str",index); //點擊第index個字符"str"(因為有時str會出現多次,另外注意下標從0開始)
2.2 查找函數find/findone/findonce
之前說過,根據我們設定的一些屬性,我們可以對屏幕上的控件進行搜索和查找,並返回符合條件的控件。因此,想要對返回的控件進行下一步操作的前提是必須要“.findone()”,如前面所述,要想從父子關系查找關聯控件必須先“.findone().parent()”,再比如要想獲取控件的坐標矩陣也必須“.findone().bounds()”。三個搜索函數“.find()” “.findone()” “.findonce()”在使用上是有點差別的,具體如下:
//find()函數會找出所有滿足條件的控件並返回一個控件集合,之后可以對控件集合進行操作
var findAssemble = textContains("2020-07-15").find(); //找到所有包含"2020-07-15"的控件集合findAssemble
//findone()函數會對屏幕上的控件進行搜索,直到屏幕上出現滿足條件的一個控件為止,並返回該控件
//如果找不到控件,當屏幕內容發生變化時會重新尋找,直至找到
//注意:如果findone不加限制時間且屏幕上一直沒有出現所描述的控件,則該函數會阻塞,直到找到為止
var findoneAssem1 = textContains("2020-07-15").findone(); //找到一個包含"2020-07-15"的控件findoneAssem1
var findoneAssem2 = textContains("2020-07-15").findone(500); //在500毫秒內找到一個包含"2020-07-15"的控件findoneAssem,若找不到,終止搜索返回null
//findonce(i)函數會根據當前所確定的篩選條件,對屏幕上的控件進行搜索,並返回第 i + 1 個符合條件的控件
//如果沒有找到符合條件的控件,或者符合條件的控件個數 < i, 則返回null
var findonce1 = textContains("2020-07-15").findonce(0); //搜索第一個包含"2020-07-15"的控件findonce1
var findonce2 = textContains("2020-07-15").findonce(1); //搜索第二個包含"2020-07-15"的控件findonce2
2.3 上下滑動和翻頁
Auto.JS上下滑動可以是對整個屏幕的滑動或對某特定控件的滑動,對整個屏幕滑動如下例2.3.1所示:
例2.3.1:
//滑動函數swipe(x1,y1,x2,y2,time)
var h=device.height; //屏幕高
var w=device.width; //屏幕寬
var x=(w/3)*2; //橫坐標2分之3處
var h1=(h/6)*5; //縱坐標6分之5處
var h2=(h/6); //縱坐標6分之1處
swipe(x, h1, x, h2, 500); //向下翻頁(從縱坐標6分之5處拖到縱坐標6分之1處)
swipe(x, h2, x, h1, 500); //向上翻頁(從縱坐標6分之1處拖到縱坐標6分之5處)
在很多時候,我們經常會見到className名為“.ListView”的控件,實際上其往往是充當裝在很多list的集合,以此控件為例,我們可以實現對此控件的上下滑動,如下例2.3.2所示:
例2.3.2:
//scrollForward()函數會對控件執行向前滑動的操作,並返回是否操作成功
//scrollBackward()函數會對控件執行向后滑動的操作,並返回是否操作成功
var listView = ClassName(“ListView”).id(XXX).findone();
ListView.scrollForward(); //向前滑動
ListView.scrollBackward(); //向后滑動
在此只是以“.ListView”的控件進行舉例,實際使用過程中,只要控件是可上下滑動的,都可以調用函數“scrollForward()”和“scrollBackward()”來實現對控件的滑動操作。
2.4 其他通用函數和全局函數
因為Auto.JS是基於JavaScript的語言,因此基本的語法結構、很多兩者通用的函數等都是可以在JavaScript里面找到,如常見的“.replace()”“.indexof()”“.test()”等這些都在JavaScript網站上有相關的用法說明。可見:JavaScript學習
另外,Auto.JS的一些全局函數如啟動程序函數“launch(“XXX”)”,控制台的函數如“console.show()”、“console.log()”等,再如返回函數“back()”,隨機函數“random(start,end)”等這些都可在官方的提取文檔里找到。可見:Auto.JS官方提取文檔
2.5 一些碎碎念和心得(持續更新)
1. 對於文本設置函數“.setText(index,文本內容)”,如果index沒有,則默認是在當前頁面找所有文本框中填入“文本內容”。
2. 函數“.split("")”可用於分割字符串,比如文本“我愛你中國”會被分成“我”“愛”“你”“中”“國”,可以用在取隨機姓名時百家姓的分割。
3.有些控件的“.clickable()”屬性是為false的,這意味着你進行click()點擊操作會返回false失敗,因此,在對控件操作時要注意查看其“.clickable()”屬性,如果其不可點擊,我們可用一些屏幕點擊或坐標點擊的方法來對其進行點擊。
三、一些自己寫的實例
3.1 Auto.JS取隨機姓名
/**
* @description: 取隨機姓名函數
* @param: null
* @return: randomName隨機姓名
*/
function randomName()
{
var allFirstName="王李張劉陳楊黃吳趙周徐孫馬朱胡林郭何高羅鄭梁謝宋唐許鄧馮韓曹曾彭蕭蔡潘田董袁於余葉蔣杜蘇魏程呂丁沈任姚盧傅鍾姜崔譚廖范汪陸金石戴賈韋夏邱方侯鄒熊孟秦白江閻薛尹段雷黎史龍陶賀顧毛郝龔邵萬錢嚴賴覃洪武莫孔"
var firstNameArray = allFirstName.split("");
var firstNameIndex=random(0,firstNameArray.length-1);
var firstName = firstNameArray[firstNameIndex];
var allSecondNames = "偉剛勇毅俊峰強軍平保東文輝力明永健世廣志義興良海山仁波寧貴福生龍元全國勝學祥才發武新利清飛彬富順信子傑濤昌成康星光天達安岩中茂進林有堅和彪博誠先敬震振壯會思群豪心邦承樂紹功松善厚慶磊民友裕河哲江超浩亮政謙亨奇固之輪翰朗伯宏言若鳴朋斌梁棟維啟克倫翔旭鵬澤晨辰士以建家致樹炎德行時泰盛雄琛鈞冠策騰楠榕風航弘秀娟英華慧巧美娜靜淑惠珠翠雅芝玉萍紅娥玲芬芳燕彩春菊蘭鳳潔梅琳素雲蓮真環雪榮愛妹霞香月鶯媛艷瑞凡佳嘉瓊勤珍貞莉桂娣葉璧璐婭琦晶妍茜秋珊莎錦黛青倩婷姣婉嫻瑾穎露瑤怡嬋雁蓓紈儀荷丹蓉眉君琴蕊薇菁夢嵐苑婕馨瑗琰韻融園藝詠卿聰瀾純毓悅昭冰爽琬茗羽希寧欣飄育瀅馥筠柔竹靄凝曉歡霄楓芸菲寒伊亞宜可姬舒影荔枝思麗子璇淼國棟夫子瑞堂甜敏尚國賢賀祥晨濤昊軒易軒益辰益帆益冉瑾春瑾昆春齊楊文昊東東雄霖浩晨熙涵溶溶冰楓欣欣宜豪欣慧建政美欣淑慧文軒文傑欣源忠林榕潤欣汝慧嘉新建建林亦菲林冰潔佳欣涵涵禹辰淳美澤惠偉洋涵越潤麗翔淑華晶瑩凌晶苒溪雨涵嘉怡佳毅子辰佳琪紫軒瑞辰昕蕊萌明遠欣宜澤遠欣怡佳怡佳惠晨茜晨璐運昊汝鑫淑君晶瀅潤莎榕汕佳鈺佳玉曉慶一鳴語晨添池添昊雨澤雅晗雅涵清妍詩悅嘉樂晨涵天赫玥傲佳昊天昊萌萌若萌"
var secondNameArray = allSecondNames.split("");
var secondName="";
var givenNameLength =random(1,2);
if (givenNameLength==1)
{
var secondNameIndex=random(0,secondNameArray.length-1);
secondName=secondNameArray[secondNameIndex];
}
if (givenNameLength==2)
{
var secondNameIndex1=random(0,secondNameArray.length-1);
var secondNameIndex2=random(0,secondNameArray.length-1);
secondName=secondNameArray[secondNameIndex1] + secondNameArray[secondNameIndex2];
}
randomName = (firstName+secondName).toString();
return randomName;
}
3.2 UI用戶界面設計
/********************************************UI部分***********************************************/
auto.waitFor(); //等待獲取無障礙輔助權限
var form =
{
isText: false,
}
let deviceWidth = device.width;
let deviceHeight = device.height;
let margin = parseInt(deviceWidth * 0.03);
let buttonWidth = parseInt(deviceWidth * 0.40);
ui.layout(
<vertical margin={margin + "px"} gravity="left|top">
<appbar>
<toolbar id="toolbar" title="軟件Title"/>
</appbar>
<Switch id="autoService" text="無障礙服務" checked="{{auto.service != null}}" padding="8 8 8 8" textSize="15sp"/>
<text textSize="16sp" textColor="red" text="使用前請確保無障礙服務和懸浮窗權限已經開啟!" />
<vertical>
<button id="all" h="50" text="開始運行" />
</vertical>
<horizontal>
<button margin={margin + "px"} id="dq" h="40" text="單獨功能1" w={buttonWidth + "px"}/>
<button margin={margin + "px"} id="cq" h="40" text="單獨功能2" w={buttonWidth + "px"}/>
</horizontal>
<horizontal>
<button margin={margin + "px"} id="wq" h="40" text="單獨功能3" w={buttonWidth + "px"}/>
<button margin={margin + "px"} id="sq" h="40" text="單獨功能4" w={buttonWidth + "px"}/>
</horizontal>
<horizontal>
<button margin={margin + "px"} id="update" h="40" text=" 單獨功能5 " w={buttonWidth + "px"} />
<button margin={margin + "px"} id="stop" h="40" text="停止運行" w={buttonWidth + "px"} />
</horizontal>
<horizontal>
<text textSize="16sp" marginLeft="15" textColor="black" text="用戶參數輸入:" />
<input id="acatlog" text="" />
</horizontal>
<vertical>
<text text="用戶參數選擇" textColor="#222222"/>
<horizontal>
<radio id="yes_read" text="是" checked = "true"></radio>
<radio id="no_read" text="否"></radio>
</horizontal>
</vertical>
<text id={"resultLabel"} textColor="red" w="*" />
<button w="250" layout_gravity="center" id="about" text="關於本軟件" />
</vertical>
);
//創建選項菜單(右上角)
ui.emitter.on("create_options_menu", menu=>{
menu.add("啟動懸浮窗");
menu.add("運行日志");
});
//監聽選項菜單點擊
ui.emitter.on("options_item_selected", (e, item)=>
{
switch(item.getTitle())
{
case "啟動懸浮窗":
var intent = new Intent();
intent.setAction("android.settings.action.MANAGE_OVERLAY_PERMISSION");
app.startActivity(intent);
break;
case "運行日志":
app.startActivity('console');
break;
}
e.consumed = true;
});
ui.yes_read.on("check",function(check)
{
if(check)
{
form.isText= true;
textTarget=true;
}
});
ui.no_read.on("check",function(check)
{
if(check)
{
form.isText= false;
textTarget=false;
}
});
ui.acatlog.setText(aCatlog.toString());
ui.autoService.on("check", function(checked)
{
// 用戶勾選無障礙服務的選項時,跳轉到頁面讓用戶去開啟
if(checked && auto.service == null)
{
app.startActivity({action: "android.settings.ACCESSIBILITY_SETTINGS"});
}
if(!checked && auto.service != null)
{
auto.service.disableSelf();
}
});
// 當用戶回到本界面時,resume事件會被觸發
ui.emitter.on("resume", function()
{
// 此時根據無障礙服務的開啟情況,同步開關的狀態
ui.autoService.checked = auto.service != null;
});
var thread = null;
ui.all.click(function ()
{
if (thread != null && thread.isAlive())
{
alert("注意!", "當前程序正在運行,請結束之前進程");
return;
}
toast("開始運行");
thread = threads.start(function ()
{
aCatlog = ui.acatlog.getText();
if(auto.service == null)
{
toastLog("請先開啟無障礙服務!");
return;
}
main(); //主函數開始運行
});
});
ui.cq.click(function ()
{
if (thread != null && thread.isAlive())
{
alert("注意!", "當前程序正在運行,請結束之前進程");
return;
}
thread = threads.start(function ()
{
if(auto.service == null)
{
toastLog("請先開啟無障礙服務!");
return;
}
//此處開始執行函數();
});
});
ui.dq.click(function ()
{
if (thread != null && thread.isAlive())
{
alert("注意!", "當前程序正在運行,請結束之前進程");
return;
}
thread = threads.start(function ()
{
if(auto.service == null)
{
toastLog("請先開啟無障礙服務!");
return;
}
//此處開始執行函數();
});
});
ui.wq.click(function ()
{
if (thread != null && thread.isAlive())
{
alert("注意!", "當前程序正在運行,請結束之前進程");
return;
}
thread = threads.start(function ()
{
if(auto.service == null)
{
toastLog("請先開啟無障礙服務!");
return;
}
//此處開始執行函數();
});
});
ui.sq.click(function ()
{
if (thread != null && thread.isAlive())
{
alert("注意!", "當前程序正在運行,請結束之前進程");
return;
}
thread = threads.start(function ()
{
if(auto.service == null)
{
toastLog("請先開啟無障礙服務!");
return;
}
//此處開始執行函數();
});
});
ui.stop.click(function ()
{
if (thread != null && thread.isAlive())
{
threads.shutDownAll();
toast("已停止運行!")
console.hide();
}
else
{
toast("當前沒有線程在運行!")
}
});
ui.about.click(function ()
{
alert("說明", "本文中所有代碼和舉例均為學習交流之用,不得用於其他用途!");
});