adb即 Android Debug Bridge 是一個通用的命令行工具,可用於通過PC端對連接的Android模擬器設備或連接至電腦的真實物理設備進行命令行操作。目前,許多軟件均會借助 adb 工具與移動終端進行交互。這里以 Android Studio 中帶有的 adb 工具為例,描述與啟動 adb shell相關的步驟,從而解釋出現上述錯誤的原因。
Android Studio 自帶的 adb 位於C:\Users\user_name\AppData\Local\Android\Sdk\platform-tools文件夾下(即實際位置取決於Sdk的安裝目錄)。
命令行運行adb工具
安裝 Android Studio 后,命令行中輸入 adb 命令(如adb -version,顯示adb的版本號)時,系統會提示找不到該命令。這是由於 adb 工具的位置無法被確定,可通過以下幾種方案在命令行方式下運行 adb :
(1)將 adb 工具所在目錄的路徑加入系統的 Path 環境變量中,則可在命令行的任意路徑下直接運行 adb 命令。在這里,也就是將 C:\Users\user_name\AppData\Local\Android\Sdk\platform-tools 加入 Path 變量中;
(2)切換控制台中的路徑至 adb 工具所在路徑下,如可以通過命令 cd C:\Users\user_name\AppData\Local\Android\Sdk\platform-tools切換至 adb 工具所在的文件夾,即可在當前命令行中直接運行 adb 命令;
(3)在文件管理器中,進入上述 C:\Users\user_name\AppData\Local\Android\Sdk\platform-tools 目錄,在該目錄內,按住 Shift 鍵,右鍵 -> 在此處打開命令窗口 ,在打開的窗口中可以看到控制台提供的路徑名稱與(1)中切換后的效果是一致的;
無法運行 adb shell 命令
在完成上述操作后,運行 adb shell 命令,出現報錯信息:adb server version (26) doesn't match this client (39); killing...
根據查到的資料的一些說法,這一問題是由於系統上存在兩個不一樣版本的 adb 工具造成的。
筆者在上述目錄下(屬於Android Studio的目錄)運行了命令 adb version,結果如下圖:
也就是說當前目錄下,Android Studio自帶的adb工具版本為 1.0.39 ,猜想這就是上述報錯信息中的 client(39),相應的可能系統上還存在一個版本為26的 adb 工具。
問題描述
筆者查閱了Android Studio官網上對 adb 工具的介紹。介紹中對 adb 的描述: 啟動一個adb 客戶端時,此客戶端首先檢查是否有已經運行的 adb 服務器進程。如果沒有,它將啟動服務器進程。當服務器啟動后,它將與本地 TCP 端口 5037 綁定,並偵聽從 adb 客戶端發送的命令。所有的 adb 客戶端均通過端口 5037 與 adb 服務器進行通信。
通過上述描述,可以看到既然報錯信息顯示的是adb server version(26),那當前系統中一定存在一個 adb 服務進程 , 它較之我們運行的那個 adb 工具先開始,且版本要低於我們使用的 adb 版本。可以通過命令行工具查找該進程。
(1)由於 adb 服務進程一定會占據 5037 端口,所以首先查看當前 5037 端口被那個進程調用。命令行方式下可以通過 netstat 命令顯示當前的網絡情況,可通過 netstat /? 查看命令幫助。
netstat -ano | findstr "5037" //在 netstat 輸出的結果中篩選出有 5037 字符串的行,findstr命令類似於Linux下的grep
結果如下圖所示:
(2)獲得上述進程 pid 對應的進程的信息。有兩種方式,通過命令行或者任務管理器。
a)打開 任務管理器 -> 詳細信息 ,通過 pid 即可定位對應的進程,可通過右鍵 -> 屬性,可查看該進程的描述信息,從而獲得另一個 adb 工具相關的信息;
b)通過命令行工具,tasklist | findstr "10044"找到對應的進程;
tasklist | findstr "xxx" //將tasklist輸出結果中帶有目標字符串的行篩選出來
其中,通過任務管理器獲得的信息更詳細,可以定位到對應的 adb 工具的目錄位置。比如 360 的軟件中,會帶有 adb 工具,而這可能會帶來 adb 工具版本的不同。
解決方案
解決的方法包括但不限於將之前啟動的adb服務進程刪除掉(注意要確定對應的應用程序可以關閉該服務),之后再啟動我們想要的 adb 工具。
在終止了之前存在的不同版本的 adb 服務進程之后,再次啟動 Android Studio 對應的 adb 工具時, 該 adb 工具會發現當前沒有 adb 服務端,故而會自行啟動服務器進程,如下圖。由於沒有連接設備,故而不會直接顯示出Shell。
通過命令行工具我們可以看到系統上現在存在了新的 adb 服務器進程,是由我們剛才使用 adb 工具的命令開啟的。
完成上述操作后,即可以將物理設備的USB調試模式打開,並連接至PC,再次使用 adb shell 命令,即可進入 adb 工具提供的Shell。
其他
基於錯誤信息的描述,可能的解決方法還包括將兩個不同版本的 adb 工具更新成一致版本,這樣可以避免每次使用時均要檢查是否已有不同版本的 adb 服務器進程存在。出現有兩個版本的 adb 工具的常見場景是系統可能同時安裝了兩個提供該工具的應用,如 Android Studio 和 Genymotion ,可以參見 stackoverflow 的回答 。
根據 adb 工具運行的原理,若TCP端口 5037 被其他進程占用了,則也會出現報錯,典型的報錯信息是 "cannot bind to 127.0.0.1:5037 :t通常每個套接字地址(協議/網絡地址/端口)只允許使用一次",此時可能需要考慮將占用該端口的進程終止掉(在沒有副作用的情況下)。