Learn how to use the Cronet Library to perform network operations in your
Android app. Cronet is the Chromium network stack made available as a library
for you to use in your apps. For more information about the library features,
see [Perform network operations using
Cronet](https://developer.android.com/develop/connectivity/cronet).

## Set up the library in your project

Follow these steps to add a dependency to the Cronet Library in your project:

1. Verify that Android Studio included a reference to Google's Maven Repository
   in your project's `settings.gradle` file, as shown in the following
   example:

   ### Groovy

   ```groovy
   dependencyResolutionManagement {
      ...
      repositories {
          ...
          google()
      }
   }
   ```

   ### Kotlin

   ```kotlin
   dependencyResolutionManagement {
      ...
      repositories {
          ...
          google()
      }
   }
   ```
2. Include a reference to the Google Play Services Client Library for Cronet
   in the `dependencies` section of your app module's `build.gradle` file, as
   shown in the following example:

   ### Groovy

   ```groovy
   dependencies {
      implementation 'com.google.android.gms:play-services-cronet:18.0.1'
   }
   ```

   ### Kotlin

   ```kotlin
   dependencies {
      implementation("com.google.android.gms:play-services-cronet:18.0.1")
   }
   ```

[`CronetEngine`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/CronetEngine) objects created once this
dependency is added will use Cronet loaded from Google Play services. Call
[`CronetProviderInstaller.installProvider(Context)`](https://developers.google.com/android/reference/com/google/android/gms/net/CronetProviderInstaller)
before creating `CronetEngine` objects to prevent unexpected exceptions
from being thrown during `CronetEngine` creation due to errors like devices
requiring an updated version of Google Play services.

In cases where Cronet cannot be loaded from Google Play services, there is
a less performant implementation of Cronet's API that can be used. To use
this fall-back implementation, depend on `org.chromium.net:cronet-fallback`
and call [`new JavaCronetProvider(context).createBuilder()`](https://cs.chromium.org/chromium/src/components/cronet/android/java/src/org/chromium/net/impl/JavaCronetProvider.java?rcl=083c8628750635ebdb2e1fa303c26141d4ac8773&l=31).

## Create a network request

This section shows how to create and send a network request using the Cronet
Library. After sending the network request, your app should [process the network
response](https://developer.android.com/develop/connectivity/cronet/start#response).

### Create and configure an instance of CronetEngine

The library provides a
[`CronetEngine.Builder`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/CronetEngine.Builder) class
that you can use to create an instance of
[`CronetEngine`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/CronetEngine). The following example
shows how to create a `CronetEngine` object:  

### Kotlin

```kotlin
val myBuilder = CronetEngine.Builder(context)
val cronetEngine: CronetEngine = myBuilder.build()
```

### Java

```java
CronetEngine.Builder myBuilder = new CronetEngine.Builder(context);
CronetEngine cronetEngine = myBuilder.build();
```
| **Note:** It's recommended to create only one instance of `CronetEngine`. A single instance can send multiple asynchronous requests. Additionally, a storage directory doesn't support concurrent access by multiple `CronetEngine` instances. For more information, see [`setStoragePath()`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/CronetEngine.Builder#setStoragePath(java.lang.String)).

You can use the `Builder` class to configure a
[`CronetEngine`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/CronetEngine) object, for example you can
provide options like caching and data compression. For more information, see
[`CronetEngine.Builder`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/CronetEngine.Builder).

### Provide an implementation of the request callback

To provide an implementation of the callback, create a subclass of
[`UrlRequest.Callback`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest.Callback) and
implement the required abstract methods, as shown in the following example:  

### Kotlin

```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

```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.");
  }
}
```
| **Note:** For simplicity, the previous code example creates an implementation of [`UrlRequest.Callback`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest.Callback) that writes a message to the log when a network event happens. To learn more details about how to implement the callback, see [Process the network response](https://developer.android.com/develop/connectivity/cronet/start#response).

### Create an Executor object to manage network tasks

You can use the [Executor](https://developer.android.com/reference/java/util/concurrent/Executor) class to execute network
tasks.
To get an instance of [Executor](https://developer.android.com/reference/java/util/concurrent/Executor), use one of the
static methods of the [Executors](https://developer.android.com/reference/java/util/concurrent/Executors) class that return
an `Executor` object. The following example shows how to create an `Executor`
object using the [newSingleThreadExecutor()](https://developer.android.com/reference/java/util/concurrent/Executors#newSingleThreadExecutor())
method:  

### Kotlin

```kotlin
val executor: Executor = Executors.newSingleThreadExecutor()
```

### Java

```java
Executor executor = Executors.newSingleThreadExecutor();
```

### Create and configure a UrlRequest object

To create the network request, call the
[`newUrlRequestBuilder()`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/CronetEngine#newUrlRequestBuilder(java.lang.String,%20org.chromium.net.UrlRequest.Callback,%20java.util.concurrent.Executor))
method of the [`CronetEngine`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/CronetEngine) passing the
destination URL, an instance of your callback class, and the executor object.
The `newUrlRequestBuilder()` method returns a
[`UrlRequest.Builder`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest.Builder) object that
you can use to create the [`UrlRequest`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest)
object, as shown in the following example:  

### Kotlin

```kotlin
val requestBuilder = cronetEngine.newUrlRequestBuilder(
        "https://www.example.com",
        MyUrlRequestCallback(),
        executor
)

val request: UrlRequest = requestBuilder.build()
```

### Java

```java
UrlRequest.Builder requestBuilder = cronetEngine.newUrlRequestBuilder(
        "https://www.example.com", new MyUrlRequestCallback(), executor);

UrlRequest request = requestBuilder.build();
```

You can use the [`Builder`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest.Builder) class to
configure the instance of [`UrlRequest`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest). For
example, you can specify a priority or the HTTP verb. For more information, see
[`UrlRequest.Builder`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest.Builder).

To start the network task, call the
[`start()`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest#start()) method of the request:  

### Kotlin

```kotlin
request.start()
```

### Java

```java
request.start();
```

By following the instructions in this section, you can create and send a network
request using Cronet. However, for the sake of simplicity, the example
implementation of
[`UrlRequest.Callback`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest.Callback) only prints
a message to the log. The following section shows how to provide a callback
implementation that supports more useful scenarios, such as extracting data from
the response and detecting a failure in the request.

## Process the network response

Once you call the [`start()`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest#start())
method, the Cronet request lifecycle is initiated. Your app should manage the
request during the lifecycle by specifying a callback. To learn more about the
lifecycle, see [Cronet request
lifecycle](https://developer.android.com/develop/connectivity/cronet/lifecycle). You can specify a
callback by creating a subclass of
[`UrlRequest.Callback`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest.Callback) and
implementing the following methods:

[`onRedirectReceived()`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest.Callback#onRedirectReceived(org.chromium.net.UrlRequest,%20org.chromium.net.UrlResponseInfo,%20java.lang.String))

:   Invoked when the server issues an HTTP redirect code in response to the
    original request. To follow the redirect to the new destination, use the
    [`followRedirect()`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest#followRedirect())
    method. Otherwise use the [`cancel()`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest#cancel())
    method. The following example shows how to implement the method:

    ### Kotlin

    ```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

    ```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()`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest.Callback#onResponseStarted(org.chromium.net.UrlRequest,%20org.chromium.net.UrlResponseInfo))

:   Invoked when the final set of headers is received. The `onResponseStarted()`
    method is only invoked after all redirects are followed. The following code
    shows an example implementation of the method:

    ### Kotlin

    ```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

    ```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();
    }
    ```
    | **Note:** Status codes `4xx` and `5xx` aren't considered errors from Cronet's perspective. You should still try to read the response using the [`read()`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest#read(java.nio.ByteBuffer)) method because the it could contain some data. You can also cancel the request using the [`cancel()`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest#cancel()) method. These actions ensure that the request is taken to a final state.

[`onReadCompleted()`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest.Callback#onReadCompleted(org.chromium.net.UrlRequest,%20org.chromium.net.UrlResponseInfo,%20java.nio.ByteBuffer))

:   Invoked whenever part of the response body has been read. The following code
    example shows how to implement the method and extract the response body:

    ### Kotlin

    ```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

    ```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()`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest.Callback#onSucceeded(org.chromium.net.UrlRequest,%20org.chromium.net.UrlResponseInfo))

:   Invoked when the network request is completed successfully. The following
    example shows how to implement the method:

    ### Kotlin

    ```kotlin
    override fun onSucceeded(request: UrlRequest?, info: UrlResponseInfo?) {
        // The request has completed successfully.
    }
    ```

    ### Java

    ```java
    @Override
    public void onSucceeded(UrlRequest request, UrlResponseInfo info) {
      // The request has completed successfully.
    }
    ```

[`onFailed()`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest.Callback#onFailed(org.chromium.net.UrlRequest,%20org.chromium.net.UrlResponseInfo,%20org.chromium.net.CronetException))

:   Invoked if the request failed for any reason after the
    [`start()`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest#start()) method was called. The
    following example shows how to implement the method and get information about
    the error:

    ### Kotlin

    ```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

    ```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()`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest.Callback#onCanceled(org.chromium.net.UrlRequest,%20org.chromium.net.UrlResponseInfo))

:   Invoked if the request was canceled using the
    [`cancel()`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest#cancel()) method. Once invoked, no
    other methods of the
    [`UrlRequest.Callback`](https://developer.android.com/develop/connectivity/cronet/reference/org/chromium/net/UrlRequest.Callback) class are
    invoked. You can use this method to free resources allocated to process a
    request. The following example shows how to implement the method:

    ### Kotlin

    ```kotlin
    override fun onCanceled(request: UrlRequest?, info: UrlResponseInfo?) {
        // Free resources allocated to process this request.
        ...
    }
    ```

    ### Java

    ```java
    @Override
    public void onCanceled(UrlRequest request, UrlResponseInfo info) {
      // Free resources allocated to process this request.
      ...
    }
    ```