4
4
import android .content .Context ;
5
5
import android .content .pm .PackageInfo ;
6
6
import android .os .Build ;
7
+ import android .support .annotation .NonNull ;
7
8
import android .text .TextUtils ;
9
+ import android .util .Log ;
8
10
9
11
import com .mapbox .mapboxsdk .BuildConfig ;
10
12
import com .mapbox .mapboxsdk .Mapbox ;
27
29
import okhttp3 .OkHttpClient ;
28
30
import okhttp3 .Request ;
29
31
import okhttp3 .Response ;
32
+ import okhttp3 .ResponseBody ;
30
33
import okhttp3 .internal .Util ;
31
34
import timber .log .Timber ;
32
35
33
36
import static android .util .Log .DEBUG ;
37
+ import static android .util .Log .ERROR ;
34
38
import static android .util .Log .INFO ;
39
+ import static android .util .Log .VERBOSE ;
35
40
import static android .util .Log .WARN ;
36
41
37
42
class HTTPRequest implements Callback {
38
43
39
- private static OkHttpClient mClient = new OkHttpClient .Builder ().dispatcher (getDispatcher ()).build ();
40
- private static boolean logEnabled = true ;
41
- private static boolean logRequestUrl = false ;
42
-
43
- private String USER_AGENT_STRING = null ;
44
-
45
44
private static final int CONNECTION_ERROR = 0 ;
46
45
private static final int TEMPORARY_ERROR = 1 ;
47
46
private static final int PERMANENT_ERROR = 2 ;
48
47
49
- // Reentrancy is not needed, but "Lock" is an
50
- // abstract class.
51
- private ReentrantLock mLock = new ReentrantLock ();
52
-
53
- private long mNativePtr = 0 ;
54
-
55
- private Call mCall ;
56
- private Request mRequest ;
57
-
58
- private static Dispatcher getDispatcher () {
59
- Dispatcher dispatcher = new Dispatcher ();
60
- // Matches core limit set on
61
- // https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/src/http_file_source.cpp#L192
62
- dispatcher .setMaxRequestsPerHost (20 );
63
- return dispatcher ;
64
- }
65
-
66
- private native void nativeOnFailure (int type , String message );
48
+ private static OkHttpClient client = new OkHttpClient .Builder ().dispatcher (getDispatcher ()).build ();
49
+ private static boolean logEnabled = true ;
50
+ private static boolean logRequestUrl = false ;
67
51
68
- private native void nativeOnResponse (int code , String etag , String modified , String cacheControl , String expires ,
69
- String retryAfter , String xRateLimitReset , byte [] body );
52
+ // Reentrancy is not needed, but "Lock" is an abstract class.
53
+ private ReentrantLock lock = new ReentrantLock ();
54
+ private String userAgentString ;
55
+ private long nativePtr = 0 ;
56
+ private Call call ;
70
57
71
58
private HTTPRequest (long nativePtr , String resourceUrl , String etag , String modified ) {
72
- mNativePtr = nativePtr ;
59
+ this . nativePtr = nativePtr ;
73
60
74
61
try {
75
62
HttpUrl httpUrl = HttpUrl .parse (resourceUrl );
76
- final String host = httpUrl .host ().toLowerCase (MapboxConstants .MAPBOX_LOCALE );
63
+ if (httpUrl == null ) {
64
+ log (Log .ERROR , String .format ("[HTTP] Unable to parse resourceUrl %s" , resourceUrl ));
65
+ }
77
66
67
+ final String host = httpUrl .host ().toLowerCase (MapboxConstants .MAPBOX_LOCALE );
78
68
// Don't try a request to remote server if we aren't connected
79
69
if (!Mapbox .isConnected () && !host .equals ("127.0.0.1" ) && !host .equals ("localhost" )) {
80
70
throw new NoRouteToHostException ("No Internet connection available." );
@@ -99,56 +89,59 @@ private HTTPRequest(long nativePtr, String resourceUrl, String etag, String modi
99
89
} else if (modified .length () > 0 ) {
100
90
builder = builder .addHeader ("If-Modified-Since" , modified );
101
91
}
102
- mRequest = builder .build ();
103
- mCall = mClient .newCall (mRequest );
104
- mCall .enqueue (this );
92
+ Request request = builder .build ();
93
+ call = client .newCall (request );
94
+ call .enqueue (this );
105
95
} catch (Exception exception ) {
106
- handleFailure (mCall , exception );
96
+ handleFailure (call , exception );
107
97
}
108
98
}
109
99
110
100
public void cancel () {
111
- // mCall can be null if the constructor gets aborted (e.g, under a NoRouteToHostException).
112
- if (mCall != null ) {
113
- mCall .cancel ();
101
+ // call can be null if the constructor gets aborted (e.g, under a NoRouteToHostException).
102
+ if (call != null ) {
103
+ call .cancel ();
114
104
}
115
105
116
106
// TODO: We need a lock here because we can try
117
107
// to cancel at the same time the request is getting
118
108
// answered on the OkHTTP thread. We could get rid of
119
109
// this lock by using Runnable when we move Android
120
110
// implementation of mbgl::RunLoop to Looper.
121
- mLock .lock ();
122
- mNativePtr = 0 ;
123
- mLock .unlock ();
111
+ lock .lock ();
112
+ nativePtr = 0 ;
113
+ lock .unlock ();
124
114
}
125
115
126
116
@ Override
127
- public void onResponse (Call call , Response response ) throws IOException {
117
+ public void onResponse (@ NonNull Call call , @ NonNull Response response ) throws IOException {
118
+ if (response .isSuccessful ()) {
119
+ log (VERBOSE , String .format ("[HTTP] Request was successful (code = %s)." , response .code ()));
120
+ } else {
121
+ // We don't want to call this unsuccessful because a 304 isn't really an error
122
+ String message = !TextUtils .isEmpty (response .message ()) ? response .message () : "No additional information" ;
123
+ log (DEBUG , String .format ("[HTTP] Request with response code = %s: %s" , response .code (), message ));
124
+ }
128
125
129
- if (logEnabled ) {
130
- if (response .isSuccessful ()) {
131
- Timber .v ("[HTTP] Request was successful (code = %s)." , response .code ());
132
- } else {
133
- // We don't want to call this unsuccessful because a 304 isn't really an error
134
- String message = !TextUtils .isEmpty (response .message ()) ? response .message () : "No additional information" ;
135
- Timber .d ("[HTTP] Request with response code = %s: %s" , response .code (), message );
136
- }
126
+ ResponseBody responseBody = response .body ();
127
+ if (responseBody == null ) {
128
+ log (ERROR , "[HTTP] Received empty response body" );
129
+ return ;
137
130
}
138
131
139
132
byte [] body ;
140
133
try {
141
- body = response . body () .bytes ();
134
+ body = responseBody .bytes ();
142
135
} catch (IOException ioException ) {
143
136
onFailure (call , ioException );
144
137
// throw ioException;
145
138
return ;
146
139
} finally {
147
- response .body (). close ();
140
+ response .close ();
148
141
}
149
142
150
- mLock .lock ();
151
- if (mNativePtr != 0 ) {
143
+ lock .lock ();
144
+ if (nativePtr != 0 ) {
152
145
nativeOnResponse (response .code (),
153
146
response .header ("ETag" ),
154
147
response .header ("Last-Modified" ),
@@ -158,14 +151,34 @@ public void onResponse(Call call, Response response) throws IOException {
158
151
response .header ("x-rate-limit-reset" ),
159
152
body );
160
153
}
161
- mLock .unlock ();
154
+ lock .unlock ();
162
155
}
163
156
164
157
@ Override
165
- public void onFailure (Call call , IOException e ) {
158
+ public void onFailure (@ NonNull Call call , @ NonNull IOException e ) {
166
159
handleFailure (call , e );
167
160
}
168
161
162
+ static void enableLog (boolean enabled ) {
163
+ logEnabled = enabled ;
164
+ }
165
+
166
+ static void enablePrintRequestUrlOnFailure (boolean enabled ) {
167
+ logRequestUrl = enabled ;
168
+ }
169
+
170
+ static void setOKHttpClient (OkHttpClient client ) {
171
+ HTTPRequest .client = client ;
172
+ }
173
+
174
+ private static Dispatcher getDispatcher () {
175
+ Dispatcher dispatcher = new Dispatcher ();
176
+ // Matches core limit set on
177
+ // https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/src/http_file_source.cpp#L192
178
+ dispatcher .setMaxRequestsPerHost (20 );
179
+ return dispatcher ;
180
+ }
181
+
169
182
private void handleFailure (Call call , Exception e ) {
170
183
String errorMessage = e .getMessage () != null ? e .getMessage () : "Error processing the request" ;
171
184
int type = getFailureType (e );
@@ -175,11 +188,11 @@ private void handleFailure(Call call, Exception e) {
175
188
logFailure (type , errorMessage , requestUrl );
176
189
}
177
190
178
- mLock .lock ();
179
- if (mNativePtr != 0 ) {
191
+ lock .lock ();
192
+ if (nativePtr != 0 ) {
180
193
nativeOnFailure (type , errorMessage );
181
194
}
182
- mLock .unlock ();
195
+ lock .unlock ();
183
196
}
184
197
185
198
private int getFailureType (Exception e ) {
@@ -192,29 +205,35 @@ private int getFailureType(Exception e) {
192
205
return PERMANENT_ERROR ;
193
206
}
194
207
208
+ private void log (int type , String errorMessage ) {
209
+ if (logEnabled ) {
210
+ Timber .log (type , errorMessage );
211
+ }
212
+ }
213
+
195
214
private void logFailure (int type , String errorMessage , String requestUrl ) {
196
- Timber .log (
197
- type == TEMPORARY_ERROR ? DEBUG : type == CONNECTION_ERROR ? INFO : WARN ,
198
- "Request failed due to a %s error: %s %s" ,
199
- type == TEMPORARY_ERROR ? "temporary" : type == CONNECTION_ERROR ? "connection" : "permanent" ,
200
- errorMessage ,
201
- logRequestUrl ? requestUrl : ""
215
+ log (type == TEMPORARY_ERROR ? DEBUG : type == CONNECTION_ERROR ? INFO : WARN ,
216
+ String .format (
217
+ "Request failed due to a %s error: %s %s" ,
218
+ type == TEMPORARY_ERROR ? "temporary" : type == CONNECTION_ERROR ? "connection" : "permanent" ,
219
+ errorMessage ,
220
+ logRequestUrl ? requestUrl : ""
221
+ )
202
222
);
203
223
}
204
224
205
225
private String getUserAgent () {
206
- if (USER_AGENT_STRING == null ) {
207
- return USER_AGENT_STRING = Util .toHumanReadableAscii (
226
+ if (userAgentString == null ) {
227
+ userAgentString = Util .toHumanReadableAscii (
208
228
String .format ("%s %s (%s) Android/%s (%s)" ,
209
229
getApplicationIdentifier (),
210
230
BuildConfig .MAPBOX_VERSION_STRING ,
211
231
BuildConfig .GIT_REVISION_SHORT ,
212
232
Build .VERSION .SDK_INT ,
213
233
Build .CPU_ABI )
214
234
);
215
- } else {
216
- return USER_AGENT_STRING ;
217
235
}
236
+ return userAgentString ;
218
237
}
219
238
220
239
private String getApplicationIdentifier () {
@@ -227,15 +246,8 @@ private String getApplicationIdentifier() {
227
246
}
228
247
}
229
248
230
- static void enableLog (boolean enabled ) {
231
- logEnabled = enabled ;
232
- }
233
-
234
- static void enablePrintRequestUrlOnFailure (boolean enabled ) {
235
- logRequestUrl = enabled ;
236
- }
249
+ private native void nativeOnFailure (int type , String message );
237
250
238
- static void setOKHttpClient (OkHttpClient client ) {
239
- mClient = client ;
240
- }
251
+ private native void nativeOnResponse (int code , String etag , String modified , String cacheControl , String expires ,
252
+ String retryAfter , String xRateLimitReset , byte [] body );
241
253
}
0 commit comments