在Android中使用am和input命令在實際使用中的注意事項以及小技巧


 

    在Android使用到am和進行一些操作是非常方便的,比如一個重復自動的操作,具體用來實現一些什么是看個人需求了,接下來說對於am和input的使用。

 

    本文適用於已經大概去了解了am和input的朋友,如果暫時不了解,這里推薦兩篇文章大家可以去看看,我就不說了,說了也多是抄,當然如果您是大牛,請忽略本文,本文主要是一些使用中的經驗,和一些小技巧

am:

http://blog.csdn.net/u010164190/article/details/51384099

input:

http://blog.csdn.net/soslinken/article/details/49587497

 

 

首先是am:

    am命令主要用於讓手機去做一些指定的命令,比如打開指定應用或activity

   而input命令則是模擬用戶的點擊。

先對這兩個東西有個模糊的概念,這兩個命令經常搭配在一起使用,

(暫時可以這樣去理解它們兩個,當然不是很恰當的例子:input是一步一步的去做某個事情,慢慢的去做,和人手去操作手機一樣,一步接一步的,比如撥打10010查話費就是先點撥號然后點10010這5個數字,而am也可以暫時把它當成是input,但它是一個大的input,指哪打哪的那種,一步到位,比如我要打10010,adb shell am start -a android.intent.action.CALL -d tel:10086   這樣一句就可以了,因為am命令能做到的事情“並不是很多”,而input可以實現完全像人手一樣操作,所以這兩個經常搭配使用。當然不完全是因為這個。)

 

接下來詳細的說明這兩個命令:

使用am和input有這樣兩種方式:

一種是在Android的命令行中,打開cmd或android studio中自帶的命令行,cd到sdk的platform-tools文件夾下,在輸入am或input命令之前記得加上adb shell

另一種就是實際應用到你的android代碼中,在代碼中是不需要加入adb shell的,只需要寫命令就可以了。

 

事實上我們使用am和input大多是做一下比較投機的事情,比如一個游戲老是會有重復的點擊事件,那我就可以通過命令去實現,還有時,我有很多機器,我要進行一個同樣的操作,那也可以通過am和input去實現,am和input還可以結合Accessibility去做更多更方便的事情,很多人說這些按鍵精靈一樣的還算是編程嗎,我的看法是這樣的,只要是通過你的代碼帶來了便利,起到了作用的東西,都應該是編程。

 

好了,不說廢話了

我們假設現在有這么一個情況,我有一千台機器,每個機器上我都安裝了一個軟件,我要這一千個機器都需要更改個性簽名,我們就可以用input和am寫小腳本

 

我們捋一捋思路。

首先需要使用am跳轉離個性簽名Activity盡量近的地方

怎么才能知道APP的哪個界面是叫什么呢,有這樣一個方法!

在命令行的platfrom-tools目錄下輸入:

 

adb shell "dumpsys window | grep mCurrentFocus
查看當前app的當前activity

 

 在代碼中獲取當前activity有點繁瑣,實在需要可以私聊我發源碼

 

我們在跳轉到某個activity時需要注意一點重要

有的APP不要一步到位跳轉到指定Activity

比如微信,頻繁的am指定跳轉可能會被封號,因為系統會認為你是機器人在點,而不是人為,如果條件允許,甚至可以是一步一步去input,但是比較麻煩,且要一些時間,因為每次input后是需要線程休眠的,通常是兩秒,因為activity的跳轉加載跟不上程序的運行速度,不進行線程休眠會導致你的腳步啪啪啪一套運行完了,但都是亂點,沒有達到需要的效果

 

但是在我們假定的情況中是沒有這個限制的,因為不是每個軟件都像微信這樣去判定

這時我們要考慮的就是去跳轉到哪一個activity才最方便。

 

又有一點需要注意

不是所有am都可以簡單的運行的,大多時候我們的需求都是需要root權限的,比如要跳轉到安裝的app的某個指定Activity,否則,會提示權限不夠

獲取root的方法如下:

  主要是通過操作Process來進行

Process process = Runtime.getRuntime().exec("su");
在執行am命令時還需要使用到輸出流
完整的am執行方法如下:
public static void exeCmd(String cmd) {
try {
      Process process = Runtime.getRuntime().exec("su");
      OutputStream outputStream = process.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(
outputStream);
dataOutputStream.writeBytes(cmd + "\n");
dataOutputStream.flush();
dataOutputStream.close();
outputStream.close();
} catch (Throwable t) {
t.printStackTrace();
}
}

參數cmd就是我們的am命令
 
        

這時就可以通過adb shell "dumpsys window | grep mCurrentFocus獲取到activity,跳轉到指定activity

但是我們在跳轉時很多時候不只是跳轉這么簡單,我們會往am中傳值提交到指定Activity中(通過Intent),但是要怎么知道指定的activity是接收的什么名字的值呢。

這就需要用到反編譯.


反編譯不會混淆四大組件的名字,因為混淆后會在AndroidManifest找不到,這時我們可以去看反編譯出的代碼進行傳值,這樣就輕易很多,怎么反編譯我也不說了,大家應該都會。

 

到了指定activity通常還不能直接做完需求,需要搭配使用input。input在代碼中怎么使用呢

也是通過我們的exeCmd方法,但是傳值不再是一個單詞的String 而是按鍵行為其實也是使用的String,只是我的意思是,它不只是簡單的全一個String進去,因為我們要有面向對象的思想,如果可以面向對象,就去面,多少也是程序員,input和am不同,常用又有夠多的共性,如果不進行這樣一個封裝,真的很亂,尤其是input一多,那么到底是這樣去實現呢,如下:

會使用到String的Format方法格式化,format和C語言中的print很相似

 

舉個點擊的例子:

  

private static String TAP = "input tap %d %d";
public static String getTap(int x, int y) {
return String.format(TAP, x,y);
}

使用時:exeCmd(getTap(100,100))
長按,滑動...都是這么個事。
am和input結合起來就可以實現我們需要的了。

input如何輸入中文?
public static void execShell(String cmd) {
try {
Process process = Runtime.getRuntime().exec("su");

OutputStream outputStream = process.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(
outputStream);
byte[] t_utf8 = (cmd + "\n").getBytes("UTF-8");
dataOutputStream.write(t_utf8);
dataOutputStream.flush();
dataOutputStream.close();
outputStream.close();
} catch (Throwable t) {
Log.e("test","execCommonShell[ "+cmd+" ] error.",t);
}
}

private static String TEXT_ALL = "am broadcast -a ADB_INPUT_TEXT --es msg \"%s\"";
public static String getTextAll(String content) {
return String.format(TEXT_ALL, content);
}


就是這樣了,沒有講什么復雜的東西原理什么的,很拙劣,是自己使用中學到的經驗,都是一些實際使用中的可能會用的到的,在記錄下來的同時也希望可以幫到大家。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM