diff options
author | tobrun <tobrun.van.nuland@gmail.com> | 2018-07-17 15:05:53 +0200 |
---|---|---|
committer | tobrun <tobrun.van.nuland@gmail.com> | 2018-08-24 11:27:29 +0200 |
commit | 367c53a0a977ea85235ee7a65226b5851bbacf5b (patch) | |
tree | 1531b9e643cf867618a56f522c6166efca858aeb /platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http | |
parent | cb1f781a1897826ea69eb9787ea4a059686450d9 (diff) | |
download | qtlocation-mapboxgl-367c53a0a977ea85235ee7a65226b5851bbacf5b.tar.gz |
[android] - modularise the sdkupstream/tvn-modules
Diffstat (limited to 'platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http')
9 files changed, 277 insertions, 286 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java deleted file mode 100644 index 9e3056bf8e..0000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java +++ /dev/null @@ -1,279 +0,0 @@ -package com.mapbox.mapboxsdk.http; - -import android.content.Context; -import android.content.pm.PackageInfo; -import android.os.Build; -import android.support.annotation.Keep; -import android.support.annotation.NonNull; -import android.text.TextUtils; -import android.util.Log; -import com.mapbox.android.telemetry.TelemetryUtils; -import com.mapbox.mapboxsdk.BuildConfig; -import com.mapbox.mapboxsdk.Mapbox; -import com.mapbox.mapboxsdk.constants.MapboxConstants; -import okhttp3.Call; -import okhttp3.Callback; -import okhttp3.Dispatcher; -import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import okhttp3.ResponseBody; -import timber.log.Timber; - -import javax.net.ssl.SSLException; -import java.io.IOException; -import java.io.InterruptedIOException; -import java.net.NoRouteToHostException; -import java.net.ProtocolException; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.util.concurrent.locks.ReentrantLock; - -import static android.util.Log.DEBUG; -import static android.util.Log.ERROR; -import static android.util.Log.INFO; -import static android.util.Log.VERBOSE; -import static android.util.Log.WARN; - -class HTTPRequest implements Callback { - - private static final int CONNECTION_ERROR = 0; - private static final int TEMPORARY_ERROR = 1; - private static final int PERMANENT_ERROR = 2; - - private static OkHttpClient client = new OkHttpClient.Builder().dispatcher(getDispatcher()).build(); - private static boolean logEnabled = true; - private static boolean logRequestUrl = false; - - // Reentrancy is not needed, but "Lock" is an abstract class. - private ReentrantLock lock = new ReentrantLock(); - private String userAgentString; - @Keep - private long nativePtr = 0; - private Call call; - - @Keep - private HTTPRequest(long nativePtr, String resourceUrl, String etag, String modified) { - this.nativePtr = nativePtr; - - if (resourceUrl.startsWith("local://")) { - // used by render test to serve files from assets - executeLocalRequest(resourceUrl); - return; - } - executeRequest(resourceUrl, etag, modified); - } - - @Keep - public void cancel() { - // call can be null if the constructor gets aborted (e.g, under a NoRouteToHostException). - if (call != null) { - call.cancel(); - } - - // TODO: We need a lock here because we can try - // to cancel at the same time the request is getting - // answered on the OkHTTP thread. We could get rid of - // this lock by using Runnable when we move Android - // implementation of mbgl::RunLoop to Looper. - lock.lock(); - nativePtr = 0; - lock.unlock(); - } - - @Override - public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { - if (response.isSuccessful()) { - log(VERBOSE, String.format("[HTTP] Request was successful (code = %s).", response.code())); - } else { - // We don't want to call this unsuccessful because a 304 isn't really an error - String message = !TextUtils.isEmpty(response.message()) ? response.message() : "No additional information"; - log(DEBUG, String.format("[HTTP] Request with response code = %s: %s", response.code(), message)); - } - - ResponseBody responseBody = response.body(); - if (responseBody == null) { - log(ERROR, "[HTTP] Received empty response body"); - return; - } - - byte[] body; - try { - body = responseBody.bytes(); - } catch (IOException ioException) { - onFailure(call, ioException); - // throw ioException; - return; - } finally { - response.close(); - } - - lock.lock(); - if (nativePtr != 0) { - nativeOnResponse(response.code(), - response.header("ETag"), - response.header("Last-Modified"), - response.header("Cache-Control"), - response.header("Expires"), - response.header("Retry-After"), - response.header("x-rate-limit-reset"), - body); - } - lock.unlock(); - } - - @Override - public void onFailure(@NonNull Call call, @NonNull IOException e) { - handleFailure(call, e); - } - - static void enableLog(boolean enabled) { - logEnabled = enabled; - } - - static void enablePrintRequestUrlOnFailure(boolean enabled) { - logRequestUrl = enabled; - } - - static void setOKHttpClient(OkHttpClient client) { - HTTPRequest.client = client; - } - - private static Dispatcher getDispatcher() { - Dispatcher dispatcher = new Dispatcher(); - // Matches core limit set on - // https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/src/http_file_source.cpp#L192 - dispatcher.setMaxRequestsPerHost(20); - return dispatcher; - } - - private void executeRequest(String resourceUrl, String etag, String modified) { - try { - HttpUrl httpUrl = HttpUrl.parse(resourceUrl); - if (httpUrl == null) { - log(Log.ERROR, String.format("[HTTP] Unable to parse resourceUrl %s", resourceUrl)); - } - - final String host = httpUrl.host().toLowerCase(MapboxConstants.MAPBOX_LOCALE); - // Don't try a request to remote server if we aren't connected - if (!Mapbox.isConnected() && !host.equals("127.0.0.1") && !host.equals("localhost")) { - throw new NoRouteToHostException("No Internet connection available."); - } - - if (host.equals("mapbox.com") || host.endsWith(".mapbox.com") || host.equals("mapbox.cn") - || host.endsWith(".mapbox.cn")) { - if (httpUrl.querySize() == 0) { - resourceUrl = resourceUrl + "?"; - } else { - resourceUrl = resourceUrl + "&"; - } - resourceUrl = resourceUrl + "events=true"; - } - - Request.Builder builder = new Request.Builder() - .url(resourceUrl) - .tag(resourceUrl.toLowerCase(MapboxConstants.MAPBOX_LOCALE)) - .addHeader("User-Agent", getUserAgent()); - if (etag.length() > 0) { - builder = builder.addHeader("If-None-Match", etag); - } else if (modified.length() > 0) { - builder = builder.addHeader("If-Modified-Since", modified); - } - Request request = builder.build(); - call = client.newCall(request); - call.enqueue(this); - } catch (Exception exception) { - handleFailure(call, exception); - } - } - - private void executeLocalRequest(String resourceUrl) { - new LocalRequestTask(new LocalRequestTask.OnLocalRequestResponse() { - @Override - public void onResponse(byte[] bytes) { - if (bytes != null) { - lock.lock(); - if (nativePtr != 0) { - nativeOnResponse(200, null, null, null, null, null, null, bytes); - } - lock.unlock(); - } - } - }).execute(resourceUrl); - } - - private void handleFailure(Call call, Exception e) { - String errorMessage = e.getMessage() != null ? e.getMessage() : "Error processing the request"; - int type = getFailureType(e); - - if (logEnabled && call != null && call.request() != null) { - String requestUrl = call.request().url().toString(); - logFailure(type, errorMessage, requestUrl); - } - - lock.lock(); - if (nativePtr != 0) { - nativeOnFailure(type, errorMessage); - } - lock.unlock(); - } - - private int getFailureType(Exception e) { - if ((e instanceof NoRouteToHostException) || (e instanceof UnknownHostException) || (e instanceof SocketException) - || (e instanceof ProtocolException) || (e instanceof SSLException)) { - return CONNECTION_ERROR; - } else if ((e instanceof InterruptedIOException)) { - return TEMPORARY_ERROR; - } - return PERMANENT_ERROR; - } - - private void log(int type, String errorMessage) { - if (logEnabled) { - Timber.log(type, errorMessage); - } - } - - private void logFailure(int type, String errorMessage, String requestUrl) { - log(type == TEMPORARY_ERROR ? DEBUG : type == CONNECTION_ERROR ? INFO : WARN, - String.format( - "Request failed due to a %s error: %s %s", - type == TEMPORARY_ERROR ? "temporary" : type == CONNECTION_ERROR ? "connection" : "permanent", - errorMessage, - logRequestUrl ? requestUrl : "" - ) - ); - } - - private String getUserAgent() { - if (userAgentString == null) { - userAgentString = TelemetryUtils.toHumanReadableAscii( - String.format("%s %s (%s) Android/%s (%s)", - getApplicationIdentifier(), - BuildConfig.MAPBOX_VERSION_STRING, - BuildConfig.GIT_REVISION_SHORT, - Build.VERSION.SDK_INT, - Build.CPU_ABI) - ); - } - return userAgentString; - } - - private String getApplicationIdentifier() { - try { - Context context = Mapbox.getApplicationContext(); - PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); - return String.format("%s/%s (%s)", context.getPackageName(), packageInfo.versionName, packageInfo.versionCode); - } catch (Exception exception) { - return ""; - } - } - - @Keep - private native void nativeOnFailure(int type, String message); - - @Keep - private native void nativeOnResponse(int code, String etag, String modified, String cacheControl, String expires, - String retryAfter, String xRateLimitReset, byte[] body); -} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpIdentifier.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpIdentifier.java new file mode 100644 index 0000000000..d50be55878 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpIdentifier.java @@ -0,0 +1,36 @@ +package com.mapbox.mapboxsdk.http; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.support.annotation.NonNull; +import com.mapbox.mapboxsdk.Mapbox; + +public class HttpIdentifier { + + private HttpIdentifier() { + } + + /** + * Returns the application identifier, consisting out the package name, version name and version code. + * + * @return the application identifier + */ + public static String getIdentifier() { + return getIdentifier(Mapbox.getApplicationContext()); + } + + /** + * Returns the application identifier, consisting out the package name, version name and version code. + * + * @param context the context used to retrieve the package manager from + * @return the application identifier + */ + private static String getIdentifier(@NonNull Context context) { + try { + PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); + return String.format("%s/%s (%s)", context.getPackageName(), packageInfo.versionName, packageInfo.versionCode); + } catch (Exception exception) { + return ""; + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpLogger.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpLogger.java new file mode 100644 index 0000000000..2f44694f0c --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpLogger.java @@ -0,0 +1,35 @@ +package com.mapbox.mapboxsdk.http; + +import android.util.Log; +import com.mapbox.mapboxsdk.log.Logger; + +import static com.mapbox.mapboxsdk.http.HttpRequest.CONNECTION_ERROR; +import static com.mapbox.mapboxsdk.http.HttpRequest.TEMPORARY_ERROR; + +public class HttpLogger { + + private static final String TAG = "Mbgl-HttpRequest"; + + public static boolean logRequestUrl; + public static boolean logEnabled = true; + + private HttpLogger(){ + } + + public static void logFailure(int type, String errorMessage, String requestUrl) { + log(type == TEMPORARY_ERROR ? Log.DEBUG : type == CONNECTION_ERROR ? Log.INFO : Log.WARN, + String.format( + "Request failed due to a %s error: %s %s", + type == TEMPORARY_ERROR ? "temporary" : type == CONNECTION_ERROR ? "connection" : "permanent", + errorMessage, + logRequestUrl ? requestUrl : "" + ) + ); + } + + public static void log(int type, String errorMessage) { + if (logEnabled) { + Logger.log(type, TAG, errorMessage); + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequest.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequest.java new file mode 100644 index 0000000000..fdbb589fef --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequest.java @@ -0,0 +1,31 @@ +package com.mapbox.mapboxsdk.http; + +/** + * Interface definition for performing http requests. + * <p> + * This allows to provide alternative implementations for the http interaction of this library. + * </p> + */ +public interface HttpRequest { + + int CONNECTION_ERROR = 0; + int TEMPORARY_ERROR = 1; + int PERMANENT_ERROR = 2; + + /** + * Executes the request. + * + * @param httpRequest callback to be invoked when we receive a response + * @param nativePtr the pointer associated to the request + * @param resourceUrl the resource url to download + * @param etag http header, identifier for a specific version of a resource + * @param modified http header, used to determine if a resource hasn't been modified since + */ + void executeRequest(HttpResponder httpRequest, long nativePtr, String resourceUrl, + String etag, String modified); + + /** + * Cancels the request. + */ + void cancelRequest(); +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestUrl.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestUrl.java new file mode 100644 index 0000000000..fde8ae4a5d --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestUrl.java @@ -0,0 +1,40 @@ +package com.mapbox.mapboxsdk.http; + +public class HttpRequestUrl { + + private HttpRequestUrl() { + } + + /** + * Adapts a resource request url based on the host and query size. + * + * @param host the host used as endpoint + * @param resourceUrl the resource to download + * @param querySize the query size of the resource request + * @return the adapted resource url + */ + public static String buildResourceUrl(String host, String resourceUrl, int querySize) { + if (isValidMapboxEndpoint(host)) { + if (querySize == 0) { + resourceUrl = resourceUrl + "?"; + } else { + resourceUrl = resourceUrl + "&"; + } + resourceUrl = resourceUrl + "events=true"; + } + return resourceUrl; + } + + /** + * Validates if the host used as endpoint is a valid Mapbox endpoint. + * + * @param host the host used as endpoint + * @return true if a valid Mapbox endpoint + */ + private static boolean isValidMapboxEndpoint(String host) { + return host.equals("mapbox.com") + || host.endsWith(".mapbox.com") + || host.equals("mapbox.cn") + || host.endsWith(".mapbox.cn"); + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestUtil.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestUtil.java index 872032867a..2b85555cc7 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestUtil.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestUtil.java @@ -3,8 +3,11 @@ package com.mapbox.mapboxsdk.http; import okhttp3.OkHttpClient; /** - * Utility class for setting HttpRequest configurations + * Utility class for setting HttpRequest configurations. + * + * @deprecated use {@link com.mapbox.mapboxsdk.module.http.HttpRequestUtil} instead */ +@Deprecated public class HttpRequestUtil { /** @@ -14,9 +17,11 @@ public class HttpRequestUtil { * </p> * * @param enabled True will enable logging, false will disable + * @deprecated use {@link com.mapbox.mapboxsdk.module.http.HttpRequestUtil#setLogEnabled(boolean)} instead */ + @Deprecated public static void setLogEnabled(boolean enabled) { - HTTPRequest.enableLog(enabled); + com.mapbox.mapboxsdk.module.http.HttpRequestUtil.setLogEnabled(enabled); } /** @@ -29,18 +34,22 @@ public class HttpRequestUtil { * </p> * * @param enabled True will print urls, false will disable + * @deprecated use {@link com.mapbox.mapboxsdk.module.http.HttpRequestUtil#setPrintRequestUrlOnFailure(boolean)} + * instead */ + @Deprecated public static void setPrintRequestUrlOnFailure(boolean enabled) { - HTTPRequest.enablePrintRequestUrlOnFailure(enabled); + com.mapbox.mapboxsdk.module.http.HttpRequestUtil.setPrintRequestUrlOnFailure(enabled); } /** * Set the OkHttpClient used for requesting map resources. * * @param client the OkHttpClient + * @deprecated use {@link com.mapbox.mapboxsdk.module.http.HttpRequestUtil#setOkHttpClient(OkHttpClient)} instead. */ + @Deprecated public static void setOkHttpClient(OkHttpClient client) { - HTTPRequest.setOKHttpClient(client); + com.mapbox.mapboxsdk.module.http.HttpRequestUtil.setOkHttpClient(client); } - }
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpResponder.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpResponder.java new file mode 100644 index 0000000000..a050e07c52 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpResponder.java @@ -0,0 +1,32 @@ +package com.mapbox.mapboxsdk.http; + +/** + * Interface definition for a callback to be invoked when either a response was returned for a requested resource or + * when an error occurred when requesting the resource. + */ +public interface HttpResponder { + + /** + * Invoked when a resource has finished. + * + * @param responseCode http response code + * @param eTag http header, identifier for a specific version of a resource + * @param lastModified http header, used to determine if a resource hasn't been modified since + * @param cacheControl http header, used to determine cache strategy of a resource + * @param expires http header, used to determine when a resource is stale + * @param retryAfter http header, used to indicate when the service is expected to be unavailable to the client + * @param xRateLimitReset http header, used to determine the remaining window before the rate limit resets + * @param body http response body, in an array of bytes representation + */ + void onResponse(int responseCode, String eTag, String lastModified, String cacheControl, String expires, + String retryAfter, String xRateLimitReset, byte[] body); + + /** + * Invoked when a resource failed to be retrieved. + * + * @param type the error type, either one of {@link HttpRequest#CONNECTION_ERROR}, + * {@link HttpRequest#TEMPORARY_ERROR} or {@link HttpRequest#PERMANENT_ERROR} + * @param errorMessage the error message associated with the failure + */ + void handleFailure(int type, String errorMessage); +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/LocalRequestTask.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/LocalRequestTask.java index 8f31364c39..b8ed407417 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/LocalRequestTask.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/LocalRequestTask.java @@ -3,13 +3,15 @@ package com.mapbox.mapboxsdk.http; import android.content.res.AssetManager; import android.os.AsyncTask; import com.mapbox.mapboxsdk.Mapbox; -import timber.log.Timber; +import com.mapbox.mapboxsdk.log.Logger; import java.io.IOException; import java.io.InputStream; class LocalRequestTask extends AsyncTask<String, Void, byte[]> { + private static final String TAG = "Mbgl-LocalRequestTask"; + private OnLocalRequestResponse requestResponse; LocalRequestTask(OnLocalRequestResponse requestResponse) { @@ -40,7 +42,7 @@ class LocalRequestTask extends AsyncTask<String, Void, byte[]> { buffer = new byte[size]; input.read(buffer); } catch (IOException exception) { - Timber.e(exception); + Logger.e(TAG, "Load file failed", exception); } return buffer; } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/NativeHttpRequest.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/NativeHttpRequest.java new file mode 100644 index 0000000000..5535e20923 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/NativeHttpRequest.java @@ -0,0 +1,85 @@ +package com.mapbox.mapboxsdk.http; + +import android.support.annotation.Keep; +import com.mapbox.mapboxsdk.Mapbox; + +import java.util.concurrent.locks.ReentrantLock; + +public class NativeHttpRequest implements HttpResponder { + + private final HttpRequest httpRequest = Mapbox.getModuleProvider().createHttpRequest(); + + // Reentrancy is not needed, but "Lock" is an abstract class. + private final ReentrantLock lock = new ReentrantLock(); + + @Keep + private long nativePtr; + + @Keep + private NativeHttpRequest(long nativePtr, String resourceUrl, String etag, String modified) { + this.nativePtr = nativePtr; + + if (resourceUrl.startsWith("local://")) { + // used by render test to serve files from assets + executeLocalRequest(resourceUrl); + return; + } + httpRequest.executeRequest(this, nativePtr, resourceUrl, etag, modified); + } + + public void cancel() { + httpRequest.cancelRequest(); + + // TODO: We need a lock here because we can try + // to cancel at the same time the request is getting + // answered on the OkHTTP thread. We could get rid of + // this lock by using Runnable when we move Android + // implementation of mbgl::RunLoop to Looper. + lock.lock(); + nativePtr = 0; + lock.unlock(); + } + + public void onResponse(int responseCode, String etag, String lastModified, String cacheControl, String expires, + String retryAfter, String xRateLimitReset, byte[] body) { + lock.lock(); + if (nativePtr != 0) { + nativeOnResponse(responseCode, + etag, + lastModified, + cacheControl, + expires, + retryAfter, + xRateLimitReset, + body); + } + lock.unlock(); + } + + private void executeLocalRequest(String resourceUrl) { + new LocalRequestTask(bytes -> { + if (bytes != null) { + lock.lock(); + if (nativePtr != 0) { + nativeOnResponse(200, null, null, null, null, null, null, bytes); + } + lock.unlock(); + } + }).execute(resourceUrl); + } + + public void handleFailure(int type, String errorMessage) { + lock.lock(); + if (nativePtr != 0) { + nativeOnFailure(type, errorMessage); + } + lock.unlock(); + } + + @Keep + private native void nativeOnFailure(int type, String message); + + @Keep + private native void nativeOnResponse(int code, String etag, String modified, String cacheControl, String expires, + String retryAfter, String xRateLimitReset, byte[] body); +} |