日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Auto.JS 开发

發布時間:2024/7/23 javascript 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Auto.JS 开发 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

From:https://blog.csdn.net/a6892255/article/details/107302369

autojs 代碼大全(實戰演練):https://blog.csdn.net/qq_30931547/article/details/106459765

:https://github.com/snailuncle/autojsCommonFunctions/blob/master/autojsCommonFunctions.js8

確定要控件(唯一性),以下三個方法基本可滿足日常:

  • ① depth-desc-id-classname等控件的常規的唯一屬性.
  • ② findone.parent().child(xx)等控件的父子依存順序關系.
  • ③ 最后實在無法確定可用坐標法bounds,click(x,y)操作控件
    ?

autojs 一些問題解決的方案

怎么用其他按鍵強行停止腳本

events.onKeyDown("home", function (event) {//按home停止toast("程序結束")console.hide()threads.shutDownAll()})events.onKeyDown("volume_down", function (event) {//按音量下停止toast("程序結束")console.hide()threads.shutDownAll()})

遇到 ui 堵塞怎么辦

解決方案,將 sleep 重寫為一個暫停的 function

function sleep(ms) {return new Promise(resolve => setTimeout(resolve, ms)); }

如何方便的申請權限

function 權限申請() {if (!floaty.checkPermission()) {toast("請開啟懸浮窗和后臺彈出界面權限");floaty.requestPermission();return}if (auto.service == null) {toast("請開啟腳本的無障礙服務");auto.waitFor();return} } 權限申請();

怎么運行 engines.execScript(“運行腳本名字”, Source);

var url = "http://源碼所在位置"//你要運行的js云端源碼 var res = http.post(url, {}); var Source = res.body.string();//變量自己隨便寫就行 if (Source != "") {engines.execScript("運行腳本名字", Source); } else {toast("似乎出了點問題,請聯系作者解決"); }

無法安裝,報毒.沒有安裝的入口,怎么破

一般打開設置,打開安全與隱私關閉即可。
如果是vivo 去安全中心。把應用加白名單即可。

為什么有時候 launchApp(‘應用名’); 會失效

第一,這是因為你手機存在同名軟件.找不到你想要的app,要使用launch(‘應用包名’)。第二,是因為你沒有給軟件(后臺彈出界面)權限

auto.waitFor();

語句增加是非常必要的這個在你沒有無障礙時候會提示你無障礙模式的開啟。并且開啟之后,會接著繼續運行.

AutoJs創建項目后打包成Apk后Apk無法運行

AutoJs單文件打包成Apk說是風險Apk。這個問題現在已經比較好解決了.就是使用AUTO.JS Pro版本即可,破解版可以打包.

怎么黑屏跑腳本(省電)

原理很簡單,就是去創建一個黑色的懸浮窗,在oled屏幕上,就不會發光,降低功耗.兼容任何腳本

function 息屏() {var h = confirm("是否要進入息屏掛機模式嗎?可按下音量上鍵停止輔助。并不能鎖定屏幕!!!通知欄會正常顯示(oled屏可用)");if (h) {var w = floaty.rawWindow(<frame gravity="center" bg="#000000" />);w.setSize(-1, -1);w.setTouchable(true);//保持腳本運行setInterval(() => { }, 1000);} } 息屏()

按 F5 之后不是運行腳本, 而是出現調試 Node.js

解決方案如下

?然后刪除除了 autojs 運行外的 F5 快捷鍵

如何打開控制臺

幫助 -----> 切換開發者工具 ------>?console

一、基礎知識和使用方法

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()這兩個函數進行介紹。
?

// (x1,y1)代表起始點坐標,(x2,y2)代表終點坐標,time代表滑動所需要的時間 swipe(x1,y1,x2,y2,time)// 注意:安卓7以下的滑動需要root權限,且函數名變為Swipe(x1,y1,x2,y2,time) // time同,(x1,y1)是起始點坐標,(x2,y2)是途徑點坐標,最后一個坐標是終點 gesture(time,[x1,y1],[x2,y2],[x3,y3]...)

下面以一個某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所示:

//滑動函數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所示:

// 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學習:JavaScript 正則表達式 | 菜鳥教程

另外,Auto.JS的一些全局函數如啟動程序函數“launch(“XXX”)”,控制臺的函數如“console.show()”、“console.log()”等,再如返回函數“back()”,隨機函數“random(start,end)”等這些都可在官方的提取文檔里找到。可見:Auto.JS官方提取文檔:【Auto.JS】Autojs官方提取文檔使用說明函數 (1)_小宋小宋-CSDN博客

1. 對于文本設置函數“.setText(index,文本內容)”,如果index沒有,則默認是在當前頁面找所有文本框中填入“文本內容”。

2. 函數“.split("")”可用于分割字符串,比如文本“我愛你中國”會被分成“我”“愛”“你”“中”“國”,可以用在取隨機姓名時百家姓的分割。

3.有些控件的“.clickable()”屬性是為false的,這意味著你進行click()點擊操作會返回false失敗,因此,在對控件操作時要注意查看其“.clickable()”屬性,如果其不可點擊,我們可用一些屏幕點擊或坐標點擊的方法來對其進行點擊。

Auto.js 一些高級用法

判斷打開應用失敗,未安裝

打開應用("微信") function 打開應用(應用名) {if (getPackageName(應用名) != null) {app.launchApp(應用名);toastLog("打開成功")} else {alert("溫馨提示", "請下載安裝" + 應用名);console.log("請下載安裝" + 應用名);console.hide();console.log("關閉控制臺");console.log("停止" + 應用名 + "腳本");exit();} }

在線更新,在線強制更新

function 版本更新() {var 當前版本號 = app.versionName, 新版本號var url = "驗證網址"var res = http.get(url)res = res.body.string()新版本號 = res.substr(0, 5)//截取字符,前面5位作為版本號對比log("當前版本號: " + 當前版本號)log("最新版本號: " + 新版本號)var 更新信息 = res.substr(5)//截取字符,第5位以后的作為公告log(更新信息)if (新版本號 != 當前版本號) {toastLog(更新信息)//自己在這里添加其他功能//returnexit()} else {log("當前是最新版本!!!")} } 版本更新()

判斷本腳本是否重復運行

my_count = 0; ne = engines.myEngine(); my_path = ne.mTags.get("execute_path") + "/" + ne.source; engines.all().forEach(e => {path = e.mTags.get("execute_path") + "/" + e.source;if (path == my_path) my_count++; }); if (my_count > 1) toast("本腳本重復運行");

在坐標位置顯示一個十字架,提示2秒后關閉,方便調試

function showXyTap(x, y) {var xy = floaty.window(<frame gravity="center" w="30" h="30" alpha="0.6"><View w="2" h="30" bg="#ff00e4"></View><View w="30" h="2" bg="#00ff42"></View></frame>);xy.setPosition(Math.abs(x - 15), Math.abs(y - 15));setTimeout(() => {xy.close();}, 2000); }

監控腳本是否卡在某界面不動,發現此情況重啟腳本

function Observer() {function unique(arr) {let newArr = [arr[0]];for (let i = 1; i < arr.length; i++) {let flag = false;for (var j = 0; j < newArr.length; j++) {if (arr[i] == newArr[j]) {flag = true;break;}}if (!flag) {newArr.push(arr[i]);}}return newArr;}currentActis = new Array();for (let c = 0; c < 100; c++) {sleep(500);currentActis[c] = currentActivity();}ac = unique(currentActis);if (ac.length == 1) {return false}return true }// 》》》》》》》》》》》》》》》》》》》 START work_thread = threads.start(function () {Main(); });observer_thread = threads.start(function () {while (true) {sleep(5000);if (!Observer()) {work_thread.interrupt();work_thread = threads.start(function () {console.setPosition(device.width / 2, device.height / 1.5);console.show();console.warn("Main線程在5秒后重啟!");sleep(5000);console.hide();Main();});}} });

兼容安卓7.0以上與6.0以下的點擊,6.0需要root

function clickHelper2(x, y) {showXyTap(x, y);if (IS_GT_SDK23) {click(x, y);} else {try {// 容易出毛病,toomanyevenliserExceptionTap(x, y);runtime.sleep(1000);} catch (e) {try {if (!ra) {ra = new RootAutomator();}// 保險點擊ra.tap(x, y, 1);runtime.sleep(800);// ra.press(x, y, 10, 1);} catch (e) {ErrorHandle("在此設備上需要Root權限才能運行本腳本!", true);}}} }

跳轉 到 添加QQ

app.startActivity({action: "android.intent.action.VIEW",data: "mqqapi://car/show_pslcard?&uin=542999277" })

加群,加qq的彈窗

//測試寫法qq,qq群 聯系(1906507927, 553908361) function 聯系(QQ, QQ群) {var Q群 = QQ群var isFold = false,isRunning = false,isRotate = null;function sjcl() {let d = ["red", "green", "blue", "purple"]let y = random(0, 3)return d[y]}var ys = sjcl();var h = device.height;var w = device.width;dialogs.build({title: "歡迎加入更多項目群",titleColor: ys,content: "作者QQ:" + QQ + "\nautojs交流群:" + Q群,contentColor: ys,cancelable: true,positive: "加入Q群",positiveColor: ys,neutral: "取消",neutralColor: ys,negative: "聯系作者",negativeColor: ys}).on("positive", () => {app.startActivity({action: "android.intent.action.VIEW",data: "mqqapi://card/show_pslcard?card_type=group&uin=" + Q群,packageName: "com.tencent.mobileqq",});toast("加入Q群")}).on("negative", () => {app.startActivity({action: "android.intent.action.VIEW",data: "mqqapi://card/show_pslcard?uin=" + QQ,packageName: "com.tencent.mobileqq",})toast("聯系作者")}).on("neutral", () => {//取消鍵toast("返回")}).show(); }

提醒開啟無障礙服務

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();} });

跳轉到開啟懸浮窗

(在其它應用窗口上顯示,貌似要先設置一下無障礙,才能成功跳這個)

int = app.startActivity({packageName: "com.android.settings",className: "com.android.settings.Settings$AppDrawOverlaySettingsActivity",data: "package:" + auto.service.getPackageName().toString() });

結束 autojs

var nowPid = android.os.Process.myPid(); var am = context.getSystemService(java.lang.Class.forName("android.app.ActivityManager")); var list = am.getRunningAppProcesses(); for (var i = 0; i < list.size(); i++) {var info = list.get(i)if (info.pid != nowPid) {kill(info.pid);} } kill(nowPid); function kill(pid) {android.os.Process.killProcess(pid); }

base64 加密和解密

function FuckYourFamily(str) {return java.lang.String(android.util.Base64.decode(java.lang.String(str).getBytes(), 0)); } //調用方式,直接 FuckYourFamily(str) 即可,其中str為base64加密

適配安卓5到9.如果有root,會用root點擊或者滑動.

function 滑動(x1, y1, x2, y2, time) {if (device.sdkInt < 24) {Swipe(x1, y1, x2, y2, time)} else {swipe(x1, y1, x2, y2, time)} } function 點擊(x, y) {if (device.sdkInt < 24) {Tap(x, y)} else {click(x, y)} } function home() {if (device.sdkInt < 24) {Home()} else {home()} } function back() {if (device.sdkInt < 24) {Back()} else {back()} }

/** * 不能點擊的控件,通過坐標點擊 * @param {*} uiSelector */

function clickUiBounds(ui) {if (ui.exists()) {var a = ui.findOnce();if (a) {var b = a.bounds();if (b) {click(b.centerX(), b.centerY());return true;}}}return false; }

配置讀寫

function 寫配置(文件名, 鍵, 值) {const storage = storages.create(文件名);storage.put(鍵, 值); } function 讀配置(文件名, 鍵, 默認值) {const storage = storages.create(文件名);if (storage.contains(鍵)) {return storage.get(鍵, 默認值);};寫配置(文件名, 鍵, 默認值);return 默認值; }

文本操作

function 到文本(數值) {return 數值 + "" }function 到整數(文本) {return 文本 * 1 }function 隨機數(min, max) {return Math.floor(Math.random() * (max - min + 1)) + min } //log(隨機數(1,5))function 子文本替換(原始文本, 欲被替換的文本, 用作替換的文本) {return 原始文本.replace(eval("/" + 欲被替換的文本 + "/g"), 用作替換的文本) } log(子文本替換("1234567890", "123", "qwe")) function 取文本中間(str, firstStr, secondStr) //字符串,開頭,結尾 {if (firstStr == "") { str = "**" + str; firstStr = "**" }if (secondStr == "") { str = str + "**"; secondStr = "**" }if (str == "" || str == null || str == undefined) {return "";}if (str.indexOf(firstStr) < 0) {return "";}var subFirstStr = str.substring(str.indexOf(firstStr) + firstStr.length, str.length);var subSecondStr = subFirstStr.substring(0, subFirstStr.indexOf(secondStr));return subSecondStr; }

判斷系統是否 ROOT

function isRoot() {var r = shell("ls /system/bin", true).result.toString()if (r.length > 50) {return true} else {return false} }

判斷網絡狀態

function networkInfo() {importClass(android.net.ConnectivityManager);var mConnectivityManager = context.getSystemService(context.CONNECTIVITY_SERVICE);netInfo = mConnectivityManager.getActiveNetworkInfo();if (netInfo != null && netInfo.isAvailable()) {/網絡連接var name = netInfo.getTypeName();if (netInfo.getType() == ConnectivityManager.TYPE_WIFI) {/WiFi網絡return "WIFI"} else if (netInfo.getType() == ConnectivityManager.TYPE_ETHERNET) {/有線網絡return "有線"} else if (netInfo.getType() == ConnectivityManager.TYPE_MOBILE) {/3g網絡return "移動"}else {return "未知"}} else {網絡斷開return "斷開"} }

清理緩存

checkSpace() function clickUi(ui) {if (ui.exists()) {var a = ui.findOnce();if (a) {var b = a.bounds();if (b) {click(b.centerX(), b.centerY());return true;}}}return false; } //清理緩存,如果緩存空間不足 function checkSpace() {if (textStartsWith('存儲空間').exists() && text('取消').exists()) {var o = text('取消').findOnce();if (o) {clickui(o);sleep(1000);}if (device.sdkInt > 24) {var intent = new Intent();intent.setAction("android.settings.INTERNAL_STORAGE_SETTINGS"); //MEMORY_CARD_SETTINGSapp.startActivity(intent);sleep(3000);var o = text('緩存數據').findOnce(); //小米if (o) {clickui(o);sleep(1000);if (text('取消').exists() && text('確定').exists()) {var o = text('確定').findOnce();clickui(o);sleep(10000);}}swipe(100, 200, 100, 500, 500);//z注意,這里需要修改.這里是用于滑動的var o = text('垃圾清理').findOnce(); //小米if (o.length > 0) {// clickObject(o[o.length - 1]);o.click()sleep(3000);var iii = 10;while (iii-- > 0) {if (textStartsWith('清理選中垃圾').exists()) {var o = textStartsWith('清理選中垃圾').findOnce();o.click()sleep(5000);back();break;}elsesleep(5000);}}}else {app.startActivity({action: "android.settings.INTERNAL_STORAGE_SETTINGS",root: true});sleep(8000);var o = text('緩存數據').findOnce(); //小米if (o) {o.click();sleep(1000);if (text('取消').exists() && text('確定').exists()) {var o = text('確定').findOnce();clickui(o);sleep(10000);}}}back();} }

示例:

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; }

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("說明", "本文中所有代碼和舉例均為學習交流之用,不得用于其他用途!"); });

總結

以上是生活随笔為你收集整理的Auto.JS 开发的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。