『壹』 adb錯誤「'adb' 不是內部或外部命令,也不是可運行的程序或批處理文件。
adb的全稱為android Debug Bridge 調試橋,是連接Android手機與PC端的橋梁,通過adb可以管理、操作模擬器和設備,如安裝軟體、系統升級、運行shell命令等。
現在使用adb命令的時候出現錯誤「'adb' 不是內部或外部命令,也不是可運行的程序或批處理文件。」,如下圖所示:
這個問題一般有兩種可能:
1.就是沒有配置環境變數, 這個只需要將android安裝:例如D:\Program Files\eclipse-jee-juno-win32-x86_64\eclipse\android-sdk\tools加入到系統變數Path中,需要注意的是Path中會配置的有其他的路徑,需要在android的路徑前加;然後將上面的路徑粘貼上去就OK了。
原來是android2.2和android 2.3不一樣了 ,android2.3 adb.exe是放在android-sdk\platform-tools目錄下面的,而2.2是放在tools目錄下面的,所以需要把path的路徑指到platform-tools下面,然後輸入adb,能夠顯示相關的信息。
『貳』 踩坑adb——我的一次使用adb命令的踩坑之旅
昨晚正在測case的時候,突然冒出來一同事(我們都叫他肖總),來了一句:BUG基(同事都叫我BUG基,你懂的),我這復現了一個問題,但是開發那邊說叫我把log導出來,我這不會導,你知道怎麼導嗎?
作為一隻BUG基,我怎麼可能會放過這個裝比的機會呢,哈哈。
叫肖總導log的那個開發啥也沒說,就只在jira系統的comments最後寫了一句「導出方法:adb pull/cache/recovery/ ./」。其實當時我是崩潰的,我擦,肖總,你妹,這開發不是說了導出方法了嗎?你直接復制粘貼打上去命令不就行了嗎?然而,裝比心理作怪,我還是決定了幫他。
那麼下一步是什麼?沒錯,是時候展現裝比的技術了!
拿過Pad的第一步,那當然是先裝驅動啦。沒驅動你怎麼使用adb命令?為什麼這么說呢。驅動一般指的是設備驅動程序(Device Driver),是一種可以使 計算機 和設備通信的特殊程序。相當於 硬體 的介面, 操作系統 只有通過這個介面,才能控制 硬體 設備的工作,假如某設備的驅動程序未能正確安裝,便不能正常工作。那麼ADB又是什麼東東?Android Debug Bridge,我們一般簡稱為adb,它是一個非常強大的命令行工具,通過這個工具你能夠與你的android設備進行交互。意思也就是說,ADB命令需要通過驅動程序提供的介面來控制硬體設備,因為我們的文件是存儲在硬體設備上的呀。
那裝驅動要在什麼狀態下安裝?廢話,肯定是開機狀態啦。當然在安裝驅動前,要先開啟開發者模式的ADB調試,這里我就不說為什麼了,自己想。
那再下一步就是我們要用開發給的adb命令,導出/cache/recovery/這個文件夾的內容。或許有人會問,這開發不是已經給了文件的路勁了嗎,直接在Pad上復制粘貼到SD卡又或者直接用PC從Pad復制粘貼到PC就可以了呀。對於這個,我只想說,廢話,這么簡單的,你會想不到嗎?你以為我是豬啊。然而我並不是豬,我是BUG基。
對於上面那個想法,條件並不成立,當我們連接Pad時,windows是屏蔽部分文件的,反正我這里是這個情況,而用Pad直接復制粘貼到SD卡也是不成立,當我復制的時候,會提示「操作失敗,目標無法復制」,至於為什麼會出現這個提示,請往下看。
既然上面兩個方法都不行,那我們就只有用adb命令了。
在執行操作之前,我們要先看移動設備是否跟PC連接,那麼就需要用adb devices這個命令查看當前連接的設備,這里可能返回的狀態有三種:
I.device設備已經成功連接到了adb-server
II.offline設備並沒有連接到adb或者沒有響應
III.no device並沒有設備/模擬器連接
這里說的三種狀態顯示的可能跟顯示情況不大一樣,譬如我連接是正常的,返回的是
或許有人知道這里的意思是什麼,但是是否有想到過前面的那個daemon是什麼呢?當然有人會說,只要復制粘貼會用就可以了,對於這個回答,我默默表示不回答。
這個daemon還得要從ADB說起,ADB包含了以下三部分的cs模式的程序:
而在解釋上圖的意思之前,我想先引入兩個概念,那就是埠和通信(已理解的可以略過)。
埠
計算機"埠"是英文port的譯義,可以認為是計算機與外界通訊交流的出口。其中硬體領域的埠又稱介面,如:USB埠、串列埠等。軟體領域的埠一般指網路中面向連接服務和無連接服務的通信協議埠,是一種抽象的軟體結構,包括一些數據結構和I/O(基本輸入輸出)緩沖區。
埠最主要的作用就是通信和數據傳輸,把數據報順利的傳送到目的主機是沒有問題的。那麼問題出在哪裡呢?我們知道大多數 操作系統 都支持多程序(進程)同時運行,那麼目的主機應該把接收到的數據報傳送給眾多同時運行的進程中的哪一個呢?顯然這個問題有待解決,埠機制便由此被引入進來。
本地 操作系統 會給那些有需求的進程分配協議埠(protocal port,即我們常說的埠),每個協議埠由一個正整數標識,如:80,139,445,等等。當目的主機接收到數據報後,將根據報文首部的目的埠號,把數據發送到相應埠,而與此埠相對應的那個進程將會領取數據並等待下一組數據的到來。說到這里,埠的概念似乎仍然抽象,那麼繼續跟我來,別走開。
埠其實就是隊, 操作系統 為各個進程分配了不同的隊,數據報按照目的埠被推入相應的隊中,等待被進程取用,在極特殊的情況下,這個隊也是有可能溢出的,不過操作系統允許各進程指定和調整自己的隊的大小。
通信
通信(Communication)就是信息的傳遞,是指由一地向另一地進行信息的傳輸與交換,其目的是傳輸消息。其實這里的通信,意思就是說用特定的邏輯信號,實現雙方的互相信息傳輸,譬如說在命令行輸入adb devices命令,意思就是說我想要對方輸出設備列表給我看,這里的輸入」adb devices」就是發送給對方的信號,而輸出的設備列表就是對方反饋回來的信號,這個整個過程就是通信的過程。
說了這么多,其目的就在於掃盲,下面我們來說上面提到的ADB三部分的cs模式的程序(我把上面的圖拉下來,防止大家看不到):
1) adb client
從圖中,我們知道client是運行在PC端的,每當我們發起一個adb命令的時候,就會開啟一個client程序。當然,當我們開啟DDMS或者ADT的時候,也會自動創建client。
當我們開啟一個client的時候,它首先會去檢測後台是否已經有一個server程序在運行著,否則會開啟一個adb-server進程。
所有的client都是通過5037埠與adb-server進行通信的。
2 ) adb daemon ( adbd )
從圖中,我們知道daemon是作為一個後台進程運行在模擬器/真實Android設備中的。
daemon使用埠的范圍是5554-5585,每個模擬器/設備連接到PC端時,總會開啟這么一個後台進程,並且為其分配了兩個連續的埠,比如:
Emulator 1,console: 5554
Emulator 1, adb:5555
也正因為每個設備都分一組兩個埠,也已adb連接手機的最大數量為16。
說回埠的作用,在這兩個埠中,其中偶數埠是用於server與設備進行交互的,可以讓server直接從設備中讀取數據,而奇數埠是用來與設備的adbd進行連接通信的。
3) adb server
從圖中,我們同樣可以知道,server也是作為一個後台的程序運行在PC端的,他負責管理client進程以及adb daemon之間的通信。
當一個server開啟的時候,他會自動綁定並且監聽5037埠,接收client通過該埠發送過來的命令。同時server還會對5555-5585間的奇數埠進行掃描,進行對已連接設備的定位。
完成了上面一大堆吧啦吧啦的掃盲,大家應該知道了圖1的意思了吧,那麼我們就要解決問題了。
我們來看開發給我們的adb命令
不知大家是否看到使用adb命令都要在前面輸入adb,譬如開發給的「adb pull /cache/recovery/ ./」這個命令就有adb在前面。那麼為什麼要在命令前面加上一個adb呢,原因在於如果我們不加adb,windows系統會默認為對windows執行命令,而不是通過ADB命令行工具對手機執行操作命令。後面的「pull /cache/recovery/ ./」通過前面學習linux命令結構(linux命令結構為command [options] [arguments...])大概可知道pull指的是命令動作,後面那兩個,指的其實就是參數,/cache/recovery/指的是Pad設備的文件路徑,而./指的是當前運行命令行的路勁,譬如下面的提到的C:\Users\301001958這個路徑。
好了,繼續回到我們的裝比之路,剛開始的時候,我不小心把」 adb pull /cache/recovery/ ./ 」打成了「adb pull /cache/recovery/./」,也就是,我沒有把中間的空格打上,結果彈出了這樣的提示,啊,真是瞎了我的眼……
於是,我馬上改過來,修改成了「adb pull /cache/recovery/ ./」,結果還是彈出了一樣的提示。
我擦,這怎麼辦怎麼辦,難道真的要裝比不成,反遭雷劈?別急,我們先來看看這里提示的意思,這里的這個remote的意思是指的遠端設備,在這指的就是Pad,而object '/cache/recovery/' does not exist的意思就是說Pad的/cache/recovery/這個文件夾對象不存在。
這咋回事啊?怎麼會就不存在呢?於是乎,我再進入Recovery mode查看,得到的結果如下:
我擦,這怎麼回事?明明有這個文件夾的存在,於是我再次開機在命令行輸入adb -help,驗證一下這個adb命令的用法,結果吧啦吧啦的出現了一大坨黑色的字,看著都頭暈啊,不過還是讓我找到了想要的信息,如下圖:
看到了這里,我瞬間臉黑了,我靠,這完全就是跟我想的那樣沒錯嘛,怎麼就說文件夾對象不存在呢。
於是我還是找上了大家最喜歡的——度娘。找了一番,找到了一個似乎有用的信息,如下圖:
正如上面所說,難道是因為沒有文件夾沒有讀寫許可權?於是,我又輸入了adb remount,得出結果如下:
額,看到這里,我不想說話了,不過這里,已經算是弄出了點端倪,大家應該也知道了前面直接在Pad的系統裡面復制提示無法復制了吧,最主要就是不夠許可權的原因,因為一旦系統運行文件隨便被更改,系統就有可能出現運行錯誤或者崩潰。只是我竟天真的以為這里的root,指的是我們經常用的那個一鍵root軟體,只要用軟體一鍵root了,就可以快樂的解決問題了,可想而知,得到的結果依然是像是碰到了蜜蜂窩一樣,被蟄著千瘡百孔啊,面目全非……這些什麼鳥一鍵root軟體,根本就無法root得了我們這些開發中的Pad嘛,還試了一大堆都不行,至於為什麼,暫時我沒有深究,大家有空可以去研究研究。
到了這里,我只想說:蓋倫,請給我一把大寶劍……
無奈,問題最終還是得要解決,於是我繼續再找度娘玩去了。
經過了一番查找,我似乎終於找到了答案如何獲得root許可權了,就是僅僅只需要用「adb root」這個命令就可以讓adb獲得root許可權,二話不說,趕緊開干啊,輸入adb root,得出的結果是:adbd restart as root,我擦,藍瘦香菇,明明只需要幾個命令……就可以獲得root許可權,我為什麼能搞得那麼復雜,我不行了,蓋倫,借你的大寶劍扶我起來……
但是似乎有一件很重要的事是,正因為我前面用了一鍵root軟體,我才能在adb命令使用root許可權,前面的功夫也並不是全是無用功,來到這里,我們就只需執行最後一步就是用開發給的命令,把文件拖出來,不過,我把開發給的最後一個參數改了,也就是「./」這個參數,改成了我自己電腦桌面的一個文件夾路徑,如我在桌面起了個叫做FileLog的文件夾,如我FileLog的文件夾路徑為C:\Users\301001958\Desktop\FileLog,那麼我執行的就是adb pull /cache/recovery/ C:\Users\301001958\Desktop\FileLog,然後按Enter執行命令,文件就巴拉拉的復制到了我的FileLog文件夾裡面,到這里問題解決完畢。
回顧整個過程,踩的坑著實不少,一個簡簡單單的命令,一個簡簡單單的操作,都能把自己搞死,不過在這整個過程裡面,也是一個不斷擴展知識的過程,也是一個不斷挑戰自我的過程,到最後的解決,是滿心的舒暢。
這整個過程里,給我最大的感悟是,樂於助人,助的有時候不僅僅是別人,助的也是自己,因為在這個過程中,我的知識獲得了拓展,獲得了成長,也獲得了成就感,獲得了興趣,用此文,希望能助正在踩坑的你,走出這個坑,不管是大坑還是小坑,又或者是神坑,在這個寫作分享的過程中,也讓我對整個知識面理解更全面更深了一步。
文章寫得不是那麼好,太長了點,請輕噴。
致正在踩坑的你我。 2017.02.26 By BUG基
『叄』 運行adb shell出現error錯誤怎麼辦
1、adb kill-server來殺死adb進程,然後再使用adb start-server命令來開啟;
2、檢測5037埠(adb.exe默認埠)是否被佔用,關閉除adb.exe以外佔用了5037埠的進程,重新開啟adb服務:
2.1、adb nodaemon server:檢測5037埠是否被佔用;
2.2、netstat -ano | findstr 「5037」:查看是什麼進程佔用了5037埠;
2.3、tasklist | findstr 「21152」:查看這個進程是由哪個程序創建的(21152就是佔用5037埠的一個進程的PID);
2.4、taskkill /f /pid 21152:將進程關掉;
2.5、adb devices:顯示當前連接設備。
在此提供另外一種解決方案,通過手動查看硬體ID,並安裝google原生android debug驅動;
1、右鍵我的電腦->管理->設備管理->Android Phone.在這里我們可以看到對應android設備的驅動。
2、選中該驅動右鍵屬性,在詳細信息選項下,在屬性(p)選項中選擇硬體Id,記錄下面的值(v)中的信息,例如某設備的這一值為:
USBVID_2A45&PID_0C02&REV_????&MI_01
USBVID_2A45&PID_0C02&MI_01
主要關注2A45和0C02這兩個值。
3、在電腦中找到android開發下載的sdk目錄(假設你已經通過sdk manager下載了),進入extrasgoogleusb_driver文件夾下,找到android_winusb.inf並打開,這就是google針對android的一個配置文件。在文件中找到[Google.NTx86](針對32位平台,64位同理添加)這一行,在下面可以看到很多android設備的驅動信息,例如:
;Google Nexus One%SingleAdbInterface% = USB_Install, USBVID_18D1&PID_0D02%CompositeAdbInterface% = USB_Install, USBVID_18D1&PID_0D02&MI_01123
這里我們只需要仿照這種文件的格式,復制這些驅動信息,並用2中獲取的2A45和0C02來修改,如下:
;MEIZU metal%SingleAdbInterface% = USB_Install, USBVID_2A45&PID_0C02%CompositeAdbInterface% = USB_Install, USBVID_2A45&PID_0C02&MI_01123
保存並關閉。
4、卸載掉原來驅動程序,重啟電腦。確保手機已經進入開發者模式並允許USB調試,連接方式選擇傳輸文件。然後再次右鍵電腦->管理->設備管理->其他設備。可以看到ADB Interface選項上有一個問號,表示該驅動沒有正確安裝。選中ADB Interface並右鍵選擇更新驅動程序軟體->瀏覽計算機以查找驅動程序軟體,在瀏覽中選進我們之前添加了硬體設備驅動信息文件android_winusb.inf的文件夾(D:android-sdksextrasgoogleusb_driver,這里只需要選擇文件夾,不需要選擇文件),下一步後選擇始終安裝。
5、安裝成功後,在設備管理中會出現一個Android Phone的選項。
『肆』 深入扒一扒安卓中的ADB命令
做過安卓開發的朋友或多或少都遇到過讓人厭惡的類似於「could not read ok from ADB Server」的錯誤。產生這個錯誤的原因可能多種多樣,每次遇到問題的時候,可能大部分人都和我一樣,去google一下這個問題別人是如何解決的。假設一下子找到解決了,就放過,下次在遇到的時候同樣的再去google一下就好了。但是,這樣不是正確的治學態度,為此孔祥子決定去扒一扒!
如下,是我在發現Android studio連接不上手機的時候,嘗試去啟動一個adb server,但是失敗了。
<pre>
根據問題提示,5037埠被佔用了。下面就來看看到底是哪一個埠被佔用。
<pre>
C:Userszxy>netstat -ano | findstr "5037"
TCP 127.0.0.1:5037 0.0.0.0:0 LISTENING 7912
TCP 127.0.0.1:5037 127.0.0.1:50025 ESTABLISHED 7912
TCP 127.0.0.1:5037 127.0.0.1:56501 ESTABLISHED 7912
TCP 127.0.0.1:50025 127.0.0.1:5037 ESTABLISHED 7120
TCP 127.0.0.1:56501 127.0.0.1:5037 ESTABLISHED 1264
</pre>
果然,5037被進程id為7912的進程佔用了。順藤摸瓜,看看到底什麼進程搗的鬼,
<pre>
C:Userszxy>tasklist | findstr "7912"
romaster_daemon.exe 7912 Console 1 3,024 K
</pre>
看到了嗎,是這個進程romaster_daemon.exe ,好了,到此為止找出來是哪一個程序了,下面打開任務管理器,kill掉就可以了。
Android adb(Android Debug Bridge) 是一個通用命令行工具,其允許您與模擬器實例或連接的 Android 設備進行通信。它可為各種設備操作提供便利,如安裝和調試應用,並提供對 Unix shell(可用來在模擬器或連接的設備上運行各種命令)的訪問。
該工具作為一個客戶端-伺服器程序,包括三個組件:
客戶端(adb client) ,該組件發送命令。客戶端在開發計算機上運行。可以通過發出 adb 命令從命令行終端調用客戶端。
這里說的客戶端,其實包含很廣泛。例如我們在命令行窗口運行一個adb命令,其實就是一個adb客戶端。還有,我們在android studio中通過點擊運行或者調試按鈕,app就安裝到手機裡面了,這個也可以看做是adb客戶端。對應的後台進程名稱 根據運行的程序的不同而不同。
後台程序 ,該組件在設備上運行命令。後台程序在每個模擬器或設備實例上作為後台進程運行。
也就說,開發者測試手機或者模擬器上運行的後台進程,負責接收命令,並運行命令。這個名字對應應該是adbd
具體如下
服務端 ,該組件管理客戶端和後台程序之間的通信。伺服器在開發計算機上作為後台進程運行。
您可以在 android_sdk/platform-tools/ 中找到 adb 工具
這個是在開發者自己的電腦上,運行的旨在管理adb客戶端和手機端的後台程序通信的一個管理程序。
具體流程如下
啟動一個 adb 客戶端時,此客戶端首先檢查是否有已運行的 adb 伺服器進程。如果沒有,它將啟動伺服器進程。當伺服器啟動時,它與本地 TCP 埠 5037 綁定,並偵聽從 adb 客戶端發送的命令—所有 adb 客戶端均使用埠 5037 與 adb 伺服器通信。
然後,伺服器設置與所有運行的模擬器/設備實例的連接。它通過掃描 5555 到 5585 之間(模擬器/設備使用的范圍)的奇數號埠查找模擬器/設備實例。伺服器一旦發現 adb 後台程序,它將設置與該埠的連接。請注意,每個模擬器/設備實例將獲取一對按順序排列的埠 , 這些埠包括用於控制台連接的偶數號埠和用於 adb 連接的奇數號埠。例如:
模擬器 1,控制台:5554
模擬器 1,adb:5555
模擬器 2,控制台:5556
模擬器 2,adb:5557
以此類推...
如上所示,在埠 5555 與 adb 連接的模擬器實例與偵聽埠 5554 的控制台的實例相同。
注意 ,這里所說的埠都是開發者電腦上的埠。
我的理解,偶數埠用來實際的數據傳輸。奇數埠用來發送控制命令和連接用的,例如調試。(如果不正確請指出)
當伺服器已設置與所有模擬器實例的連接後,您可以使用 adb 命令訪問這些實例。由於伺服器管理與模擬器/設備實例的連接,並處理來自多個 adb 客戶端的命令,因此,您可以從任意客戶端(或從某個腳本)控制任意模擬器/設備實例。
解讀一下
注意:上圖中的標識為黃色的區域的進程為後台守護進程。
Adb Server運行在開發者電腦上,任何adb client都要等待這個運行起來之後才能做後續的工作。電腦上的android studio或者eclipse等一些adb client和它交互。一旦adb client的命令被發送到手機中,並且被手機中的adbd接收之後,才能和手機交互。
然後在看一張更詳細的圖
這個圖,詳細的解釋了我運行adb命令中的詳細細節。
關於adb的詳細命令可以參考: http://adbshell.com/commands 這個網站詳。
看了之後,對於前面的5037被佔用,導致無法連接手機的原因,我想,我們應該有了更深層次的理解。同時對於其他情況的不能連接手機,我們下次就會有了自己的思考了。