Android Http網路開發神兵利器
來自專欄 流水不腐小夏
本人在Android移動端開發已經有不少年的經驗,經歷頗多,感受頗深,特寫下此文記錄下在Android Http網路開發中的各種工具使用,如果有其他想法和建議,歡迎前來交流xiaqiulei@126.com 。 本人文筆較差,請不要見怪。
Android開發的時候,很多APP都是基於網路請求的,大部分應用都是基於http的,少部分是基於Socket的,本文主要介紹Android Http開發的主要實踐和工具。
Http協議
說起Http網路請求,那麼要介紹下Http協議,我在公司面試的時候也很喜歡問這個問題。很多做好了3-5年的工程師,竟然不知道Http協議,只知道怎麼調用類庫,不知道原理。
作為一個有追求的程序員,Http協議還是需要了解的。知其然知其所以然,在了解Http協議的情況下,才能在實際開發中靈活運用和優化。
這裡有篇 文章 ,Http協議介紹的很詳細。
HTTP簡介
HTTP協議是Hyper Text Transfer Protocol(超文本傳輸協議)的縮寫,是用於從萬維網(WWW:World Wide Web )伺服器傳輸超文本到本地瀏覽器的傳送協議。
HTTP是一個基於TCP/IP通信協議來傳遞數據(HTML 文件, 圖片文件, 查詢結果等)。
HTTP是一個屬於應用層的面向對象的協議,由於其簡捷、快速的方式,適用於分散式超媒體信息系統。它於1990年提出,經過幾年的使用與發展,得到不斷地完善和擴展。目前在WWW中使用的是HTTP/1.0的第六版,HTTP/1.1的規範化工作正在進行之中,而且HTTP-NG(Next Generation of HTTP)的建議已經提出。
HTTP協議工作於客戶端-服務端架構為上。瀏覽器作為HTTP客戶端通過URL向HTTP服務端即WEB伺服器發送所有請求。Web伺服器根據接收到的請求後,向客戶端發送響應信息。
主要特點
1、簡單快速:客戶向伺服器請求服務時,只需傳送請求方法和路徑。請求方法常用的有GET、HEAD、POST。每種方法規定了客戶與伺服器聯繫的類型不同。由於HTTP協議簡單,使得HTTP伺服器的程序規模小,因而通信速度很快。
2、靈活:HTTP允許傳輸任意類型的數據對象。正在傳輸的類型由Content-Type加以標記。
3.無連接:無連接的含義是限制每次連接只處理一個請求。伺服器處理完客戶的請求,並收到客戶的應答後,即斷開連接。採用這種方式可以節省傳輸時間。
4.無狀態:HTTP協議是無狀態協議。無狀態是指協議對於事務處理沒有記憶能力。缺少狀態意味著如果後續處理需要前面的信息,則它必須重傳,這樣可能導致每次連接傳送的數據量增大。另一方面,在伺服器不需要先前信息時它的應答就較快。
5、支持B/S及C/S模式。
Request
Http請求消息結構上圖是一個Http請求消息結構,我們可以使用抓包工具抓取網路請求,因為是Get請求,所以後面沒有請求數據
GET /562f25980001b1b106000338.jpg HTTP/1.1Host img.mukewang.comUser-Agent Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36Accept image/webp,image/*,*/*;q=0.8Referer http://www.imooc.com/Accept-Encoding gzip, deflate, sdchAccept-Language zh-CN,zh;q=0.8
第一部分:請求行,用來說明請求類型,要訪問的資源以及所使用的HTTP版本.
GET說明請求類型為GET,[/562f25980001b1b106000338.jpg]為要訪問的資源,該行的最後一部分說明使用的是HTTP1.1版本。
第二部分:請求頭部,緊接著請求行(即第一行)之後的部分,用來說明伺服器要使用的附加信息
從第二行起為請求頭部,HOST將指出請求的目的地.User-Agent,伺服器端和客戶端腳本都能訪問它,它是瀏覽器類型檢測邏輯的重要基礎.該信息由你的瀏覽器來定義,並且在每個請求中自動發送等等
第三部分:空行,請求頭部後面的空行是必須的
即使第四部分的請求數據為空,也必須有空行。
第四部分:請求數據也叫主體,可以添加任意的其他數據。
這個例子的請求數據為空。
下面這個例子是Post方式。
POST / HTTP1.1Host:www.wrox.comUser-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)Content-Type:application/x-www-form-urlencodedContent-Length:40Connection: Keep-Alivename=Professional%20Ajax&publisher=Wiley
第一部分:請求行,第一行明了是post請求,以及http1.1版本。
第二部分:請求頭部,第二行至第六行。
第三部分:空行,第七行的空行。
第四部分:請求數據,第八行。
Response
一般情況下,伺服器接收並處理客戶端發過來的請求後會返回一個HTTP的響應消息。
HTTP響應也由四個部分組成,分別是:狀態行、消息報頭、空行和響應正文。
Http響應消息結構HTTP/1.1 200 OKDate: Fri, 22 May 2009 06:07:21 GMTContent-Type: text/html; charset=UTF-8<html> <head></head> <body> <!--body goes here--> </body></html>
第一部分:狀態行,由HTTP協議版本號, 狀態碼, 狀態消息 三部分組成。
第一行為狀態行,(HTTP/1.1)表明HTTP版本為1.1版本,狀態碼為200,狀態消息為(ok)
第二部分:消息報頭,用來說明客戶端要使用的一些附加信息
第二行和第三行為消息報頭,
Date:生成響應的日期和時間;Content-Type:指定了MIME類型的HTML(text/html),編碼類型是UTF-8第三部分:空行,消息報頭後面的空行是必須的
第四部分:響應正文,伺服器返回給客戶端的文本信息。
空行後面的html部分為響應正文。
Code
狀態代碼有三位數字組成,第一個數字定義了響應的類別,共分五種類別:
1xx:指示信息--表示請求已接收,繼續處理
2xx:成功--表示請求已被成功接收、理解、接受
3xx:重定向--要完成請求必須進行更進一步的操作
4xx:客戶端錯誤--請求有語法錯誤或請求無法實現
5xx:伺服器端錯誤--伺服器未能實現合法的請求
常見狀態碼:
200 OK // 客戶端請求成功400 Bad Request // 客戶端請求有語法錯誤,不能被伺服器所理解401 Unauthorized // 請求未經授權,這個狀態代碼必須和WWW-Authenticate報頭域一起使用403 Forbidden // 伺服器收到請求,但是拒絕提供服務404 Not Found // 請求資源不存在,eg:輸入了錯誤的URL500 Internal Server Error // 伺服器發生不可預期的錯誤503 Server Unavailable // 伺服器當前不能處理客戶端的請求,一段時間後可能恢復正常
Method
根據HTTP標準,HTTP請求可以使用多種請求方法。
HTTP1.0定義了三種請求方法: GET, POST 和 HEAD方法。HTTP1.1新增了五種請求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。GET 請求指定的頁面信息,並返回實體主體。HEAD 類似於get請求,只不過返回的響應中沒有具體的內容,用於獲取報頭POST 向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在請求體中。POST請求可能會導致新的資源的建立和/或已有資源的修改。PUT 從客戶端向伺服器傳送的數據取代指定的文檔的內容。DELETE 請求伺服器刪除指定的頁面。CONNECT HTTP/1.1協議中預留給能夠將連接改為管道方式的代理伺服器。OPTIONS 允許客戶端查看伺服器的性能。TRACE 回顯伺服器收到的請求,主要用於測試或診斷。
Header
HTTP消息由客戶端到伺服器的請求和伺服器到客戶端的響應組成。請求消息和響應消息都是由開始行(對於請求消息,開始行就是請求行,對於響應消息,開始行就是狀態行),消息報頭(可選),空行(只有CRLF的行),消息正文(可選)組成。
HTTP消息報頭包括普通報頭、請求報頭、響應報頭、實體報頭。
每一個報頭域都是由名字+「:」+空格+值 組成,消息報頭域的名字是大小寫無關的。
網路請求庫
下面介紹幾個常見的Android http網路開發的工具庫。
URLConnection
URLConnection是Java JDK中自帶的網路請求類,使用的場景不多,因為使用比較繁瑣,直接使用底層IO流進行開發,需要了解Http協議才能很好的使用,很多時候需要自己封裝,不方便。一般的一些提供第三方服務的sdk會使用,一是為了保證sdk體積大小,二是減少不必要的第三方庫引入。
這裡不做詳細介紹, 這裡有一篇博可以詳細介紹了 。
Apache HttpClient
HttpClient是Apache Jakarta Common下的子項目,用來提供高效的、最新的、功能豐富的支持HTTP協議的客戶端編程工具包,並且它支持HTTP協議最新的版本和建議。HttpClient已經應用在很多的項目中,比如Apache Jakarta上很著名的另外兩個開源項目Cactus和HTMLUnit都使用了HttpClient。
HttpClient相比傳統JDK自帶的URLConnection,增加了易用性和靈活性,它不僅是客戶端發送Http請求變得容易,而且也方便了開發人員測試介面(基於Http協議的),即提高了開發的效率,也方便提高代碼的健壯性。
Android在低版本的系統Api中也有Httpclient相關類,但是後來就已經廢棄,相關資料可以 參考這裡.
HttpClient相關博客
Volley
Android Volley 是在2013年Google I/O大會上推出了一個新的網路通信框架——Volley。Volley可是說是把AsyncHttpClient和Universal-Image-Loader的優點集於了一身,既可以像AsyncHttpClient一樣非常簡單地進行HTTP通信,也可以像Universal-Image-Loader一樣輕鬆載入網路上的圖片。除了簡單易用之外,Volley在性能方面也進行了大幅度的調整,它的設計目標就是非常適合去進行數據量不大,但通信頻繁的網路操作,而對於大數據量的網路操作,比如說下載文件等,Volley的表現就會非常糟糕。
有 資料 指出Volley在進行網路請求時,在Android 2.3及以上版本,使用的是HttpURLConnection,而在Android 2.2及以下版本,使用的是HttpClient。主要是因為HttpURLConnection存在相關bug。
Volley相關資料
Volley相關資料
OkHttp & Retrofit
OkHttpSquare公司開源的處理網路請求的開源項目,是安卓端最火熱的輕量級框架,用於替代HttpUrlConnection和Apache HttpClient。最新的版本是OkHttp3,Github地址在 這裡 。
Retrofit也是是Square公司開發的一款針對Android網路請求的框架,Retrofit2底層基於OkHttp實現的,OkHttp現在已經得到Google官方認可,大量的app都採用OkHttp做網路請求, Github地址 。
網路上也有很多關於OkHttp、Retrofit的示例和資料,而且是目前Android移動端最流行的框架,還是很值得了解一下,在這裡就不做詳細介紹。
工具
Charles
Charles是一個HTTP代理伺服器,HTTP監視器,反轉代理伺服器·它允許一個開發者查看所有連接互聯網的HTTP通信·這些包括request、response、headers(包含cookies與caching信息),由於筆者的開發機器是Mac,所以只介紹了Charles,Windows開發環境的同學可以使用fiddler。
Charles介紹
Charles 主要的功能包括:
截取 Http 和 Https 網路封包。
支持網路請求調試,設置斷點,方便調試
支持重發網路請求,方便後端調試。
支持修改網路請求參數。
支持網路請求的截獲並動態修改。
支持模擬弱網。
上面介紹了,可以使用Charles方便設置斷點,方便調試,可以很容易的修改數據包,這樣可以動態修改數據,mock api介面,在實際開發過程中很有用。
Charles Mock 數據
PostMan & Paw
上面介紹了網路抓包工具Charles,先介紹2款模擬http請求的軟體。
Postman是一款功能強大的網頁調試與發送網頁HTTP請求的Chrome插件,使用很簡單。
下圖模擬發送知乎Api的網路請求。
http://news-at.zhihu.com/api/4/themes
Postman官網
Postman資料
Paw 也是類似於Postman的一款模擬http請求的軟體,只不過postman依賴於chrome,經常需要點擊2此才可以打開postman,所以個人更加喜歡paw,下圖是paw請求知乎api的示例。BTW, paw是一款收費的軟體,不過么網上也有破解的,在這裡就不介紹如何獲取了,反正大家都懂的。
Paw 官網
Paw 使用教程
Chrome Dev Tools
Chrome dev tools是Google Chrome瀏覽器中自帶一塊調試工具。如果你是做軟體開發的,基本都了解過。
雖然Chrome dev tools 在web開發中使用很多,但是在移動端中也是有用到的,這個後面再介紹。
Chrome dev tools 相關資料
Chrome dev tools 相關資料
Chrome dev tools 相關資料
curl
curl也是和上面poastman與paw功能類似的,不過沒有和上面兩款放在一起講是因為curl比較重要,而且具有統一標準性與方便性。
curl是利用URL語法在命令行方式下工作的開源文件傳輸工具。它被廣泛應用在Unix、多種Linux發行版中,並且有DOS和Win32、Win64下的移植版本。
還是原先的例子,請求知乎的api。
很簡單在curl命令直接加入url即可發送網路請求。
為什麼有postman和paw這麼友好的軟體後,還需要介紹的curl呢,因為curl是一個命令,是文本,是字元串,當你其他同事開發聯調的時候,直接通過im工具發送即可,這樣網路請求就能很容移動復現。很多的上面介紹的charles、paw、google dev tool都支持把某一條請求導出為curl命令。這就相當於curl是一個標準,可以在不同機器上面復用,所以了解和使用curl是很有必要的。比如聯調開發時候,伺服器某個api調試不通過,需要與伺服器同學溝通與複習,你直接丟一個curl語句即可,如果對方很懂,那麼會覺的你很專業,如果對方不懂,順便可以裝個逼。
curl 資料
curl 官網
OkHttp相關
前面介紹了OkHttp,下面介紹幾個基於OkHttp攔截器機制衍生出的常用的工具。
logging-interceptor
開發中經常需要對網路請求進行查看,抓包是可以的,不過現在很多app都是全棧https,想要抓包就沒有那麼容易了,那麼最簡單的還是打日誌。
logging-interceptor就是干這個事的,在初始化okhttpclient的時候,添加下這個攔截器,那麼所有的網路請求會被記錄下來。
相關資料
相關資料
Stetho
Stetho是Facebook開源的一個工具,前面說過Google Chrome dev tools,那麼Stetho可以讓Chrome調試Android,監控網路請求。
同時Stetho還支持查看資料庫,SharePreference等,而這個前提是必須root,查看view樹,使用Stetho也可以做到。
網上也有很多也有很多相關資料,這裡不介紹詳細使用。
stetho github
stetho 相關資料
chuck
上面介紹的兩款工具,一種是需要在logcat中查看網路請求數據,一種是需要在chrome中查看數據,有沒有辦法不需要藉助任何第三方工具,直接查看呢,答案是肯定的。chuck是我最近關注比較高的一個開源工具,而且很快的就在項目中使用了。
下面官網的截圖,可以先了解下chuck的使用效果。
在高版本的Android中,還支持多屏顯示,那麼一邊操作一邊顯示。
集成的方法都很簡單,只需要在初始化OkHttpClient的時候,添加對應的攔截器即可。
Gradle依賴
dependencies { debugCompile com.readystatesoftware.chuck:library:1.0.4 releaseCompile com.readystatesoftware.chuck:library-no-op:1.0.4 }
添加攔截器
OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(new ChuckInterceptor(context)) .build();
Chuck github
其他
RESTful
RESTful一種軟體架構風格,設計風格而不是標準,只是提供了一組設計原則和約束條件。它主要用於客戶端和伺服器交互類的軟體。基於這個風格設計的軟體可以更簡潔,更有層次,更易於實現緩存等機制。
REST(英文:Representational State Transfer,簡稱REST)描述了一個架構樣式的網路系統,比如 web 應用程序。它首次出現在 2000 年 Roy Fielding 的博士論文中,他是 HTTP 規範的主要編寫者之一。在目前主流的三種Web服務交互方案中,REST相比於SOAP(Simple Object Access protocol,簡單對象訪問協議)以及XML-RPC更加簡單明了,無論是對URL的處理還是對Payload的編碼,REST都傾向於用更加簡單輕量的方法設計和實現。值得注意的是REST並沒有一個明確的標準,而更像是一種設計的風格。
雖然本文的主題是介紹Android Http開發的相關內容,並且RESTful是服務端的一種概念。但是我覺的,還是有很必要了解的,最起碼可以作為判斷你的服務端小夥伴給的介面是否滿足RESTful的標準的依據。
後面貼一篇阮一峰大神的博客介紹RESTful
總結
心得
上面介紹了很多種關於網路請求的工具,具體可以分為這幾類。
HTTP介面調用工具,這類工具主要是模擬客戶端,發起網路請求,方便調試伺服器介面。
- postman
- paw
- curl
抓包工具,這類工具不光適合Android開發,也適合其他網路開發,工具使用簡單,不過在使用前需要做少許代理配置。WiresShark是一款更加強大的工具,使用比較複雜,而且比較底層,所以在本文中就沒介紹,有興趣的同學可以自己查閱相關資料。
- Charles
- Fiddler
- WiresShark
Android Http請求工具庫,這類工具類變化很快,經常會過個幾年就會有新的一種工具替換,但是本質思想還是一樣的,都是基於URLConnection和HTTP做了一次封裝調用。
- URLConnection
- HttpClient
- Volley
- OkHttp
OkHttp相關,這類工具都是基於OkHttp做了二次封裝開發,這個主要歸功於OkHttp強大開發模式和架構,開發人員可以方便對OkHttp進行自定義和二次開發。工具很強大,不過也有局限性,只能依附於OkHttp的框架,不利於擴展到其他平台和工具。
- logging-interceptor
- Stetho
- Chuck
工具對比
上面介紹好幾款可以監控App網路請求的工具,那麼如何根據實際情況,選擇一款適合自己項目和團隊的工具呢?
Charles & Fiddler
這類工具不依賴與平台和App開發的工具庫,不管你是Android、還是iOS,不管使用的是Volley,還是OkHttp都是可以監控的,同時還支持HTTP的調試,方便mock數據,簡直是神器。
不過也有少許缺點,比如是不支持Https,如果你的app使用的是https介面,那麼這類工具一般情況是不能使用的,不過也有辦法,比如把charles的證書設置為根證書,則可以檢測到。但是也是有局限的,如果app設置強制校驗https證書,此類方法還是不可行。
因為平台無光,可檢測到某個手機設備上面的全部網路請求,數據量有時候會很大,如果經常調試某一個app,那麼域名一般是固定的,可進行相對應的過濾。
OkHttp相關
通過標題可以看成,此類工具必須依附於OKHttp,那麼只能滿足Android平台並且App的網路請求庫是OkHttp。上面介紹的三款工具,可以選擇性的選擇其中幾種或者是全部,暫時還沒有發現衝突的地方。因為是直接嵌入到代碼中,那麼Https也是可以監控到。同時也只能監控當前設備上的當前應用,不可以檢測其他的app。
不過在發布線上或者正式頒布時,需要手動去除這些代碼,否則會有很大麻煩,同時也會把相關的隱私和安全反饋給使用的用戶。
好了,上面就是關於App網路情況的監控工具比較,建議兩個大分類都可以幾個或者多個配合使用,具體問題在根據具體工具使用,方便問題解決與網路監控。
其他建議
上面介紹的OkHttp的相關的工具,都是需要在初始化OkHttpClient的時候,手動添加對應的攔截器,如果忘記添加則不會產生效果。
那麼可以使用現在流行的Aop技術,在編譯時候,會在所有調用OkHttpClient的地方,自動添加,保證不會忘記,如果你的App還是用其他的sdk,sdk裡面也是用OKhttp的話,也會監控到sdk裡面的網路請求,不少大廠已經使用了這種方法,然後收集請求數據到後端,方便管理和優化。
下面簡單介紹相關代碼:
首先集成gradle_plugin_android_aspectjx插件
dependencies { classpath com.hujiang.aspectjx:gradle-android-plugin-aspectjx:1.0.9}
然後定義Aspectj切入點
import com.facebook.stetho.okhttp3.StethoInterceptor;import com.readystatesoftware.chuck.ChuckInterceptor;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import me.ele.breakfastapp.AppContext;import okhttp3.OkHttpClient;@Aspectpublic class OkHttpAspect { @Pointcut("call(public okhttp3.OkHttpClient build())") public void build() { } @Around("build()") public Object aroundBuild(ProceedingJoinPoint joinPoint) throws Throwable { Object target = joinPoint.getTarget(); if (target instanceof OkHttpClient.Builder) { OkHttpClient.Builder builder = (OkHttpClient.Builder) target; builder.addNetworkInterceptor(new StethoInterceptor()); builder.addNetworkInterceptor(new ChuckInterceptor(AppContext.get())); } return joinPoint.proceed(); }}
那麼在代碼編譯的時候,會自動插入位元組碼。
Aop相關資料:
Aop介紹
Aop資料
Assectj
Assectj Gradle 插件
參考資料
Http博客
Http博客
URLConnection 。
Android HttpClient.
HttpClient相關博客
Volley相關資料
Volley相關資料
OkHttp 。
Retrofit Github地址 。
Charles介紹
Charles Mock 數據
Postman官網
Postman資料
Paw 官網
Paw 使用教程
Chrome dev tools 相關資料
Chrome dev tools 相關資料
Chrome dev tools 相關資料
curl 資料
curl 官網
Interceptors相關資料
LoggingInterceptors相關資料
stetho github
stetho 相關資料
Chuck github
RESTful
Aop介紹
Aop資料
Assectj
Assectj Gradle 插件
推薦閱讀:
※計算機網路:適配器
※在美聯航(United)飛機上使用免費Wi-Fi的探索
※ZT.RTL8723BE在win10系統下不支持承載網路,獵豹wifi老是掉線解決辦法
※Linux GRE tunnel的構建原理及應用
※美世留學:學霸都選擇出國留學