chromium-cronet文檔 原文文檔寫的已經很清楚,最好還是參考官方文檔,避免由于版本原因導緻的問題。
Cronet開發者文檔:https://developer.android.com/guide/topics/connectivity/cronet
部落格中的git位址:https://github.com/bgylde/chromium-cornet
環境配置
- chromium源碼環境;
- 已經配置好相關環境,安裝好相關依賴;
- 這裡是在linux環境下對Android庫的編譯,在macos環境下會直接編譯為ios平台庫;
編譯開發和debug環境的Cronet庫
Android / IOS build
$ ./components/cronet/tools/cr_cronet.py gn --out_dir=out/Cronet
如果build主機是在linux環境下,build的是android的庫。如果build主機是macOS,build的是ios庫。
$ ninja -C out/Cronet cronet_package
編譯Cronet庫,最終檔案可以在out/Cronet/cornet中尋找。
使用cronet庫
- 建立CronetEngine,最好整個應用使用一個CronetEngine,這裡可以了解為OkHttpClient;
- 建立自己的線程池給Cronet使用,Cronet的網絡請求都會線上程池中,避免主線程阻塞;
- 實作回調UrlRequest.Callback,在UrlRequest調用start以後,網絡請求開始,之後産生請求回調;
public class UrlRequestCallback extends UrlRequest.Callback {
private static final String TAG = "UrlRequestCallback";
private long startTime;
private ByteBuffer mByteBuffer = ByteBuffer.allocateDirect(102400);
private ByteArrayOutputStream mBytesReceived = new ByteArrayOutputStream();
private WritableByteChannel mReceiveChannel = Channels.newChannel(mBytesReceived);
@Override
public void onRedirectReceived(UrlRequest request, UrlResponseInfo info, String newLocationUrl) {
LogUtils.i(TAG, "onRedirectReceived method called.");
// You should call the request.followRedirect() method to continue
// processing the request.
request.followRedirect();
}
@Override
public void onResponseStarted(UrlRequest request, UrlResponseInfo info) {
LogUtils.i(TAG, "onResponseStarted method called.");
// You should call the request.read() method before the request can be
// further processed. The following instruction provides a ByteBuffer object
// with a capacity of 102400 bytes to the read() method.
//ByteBuffer byteBuffer = ByteBuffer.allocateDirect(102400);
startTime = System.currentTimeMillis();
request.read(mByteBuffer);
}
@Override
public void onReadCompleted(UrlRequest request, UrlResponseInfo info, ByteBuffer byteBuffer) {
LogUtils.i(TAG, "onReadCompleted method called.");
// You should keep reading the request until there's no more data.
try {
byteBuffer.flip();
mReceiveChannel.write(byteBuffer);
byteBuffer.clear();
} catch (IOException e) {
LogUtils.e(TAG, e);
}
request.read(mByteBuffer);
}
@Override
public void onSucceeded(UrlRequest request, UrlResponseInfo info) {
LogUtils.i(TAG, "onSucceeded method called: " + info.toString());
LogUtils.d(TAG, "cost time: " + (System.currentTimeMillis() - startTime) + " ms");
//byte[] bytes = mBytesReceived.toByteArray();
String receivedData = null;
try {
receivedData = mBytesReceived.toString("GBK");
} catch (UnsupportedEncodingException e) {
LogUtils.e(TAG, e);
}
final String url = info.getUrl();
final String text = "Completed " + url + " (" + info.getHttpStatusCode() + ")";
//LogUtils.i(TAG, "text: " + text);
//LogUtils.i(TAG, "receivedData: " + receivedData);
}
@Override
public void onFailed(UrlRequest urlRequest, UrlResponseInfo urlResponseInfo, CronetException e) {
//LogUtils.d(TAG, "url: " + urlResponseInfo.getUrl());
LogUtils.e(TAG, "onFailed method called.", e);
}
@Override
public void onCanceled(UrlRequest request, UrlResponseInfo info) {
LogUtils.d(TAG, "onCanceled method called.");
}
}
- onRedirectReceived 顧名思義,是重定向的回調,這裡直接選擇繼續通路重定向的位址,也可以調用UrlRequest的cancel方法,取消通路;
- onResponseStarted 從google文檔上面來看是請求完header以後開始請求body部分會回調這裡,每次請求隻會回調一次;
- onReadCompleted 這是讀取body一定資料時會回調這個方法,這裡request.read讀取的資料不一定會填滿緩沖區,請求生命周期中會有多次回調發生;
- onSucceeded 最終請求成功回調,可以作為資料處理階段;
- onFailed 請求失敗回調,例如網絡不通,或者沒有網絡通路權限之類的錯誤;
- onCanceled 請求取消回調,隻會在cancel後才會回調,回調這個意味着整個請求完成;
https://ssl.gstatic.com/gb/images/qi2_00ed8ca1.png 實作quic通路,可作為測試位址。
這是通過抓包看到的quic協定,進一步的性能對比就需要自己搭建一個支援quic協定的伺服器。