summaryrefslogtreecommitdiffstats
path: root/components/cronet/README.md
blob: 8a46ef534d3c29f02b3dad9ac98287fe3cbf53d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# Quick Start Guide to Using Cronet
Cronet is the networking stack of Chromium put into a library for use on
mobile. This is the same networking stack that is used in the Chrome browser
by over a billion people. It offers an easy-to-use, high performance,
standards-compliant, and secure way to perform HTTP requests. Cronet has support
for both Android and iOS. On Android, Cronet offers its own Java asynchronous
API as well as support for the [java.net.HttpURLConnection] API.
This document gives a brief introduction to using these two Java APIs.

### Basics
First you will need to implement the `UrlRequestListener` interface to handle
events during the lifetime of a request. For example:

    class MyListener implements UrlRequestListener {
        @Override
        public void onReceivedRedirect(UrlRequest request,
                ResponseInfo responseInfo, String newLocationUrl) {
            if (followRedirect) {
                // Let's tell Cronet to follow the redirect!
                mRequest.followRedirect();
            } else {
                // Not worth following the redirect? Abandon the request.
                mRequest.cancel();
            }
        }

        @Override
        public void onResponseStarted(UrlRequest request,
                ResponseInfo responseInfo) {
             // Now we have response headers!
             int httpStatusCode = responseInfo.getHttpStatusCode();
             if (httpStatusCode == 200) {
                 // Success! Let's tell Cronet to read the response body.
                 request.read(myBuffer);
             } else if (httpStatusCode == 503) {
                 // Do something. Note that 4XX and 5XX are not considered
                 // errors from Cronet's perspective since the response is
                 // successfully read.
             }
             responseHeaders = responseInfo.getAllHeaders();
        }

        @Override
        public void onReadCompleted(UrlRequest request,
                ResponseInfo responseInfo, ByteBuffer byteBuffer) {
             // Response body is available.
             doSomethingWithResponseData(byteBuffer);
             // Let's tell Cronet to continue reading the response body or
             // inform us that the response is complete!
             request.read(myBuffer);
        }

        @Override
        public void onSucceeded(UrlRequest request,
                ExtendedResponseInfo extendedResponseInfo) {
             // Request has completed successfully!
        }

        @Override
        public void onFailed(UrlRequest request,
                ResponseInfo responseInfo, UrlRequestException error) {
             // Request has failed. responseInfo might be null.
             Log.e("MyListener", "Request failed. " + error.getMessage());
             // Maybe handle error here. Typical errors include hostname
             // not resolved, connection to server refused, etc.
        }
    }

Make a request like this:

    UrlRequestContextConfig myConfig = new UrlRequestContextConfig();
    CronetUrlRequestContext myRequestContext =
            new CronetUrlRequestContext(getContext(), myConfig);
    Executor executor = ExecutorService.newSingleThreadExecutor();
    MyListener listener = new MyListener();
    UrlRequest request = myRequestContext.createRequest(
            "https://www.example.com", listener, executor);
    request.start();

In the above example, `MyListener` implements the `UrlRequestListener`
interface. The request is started asynchronously. When the response is ready
(fully or partially), and in the event of failures or redirects,
`listener`'s methods will be invoked on `executor`'s thread to inform the
client of the request state and/or response information.

### Downloading Data
When Cronet fetches response headers from the server or gets them from the
cache, `UrlRequestListener.onResponseStarted` will be invoked. To read the
response body, the client should call `UrlRequest.read` and supply a
[ByteBuffer] for Cronet to fill. Once a portion or all of
the response body is read, `UrlRequestListener.onReadCompleted` will be invoked.
The client may consume the data, or copy the contents of the `byteBuffer`
elsewhere for use later. The data in `byteBuffer` is only guaranteed to be
valid for the duration of the `UrlRequestListener.onReadCompleted` callback.
Once the client is ready to consume more data, the client should call
`UrlRequest.read` again. The process continues until
`UrlRequestListener.onSucceeded` or `UrlRequestListener.onFailed` is invoked,
which signals the completion of the request.

### Uploading Data
    MyUploadDataProvider myUploadDataProvider = new MyUploadDataProvider();
    request.setHttpMethod("POST");
    request.setUploadDataProvider(myUploadDataProvider, executor);
    request.start();

In the above example, `MyUploadDataProvider` implements the
`UploadDataProvider` interface. When Cronet is ready to send the request body,
`myUploadDataProvider.read(UploadDataSink uploadDataSink,
ByteBuffer byteBuffer)` will be invoked. The client will need to write the
request body into `byteBuffer`. Once the client is done writing into
`byteBuffer`, the client can let Cronet know by calling
`uploadDataSink.onReadSucceeded`. If the request body doesn't fit into
`byteBuffer`, the client can continue writing when `UploadDataProvider.read` is
invoked again. For more details, please see the API reference.

### <a id=configuring-cronet></a> Configuring Cronet
Various configuration options are available via the `UrlRequestContextConfig`
object.

Enabling HTTP/2, QUIC, or SDCH:

- For Example:

        myConfig.enableSPDY(true).enableQUIC(true).enableSDCH(true);

Controlling the cache:

- Use a 100KiB in-memory cache:

        myConfig.enableHttpCache(
                UrlRequestContextConfig.HttpCache.IN_MEMORY, 100 * 1024);

- or use a 1MiB disk cache:

        myConfig.setStoragePath(storagePathString);
        myConfig.enableHttpCache(UrlRequestContextConfig.HttpCache.DISK,
                1024 * 1024);

### Debugging
To get more information about how Cronet is processing network
requests, you can start and stop **NetLog** logging by calling
`UrlRequestContext.startNetLogToFile` and `UrlRequestContext.stopNetLog`.
Bear in mind that logs may contain sensitive data. You may analyze the
generated log by navigating to [chrome://net-internals#import] using a
Chrome browser.

# Using the java.net.HttpURLConnection API
Cronet offers an implementation of the [java.net.HttpURLConnection] API to make
it easier for apps which rely on this API to use Cronet.
To use Cronet's implementation instead of the system's default implementation,
simply do the following:

    CronetURLStreamHandlerFactory streamHandlerFactory =
            new CronetURLStreamHandlerFactory(getContext(), myConfig);
    URL.setURLStreamHandlerFactory(streamHandlerFactory);

Cronet's
HttpURLConnection implementation has some limitations as compared to the system
implementation, including not utilizing the default system HTTP cache (Please
see {@link org.chromium.net.urlconnection.CronetURLStreamHandlerFactory} for
more information).
You can configure Cronet and control caching through the
`UrlRequestContextConfig` instance, `myConfig`
(See [Configuring Cronet](#configuring-cronet) section), before you pass it
into the `CronetURLStreamHandlerFactory` constructor.

[ByteBuffer]: https://developer.android.com/reference/java/nio/ByteBuffer.html
[chrome://net-internals#import]: chrome://net-internals#import
[java.net.HttpURLConnection]: https://developer.android.com/reference/java/net/HttpURLConnection.html