了解如何使用 Cronet 库在 Android 应用中执行网络操作。Cronet 是以库的形式提供的 Chromium 网络栈,可供您在应用中使用。如需详细了解库功能,请参阅使用 Cronet 执行网络操作。
在您的项目中设置库
要在您的项目中为 Cronet 库添加依赖项,请按以下步骤操作:
验证 Android Studio 是否在项目的
settings.gradle文件中添加了对 Google Maven 仓库的引用,如以下示例所示:Groovy
dependencyResolutionManagement { ... repositories { ... google() } }
Kotlin
dependencyResolutionManagement { ... repositories { ... google() } }
在应用模块的
build.gradle文件的dependencies部分中添加对 Google Play 服务 Cronet 客户端库的引用,如以下示例所示:Groovy
dependencies { implementation 'com.google.android.gms:play-services-cronet:18.0.1' }
Kotlin
dependencies { implementation("com.google.android.gms:play-services-cronet:18.0.1") }
添加此依赖项后创建的 CronetEngine 对象会使用从 Google Play 服务加载的 Cronet。为防止在创建 CronetEngine 期间出现意外异常(例如在需要更新版 Google Play 服务的设备上),请在创建 CronetEngine 对象之前调用 CronetProviderInstaller.installProvider(Context)。
在无法从 Google Play 服务加载 Cronet 的情况下,可以使用性能较低的 Cronet API 实现。如需使用此回退实现,请依赖 org.chromium.net:cronet-fallback 并调用 new JavaCronetProvider(context).createBuilder()。
创建网络请求
本部分介绍了如何使用 Cronet 库创建和发送网络请求。发送网络请求后,您的应用必须处理网络响应。
创建并配置 CronetEngine 的实例
该库提供了一个 CronetEngine.Builder 类,您可以使用该类创建 CronetEngine 的实例。以下示例展示了如何创建 CronetEngine 对象:
Kotlin
val myBuilder = CronetEngine.Builder(context)
val cronetEngine: CronetEngine = myBuilder.build()
Java
CronetEngine.Builder myBuilder = new CronetEngine.Builder(context);
CronetEngine cronetEngine = myBuilder.build();
您可以使用 Builder 类来配置 CronetEngine 对象。例如,您可以提供缓存和数据压缩等选项。如需了解详情,请参阅CronetEngine.Builder。
提供请求回调的实现
如需提供回调的实现,请创建 UrlRequest.Callback 的子类并实现所需的抽象方法,如以下示例所示:
Kotlin
private const val TAG = "MyUrlRequestCallback"
class MyUrlRequestCallback : UrlRequest.Callback() {
override fun onRedirectReceived(request: UrlRequest?, info: UrlResponseInfo?, newLocationUrl: String?) {
Log.i(TAG, "onRedirectReceived method called.")
// You should call the request.followRedirect() method to continue
// processing the request.
request?.followRedirect()
}
override fun onResponseStarted(request: UrlRequest?, info: UrlResponseInfo?) {
Log.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 for the read() method. The same buffer
// with data is passed to the onReadCompleted() method.
request?.read(ByteBuffer.allocateDirect(102400))
}
override fun onReadCompleted(request: UrlRequest?, info: UrlResponseInfo?, byteBuffer: ByteBuffer?) {
Log.i(TAG, "onReadCompleted method called.")
// You should keep reading the request until there's no more data.
byteBuffer?.clear()
request?.read(byteBuffer)
}
override fun onSucceeded(request: UrlRequest?, info: UrlResponseInfo?) {
Log.i(TAG, "onSucceeded method called.")
}
}
Java
class MyUrlRequestCallback extends UrlRequest.Callback {
private static final String TAG = "MyUrlRequestCallback";
@Override
public void onRedirectReceived(UrlRequest request, UrlResponseInfo info, String newLocationUrl) {
Log.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) {
Log.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 for the read() method. The same buffer
// with data is passed to the onReadCompleted() method.
request.read(ByteBuffer.allocateDirect(102400));
}
@Override
public void onReadCompleted(UrlRequest request, UrlResponseInfo info, ByteBuffer byteBuffer) {
Log.i(TAG, "onReadCompleted method called.");
// You should keep reading the request until there's no more data.
byteBuffer.clear();
request.read(byteBuffer);
}
@Override
public void onSucceeded(UrlRequest request, UrlResponseInfo info) {
Log.i(TAG, "onSucceeded method called.");
}
}
创建一个 Executor 对象来管理网络任务
您可以使用 Executor 类来运行网络任务。如需获取 Executor 的实例,请使用 Executors 类中返回 Executor 对象的某个静态方法。以下示例展示了如何使用 newSingleThreadExecutor() 方法创建 Executor 对象:
Kotlin
val executor: Executor = Executors.newSingleThreadExecutor()
Java
Executor executor = Executors.newSingleThreadExecutor();
创建并配置 UrlRequest 对象
如需创建网络请求,请调用 CronetEngine 的 newUrlRequestBuilder() 方法,并传入目标网址、回调类的实例以及执行器对象。newUrlRequestBuilder() 方法会返回一个 UrlRequest.Builder 对象,您可以使用该对象创建 UrlRequest 对象,如以下示例所示:
Kotlin
val requestBuilder = cronetEngine.newUrlRequestBuilder(
"https://www.example.com",
MyUrlRequestCallback(),
executor
)
val request: UrlRequest = requestBuilder.build()
Java
UrlRequest.Builder requestBuilder = cronetEngine.newUrlRequestBuilder(
"https://www.example.com", new MyUrlRequestCallback(), executor);
UrlRequest request = requestBuilder.build();
您可以使用 Builder 类来配置 UrlRequest 的实例。例如,您可以指定优先级或 HTTP 动词。如需了解详情,请参阅 UrlRequest.Builder。
如需启动网络任务,请调用请求的 start() 方法:
Kotlin
request.start()
Java
request.start();
按照本部分中的说明,您可以使用 Cronet 创建和发送网络请求。不过,为简单起见,UrlRequest.Callback 的示例实现仅向日志输出一条消息。以下部分介绍了如何提供支持更多实用场景的回调实现,例如从响应中提取数据以及检测请求中的失败。
处理网络响应
调用 start() 方法后,Cronet 会启动请求生命周期。通过指定回调,在生命周期内管理请求。如需详细了解生命周期,请参阅 Cronet 请求生命周期。您可以通过创建 UrlRequest.Callback 的子类并实现以下方法来指定回调:
onRedirectReceived()当服务器发出 HTTP 重定向代码以响应原始请求时,Cronet 会调用此方法。如需遵循重定向到新目标位置,请使用
followRedirect()方法。否则,请使用cancel()方法。以下示例展示了如何实现该方法:Kotlin
override fun onRedirectReceived(request: UrlRequest?, info: UrlResponseInfo?, newLocationUrl: String?) { // Determine whether you want to follow the redirect. ... if (shouldFollow) { request?.followRedirect() } else { request?.cancel() } }Java
@Override public void onRedirectReceived(UrlRequest request, UrlResponseInfo info, String newLocationUrl) { // Determine whether you want to follow the redirect. ... if (shouldFollow) { request.followRedirect(); } else { request.cancel(); } }onResponseStarted()Cronet 会在收到最后一组标头时调用此方法。Cronet 仅在跟踪所有重定向后调用
onResponseStarted()。以下代码展示了该方法的实现示例:Kotlin
override fun onResponseStarted(request: UrlRequest?, info: UrlResponseInfo?) { val httpStatusCode = info?.httpStatusCode if (httpStatusCode == 200) { // The request was fulfilled. Start reading the response. request?.read(myBuffer) } else if (httpStatusCode == 503) { // The service is unavailable. You should still check if the request // contains some data. request?.read(myBuffer) } responseHeaders = info?.allHeaders }Java
@Override public void onResponseStarted(UrlRequest request, UrlResponseInfo info) { int httpStatusCode = info.getHttpStatusCode(); if (httpStatusCode == 200) { // The request was fulfilled. Start reading the response. request.read(myBuffer); } else if (httpStatusCode == 503) { // The service is unavailable. You should still check if the request // contains some data. request.read(myBuffer); } responseHeaders = info.getAllHeaders(); }onReadCompleted()每当读取部分响应正文时,Cronet 都会调用此方法。以下代码示例展示了如何实现该方法并提取响应正文:
Kotlin
override fun onReadCompleted(request: UrlRequest?, info: UrlResponseInfo?, byteBuffer: ByteBuffer?) { // The response body is available, process byteBuffer. ... // Continue reading the response body by reusing the same buffer // until the response has been completed. byteBuffer?.clear() request?.read(myBuffer) }Java
@Override public void onReadCompleted(UrlRequest request, UrlResponseInfo info, ByteBuffer byteBuffer) { // The response body is available, process byteBuffer. ... // Continue reading the response body by reusing the same buffer // until the response has been completed. byteBuffer.clear(); request.read(myBuffer); }onSucceeded()当网络请求成功完成时,Cronet 会调用此方法。 以下示例展示了如何实现该方法:
Kotlin
override fun onSucceeded(request: UrlRequest?, info: UrlResponseInfo?) { // The request has completed successfully. }Java
@Override public void onSucceeded(UrlRequest request, UrlResponseInfo info) { // The request has completed successfully. }onFailed()如果您的应用调用
start()方法后请求因任何原因失败,Cronet 就会调用此方法。以下示例展示了如何实现该方法并获取有关错误的信息:Kotlin
override fun onFailed(request: UrlRequest?, info: UrlResponseInfo?, error: CronetException?) { // The request has failed. If possible, handle the error. Log.e(TAG, "The request failed.", error) }Java
@Override public void onFailed(UrlRequest request, UrlResponseInfo info, CronetException error) { // The request has failed. If possible, handle the error. Log.e(TAG, "The request failed.", error); }onCanceled()如果使用
cancel()方法取消了请求,Cronet 会调用此方法。Cronet 调用onCanceled()后,不会调用UrlRequest.Callback类的任何其他方法。您可以使用此方法释放为处理请求而分配的资源。以下示例展示了如何实现该方法:Kotlin
override fun onCanceled(request: UrlRequest?, info: UrlResponseInfo?) { // Free resources allocated to process this request. ... }Java
@Override public void onCanceled(UrlRequest request, UrlResponseInfo info) { // Free resources allocated to process this request. ... }