From f400615dc87c5583d5faabbb61287155ee500971 Mon Sep 17 00:00:00 2001 From: tobrun Date: Tue, 17 Jul 2018 15:05:53 +0200 Subject: [android] - modularise used http client --- .../android/MapboxGLAndroidModuleBase/.gitignore | 1 + .../android/MapboxGLAndroidModuleBase/build.gradle | 19 ++ .../src/main/AndroidManifest.xml | 1 + .../mapboxsdk/constants/MapboxConstants.java | 159 ++++++++++++ .../com/mapbox/mapboxsdk/http/HttpRequest.java | 57 +++++ .../mapboxsdk/http/HttpRequestResponder.java | 7 + .../mapboxsdk/utils/ApplicationContextWrapper.java | 20 ++ .../android/MapboxGLAndroidModuleHttp/.gitignore | 1 + .../android/MapboxGLAndroidModuleHttp/build.gradle | 29 +++ .../src/main/AndroidManifest.xml | 1 + .../com/mapbox/mapboxsdk/http/HttpRequestImpl.java | 186 ++++++++++++++ .../com/mapbox/mapboxsdk/http/HttpRequestUtil.java | 64 +++++ platform/android/MapboxGLAndroidSDK/build.gradle | 17 +- .../android/MapboxGLAndroidSDK/gradle.properties | 20 -- .../src/main/java/com/mapbox/mapboxsdk/Mapbox.java | 5 +- .../mapboxsdk/constants/MapboxConstants.java | 159 ------------ .../com/mapbox/mapboxsdk/http/HTTPRequest.java | 273 --------------------- .../com/mapbox/mapboxsdk/http/HttpRequestUtil.java | 46 ---- .../mapbox/mapboxsdk/http/NativeHttpRequest.java | 77 ++++++ .../mapbox/mapboxsdk/maps/MapGestureDetector.java | 18 +- .../java/com/mapbox/mapboxsdk/maps/MapView.java | 18 +- .../android/MapboxGLAndroidSDKTestApp/build.gradle | 13 +- .../com/mapbox/mapboxsdk/http/HttpRequestImpl.java | 39 +++ .../mapboxsdk/testapp/MapboxApplication.java | 5 +- .../activity/camera/LatLngBoundsActivity.java | 3 - .../activity/maplayout/DebugModeActivity.java | 3 - .../activity/render/RenderTestActivity.java | 24 +- platform/android/gradle.properties | 20 ++ platform/android/gradle/dependencies.gradle | 1 + platform/android/settings.gradle | 2 +- platform/android/src/http_file_source.cpp | 2 +- 31 files changed, 730 insertions(+), 560 deletions(-) create mode 100644 platform/android/MapboxGLAndroidModuleBase/.gitignore create mode 100644 platform/android/MapboxGLAndroidModuleBase/build.gradle create mode 100644 platform/android/MapboxGLAndroidModuleBase/src/main/AndroidManifest.xml create mode 100644 platform/android/MapboxGLAndroidModuleBase/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java create mode 100644 platform/android/MapboxGLAndroidModuleBase/src/main/java/com/mapbox/mapboxsdk/http/HttpRequest.java create mode 100644 platform/android/MapboxGLAndroidModuleBase/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestResponder.java create mode 100644 platform/android/MapboxGLAndroidModuleBase/src/main/java/com/mapbox/mapboxsdk/utils/ApplicationContextWrapper.java create mode 100644 platform/android/MapboxGLAndroidModuleHttp/.gitignore create mode 100644 platform/android/MapboxGLAndroidModuleHttp/build.gradle create mode 100644 platform/android/MapboxGLAndroidModuleHttp/src/main/AndroidManifest.xml create mode 100644 platform/android/MapboxGLAndroidModuleHttp/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestImpl.java create mode 100644 platform/android/MapboxGLAndroidModuleHttp/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestUtil.java delete mode 100644 platform/android/MapboxGLAndroidSDK/gradle.properties delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java delete mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestUtil.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/NativeHttpRequest.java create mode 100644 platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestImpl.java create mode 100644 platform/android/gradle.properties diff --git a/platform/android/MapboxGLAndroidModuleBase/.gitignore b/platform/android/MapboxGLAndroidModuleBase/.gitignore new file mode 100644 index 0000000000..796b96d1c4 --- /dev/null +++ b/platform/android/MapboxGLAndroidModuleBase/.gitignore @@ -0,0 +1 @@ +/build diff --git a/platform/android/MapboxGLAndroidModuleBase/build.gradle b/platform/android/MapboxGLAndroidModuleBase/build.gradle new file mode 100644 index 0000000000..58b150e867 --- /dev/null +++ b/platform/android/MapboxGLAndroidModuleBase/build.gradle @@ -0,0 +1,19 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion androidVersions.compileSdkVersion + + defaultConfig { + minSdkVersion androidVersions.minSdkVersion + targetSdkVersion androidVersions.targetSdkVersion + buildConfigField "String", "MAPBOX_VERSION_STRING", String.format("\"Mapbox/%s\"", project.VERSION_NAME) + buildConfigField "String", "MAPBOX_SDK_IDENTIFIER", String.format("\"%s\"", "mapbox-maps-android") + buildConfigField "String", "MAPBOX_SDK_VERSION", String.format("\"%s\"", project.VERSION_NAME) + versionCode 1 + versionName "1.0" + } + + dependencies { + implementation dependenciesList.supportAnnotations + } +} \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidModuleBase/src/main/AndroidManifest.xml b/platform/android/MapboxGLAndroidModuleBase/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..1ac48e6903 --- /dev/null +++ b/platform/android/MapboxGLAndroidModuleBase/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/platform/android/MapboxGLAndroidModuleBase/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java b/platform/android/MapboxGLAndroidModuleBase/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java new file mode 100644 index 0000000000..640c70282c --- /dev/null +++ b/platform/android/MapboxGLAndroidModuleBase/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java @@ -0,0 +1,159 @@ +package com.mapbox.mapboxsdk.constants; + +import java.util.Locale; + +/** + * MapboxConstants exposes Mapbox related constants + */ +public class MapboxConstants { + + /** + * Default Locale for data processing (ex: String.toLowerCase(MAPBOX_LOCALE, "foo")) + */ + public static final Locale MAPBOX_LOCALE = Locale.US; + + /** + * Key used to switch storage to external in AndroidManifest.xml + */ + public static final String KEY_META_DATA_SET_STORAGE_EXTERNAL = "com.mapbox.SetStorageExternal"; + + /** + * Default value for KEY_META_DATA_SET_STORAGE_EXTERNAL (default is internal storage) + */ + public static final boolean DEFAULT_SET_STORAGE_EXTERNAL = false; + + /** + * Unmeasured state + */ + public static final float UNMEASURED = -1f; + + /** + * Default animation time + */ + public static final int ANIMATION_DURATION = 300; + + /** + * Default short animation time + */ + public static final int ANIMATION_DURATION_SHORT = 150; + + /** + * Animation time of a fling gesture + */ + public static final long ANIMATION_DURATION_FLING_BASE = ANIMATION_DURATION_SHORT; + + /** + * Velocity threshold for a fling gesture + */ + public static final long VELOCITY_THRESHOLD_IGNORE_FLING = 1000; + + /** + * Value by which the default rotation threshold will be increased when scaling + */ + public static final float ROTATION_THRESHOLD_INCREASE_WHEN_SCALING = 25f; + + /** + * Time within which user needs to lift fingers for velocity animation to start. + */ + public static final long SCHEDULED_ANIMATION_TIMEOUT = 150L; + + /** + * Minimum angular velocity for rotation animation + */ + public static final float MINIMUM_ANGULAR_VELOCITY = 1.5f; + + /** + * Maximum angular velocity for rotation animation + */ + public static final float MAXIMUM_ANGULAR_VELOCITY = 20f; + + /** + * Factor to calculate tilt change based on pixel change during shove gesture. + */ + public static final float SHOVE_PIXEL_CHANGE_FACTOR = 0.1f; + + /** + * The currently supported minimum zoom level. + */ + public static final float MINIMUM_ZOOM = 0.0f; + + /** + * The currently supported maximum zoom level. + */ + public static final float MAXIMUM_ZOOM = 25.5f; + + /** + * The currently supported maximum tilt value. + */ + public static final double MAXIMUM_TILT = 60; + + /** + * The currently supported minimum tilt value. + */ + public static final double MINIMUM_TILT = 0; + + /** + * The currently supported maximum direction + */ + public static final double MAXIMUM_DIRECTION = 360; + + /** + * The currently supported minimum direction + */ + public static final double MINIMUM_DIRECTION = 0; + + /** + * The currently used minimum scale factor to clamp to when a quick zoom gesture occurs + */ + public static final float MINIMUM_SCALE_FACTOR_CLAMP = 0.00f; + + /** + * The currently used maximum scale factor to clamp to when a quick zoom gesture occurs + */ + public static final float MAXIMUM_SCALE_FACTOR_CLAMP = 0.15f; + + /** + * Fragment Argument Key for MapboxMapOptions + */ + public static final String FRAG_ARG_MAPBOXMAPOPTIONS = "MapboxMapOptions"; + + // Save instance state keys + public static final String STATE_HAS_SAVED_STATE = "mapbox_savedState"; + public static final String STATE_CAMERA_POSITION = "mapbox_cameraPosition"; + public static final String STATE_ZOOM_ENABLED = "mapbox_zoomEnabled"; + public static final String STATE_SCROLL_ENABLED = "mapbox_scrollEnabled"; + public static final String STATE_ROTATE_ENABLED = "mapbox_rotateEnabled"; + public static final String STATE_TILT_ENABLED = "mapbox_tiltEnabled"; + public static final String STATE_ZOOM_CONTROLS_ENABLED = "mapbox_zoomControlsEnabled"; + public static final String STATE_DOUBLE_TAP_ENABLED = "mapbox_doubleTapEnabled"; + public static final String STATE_DEBUG_ACTIVE = "mapbox_debugActive"; + public static final String STATE_STYLE_URL = "mapbox_styleUrl"; + public static final String STATE_COMPASS_ENABLED = "mapbox_compassEnabled"; + public static final String STATE_COMPASS_GRAVITY = "mapbox_compassGravity"; + public static final String STATE_COMPASS_MARGIN_LEFT = "mapbox_compassMarginLeft"; + public static final String STATE_COMPASS_MARGIN_TOP = "mapbox_compassMarginTop"; + public static final String STATE_COMPASS_MARGIN_RIGHT = "mapbox_compassMarginRight"; + public static final String STATE_COMPASS_MARGIN_BOTTOM = "mapbox_compassMarginBottom"; + public static final String STATE_COMPASS_FADE_WHEN_FACING_NORTH = "mapbox_compassFade"; + public static final String STATE_COMPASS_IMAGE_BITMAP = "mapbox_compassImage"; + public static final String STATE_LOGO_GRAVITY = "mapbox_logoGravity"; + public static final String STATE_LOGO_MARGIN_LEFT = "mapbox_logoMarginLeft"; + public static final String STATE_LOGO_MARGIN_TOP = "mapbox_logoMarginTop"; + public static final String STATE_LOGO_MARGIN_RIGHT = "mapbox_logoMarginRight"; + public static final String STATE_LOGO_MARGIN_BOTTOM = "mapbox_logoMarginBottom"; + public static final String STATE_LOGO_ENABLED = "mapbox_logoEnabled"; + public static final String STATE_ATTRIBUTION_GRAVITY = "mapbox_attrGravity"; + public static final String STATE_ATTRIBUTION_MARGIN_LEFT = "mapbox_attrMarginLeft"; + public static final String STATE_ATTRIBUTION_MARGIN_TOP = "mapbox_attrMarginTop"; + public static final String STATE_ATTRIBUTION_MARGIN_RIGHT = "mapbox_attrMarginRight"; + public static final String STATE_ATTRIBUTION_MARGIN_BOTTOM = "mapbox_atrrMarginBottom"; + public static final String STATE_ATTRIBUTION_ENABLED = "mapbox_atrrEnabled"; + public static final String STATE_DESELECT_MARKER_ON_TAP = "mapbox_deselectMarkerOnTap"; + public static final String STATE_USER_FOCAL_POINT = "mapbox_userFocalPoint"; + public static final String STATE_SCALE_ANIMATION_ENABLED = "mapbox_scaleAnimationEnabled"; + public static final String STATE_ROTATE_ANIMATION_ENABLED = "mapbox_rotateAnimationEnabled"; + public static final String STATE_FLING_ANIMATION_ENABLED = "mapbox_flingAnimationEnabled"; + public static final String STATE_INCREASE_ROTATE_THRESHOLD = "mapbox_increaseRotateThreshold"; + public static final String STATE_INCREASE_SCALE_THRESHOLD = "mapbox_increaseScaleThreshold"; + +} diff --git a/platform/android/MapboxGLAndroidModuleBase/src/main/java/com/mapbox/mapboxsdk/http/HttpRequest.java b/platform/android/MapboxGLAndroidModuleBase/src/main/java/com/mapbox/mapboxsdk/http/HttpRequest.java new file mode 100644 index 0000000000..072a45b0de --- /dev/null +++ b/platform/android/MapboxGLAndroidModuleBase/src/main/java/com/mapbox/mapboxsdk/http/HttpRequest.java @@ -0,0 +1,57 @@ +package com.mapbox.mapboxsdk.http; + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.support.annotation.NonNull; +import com.mapbox.mapboxsdk.utils.ApplicationContextWrapper; + +public abstract class HttpRequest { + + static final int CONNECTION_ERROR = 0; + static final int TEMPORARY_ERROR = 1; + static final int PERMANENT_ERROR = 2; + + public abstract void executeRequest(HttpRequestResponder httpRequest, long nativePtr, String resourceUrl, + String etag, String modified); + + public abstract void cancelRequest(); + + // + // Utility methods + // + + static String getApplicationIdentifier() { + ApplicationContextWrapper contextWrapper = ApplicationContextWrapper.getInstance(null); + Context context = contextWrapper.getBaseContext(); + if(context == null){ + throw new RuntimeException("Mapbox.java not correctly initialized"); + } + return getApplicationIdentifier(context); + } + + private static String getApplicationIdentifier(@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 ""; + } + } + + 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; + } + + private 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/MapboxGLAndroidModuleBase/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestResponder.java b/platform/android/MapboxGLAndroidModuleBase/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestResponder.java new file mode 100644 index 0000000000..e4659e0955 --- /dev/null +++ b/platform/android/MapboxGLAndroidModuleBase/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestResponder.java @@ -0,0 +1,7 @@ +package com.mapbox.mapboxsdk.http; + +public interface HttpRequestResponder { + void onResponse(int responseCode, String eTag, String lastModified, String cacheControl, String expires, + String retryAfter, String xRateLimitReset, byte[] body); + void handleFailure(int type, String errorMessage); +} diff --git a/platform/android/MapboxGLAndroidModuleBase/src/main/java/com/mapbox/mapboxsdk/utils/ApplicationContextWrapper.java b/platform/android/MapboxGLAndroidModuleBase/src/main/java/com/mapbox/mapboxsdk/utils/ApplicationContextWrapper.java new file mode 100644 index 0000000000..8981a0f2e2 --- /dev/null +++ b/platform/android/MapboxGLAndroidModuleBase/src/main/java/com/mapbox/mapboxsdk/utils/ApplicationContextWrapper.java @@ -0,0 +1,20 @@ +package com.mapbox.mapboxsdk.utils; + +import android.content.Context; +import android.content.ContextWrapper; + +public class ApplicationContextWrapper extends ContextWrapper { + + private static ApplicationContextWrapper instance; + + public static synchronized ApplicationContextWrapper getInstance(Context context) { + if (instance == null) { + instance = new ApplicationContextWrapper(context); + } + return instance; + } + + private ApplicationContextWrapper(Context base) { + super(base.getApplicationContext()); + } +} diff --git a/platform/android/MapboxGLAndroidModuleHttp/.gitignore b/platform/android/MapboxGLAndroidModuleHttp/.gitignore new file mode 100644 index 0000000000..796b96d1c4 --- /dev/null +++ b/platform/android/MapboxGLAndroidModuleHttp/.gitignore @@ -0,0 +1 @@ +/build diff --git a/platform/android/MapboxGLAndroidModuleHttp/build.gradle b/platform/android/MapboxGLAndroidModuleHttp/build.gradle new file mode 100644 index 0000000000..c31f28b1e1 --- /dev/null +++ b/platform/android/MapboxGLAndroidModuleHttp/build.gradle @@ -0,0 +1,29 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion androidVersions.compileSdkVersion + + defaultConfig { + minSdkVersion androidVersions.minSdkVersion + targetSdkVersion androidVersions.targetSdkVersion + versionCode 1 + versionName "1.0" + buildConfigField "String", "GIT_REVISION_SHORT", String.format("\"%s\"", getGitRevision()) + buildConfigField "String", "MAPBOX_VERSION_STRING", String.format("\"Mapbox/%s\"", project.VERSION_NAME) + } +} + +dependencies { + api(project(':MapboxGLAndroidModuleBase')) + implementation dependenciesList.okhttp3 + implementation dependenciesList.supportAnnotations + implementation dependenciesList.timber +} + +def static getGitRevision() { + def cmd = "git rev-parse --short HEAD" + def proc = cmd.execute() + def ref = proc.text.trim() + return ref +} + diff --git a/platform/android/MapboxGLAndroidModuleHttp/src/main/AndroidManifest.xml b/platform/android/MapboxGLAndroidModuleHttp/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..bb66132347 --- /dev/null +++ b/platform/android/MapboxGLAndroidModuleHttp/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/platform/android/MapboxGLAndroidModuleHttp/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestImpl.java b/platform/android/MapboxGLAndroidModuleHttp/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestImpl.java new file mode 100644 index 0000000000..c562f1b147 --- /dev/null +++ b/platform/android/MapboxGLAndroidModuleHttp/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestImpl.java @@ -0,0 +1,186 @@ +package com.mapbox.mapboxsdk.http; + +import android.os.Build; +import android.support.annotation.NonNull; +import android.text.TextUtils; +import android.util.Log; +import com.mapbox.mapboxsdk.constants.MapboxConstants; +import okhttp3.*; +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 static com.mapbox.mapboxsdk.http.HttpRequestUtil.toHumanReadableAscii; + +public class HttpRequestImpl extends HttpRequest { + + private static final String userAgentString = 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) + ); + + private static OkHttpClient client = new OkHttpClient.Builder().dispatcher(getDispatcher()).build(); + private static boolean logEnabled = true; + private static boolean logRequestUrl = false; + + private Call call; + + @Override + public void executeRequest(HttpRequestResponder httpRequest, long nativePtr, String resourceUrl, + String etag, String modified) { + OkHttpCallback callback = new OkHttpCallback(httpRequest); + try { + HttpUrl httpUrl = HttpUrl.parse(resourceUrl); + if (httpUrl == null) { + log(Log.ERROR, String.format("[HTTP] Unable to parse resourceUrl %s", resourceUrl)); + return; + } + + final String host = httpUrl.host().toLowerCase(MapboxConstants.MAPBOX_LOCALE); + resourceUrl = buildResourceUrl(host, resourceUrl, httpUrl.querySize()); + + final Request.Builder builder = new Request.Builder() + .url(resourceUrl) + .tag(resourceUrl.toLowerCase(MapboxConstants.MAPBOX_LOCALE)) + .addHeader("User-Agent", userAgentString); + if (etag.length() > 0) { + builder.addHeader("If-None-Match", etag); + } else if (modified.length() > 0) { + builder.addHeader("If-Modified-Since", modified); + } + + final Request request = builder.build(); + call = client.newCall(request); + call.enqueue(callback); + } catch (Exception exception) { + callback.handleFailure(call, exception); + } + } + + @Override + public void cancelRequest() { + // call can be null if the constructor gets aborted (e.g, under a NoRouteToHostException). + if (call != null) { + call.cancel(); + } + } + + public static void enablePrintRequestUrlOnFailure(boolean enabled) { + logRequestUrl = enabled; + } + + public static void enableLog(boolean enabled) { + logEnabled = enabled; + } + + public static void setOkHttpClient(OkHttpClient okHttpClient) { + HttpRequestImpl.client = okHttpClient; + } + + private static class OkHttpCallback implements Callback { + + private HttpRequestResponder httpRequest; + + OkHttpCallback(HttpRequestResponder httpRequest) { + this.httpRequest = httpRequest; + } + + @Override + public void onFailure(@NonNull Call call, @NonNull IOException e) { + handleFailure(call, e); + } + + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) { + if (response.isSuccessful()) { + log(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(Log.DEBUG, String.format("[HTTP] Request with response code = %s: %s", response.code(), message)); + } + + ResponseBody responseBody = response.body(); + if (responseBody == null) { + log(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(); + } + + httpRequest.onResponse(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); + } + + 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); + } + httpRequest.handleFailure(type, errorMessage); + } + + private 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 : "" + ) + ); + } + + 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 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; + } + + static void log(int type, String errorMessage) { + if (logEnabled) { + Timber.log(type, errorMessage); + } + } +} \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidModuleHttp/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestUtil.java b/platform/android/MapboxGLAndroidModuleHttp/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestUtil.java new file mode 100644 index 0000000000..d8b9591a63 --- /dev/null +++ b/platform/android/MapboxGLAndroidModuleHttp/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestUtil.java @@ -0,0 +1,64 @@ +package com.mapbox.mapboxsdk.http; + +import okhttp3.OkHttpClient; +import okio.Buffer; + +/** + * Utility class for setting OkHttpRequest configurations + */ +public class HttpRequestUtil { + + /** + * Set the log state of OkHttpRequest. Default value is true. + *

+ * This configuration will outlast the lifecycle of the Map. + *

+ * + * @param enabled True will enable logging, false will disable + */ + public static void setLogEnabled(boolean enabled) { + HttpRequestImpl.enableLog(enabled); + } + + /** + * Enable printing of the request url when an error occurred. Default value is false. + *

+ * Requires {@link #setLogEnabled(boolean)} to be activated. + *

+ *

+ * This configuration will outlast the lifecycle of the Map. + *

+ * + * @param enabled True will print urls, false will disable + */ + public static void setPrintRequestUrlOnFailure(boolean enabled) { + HttpRequestImpl.enablePrintRequestUrlOnFailure(enabled); + } + + /** + * Set the OkHttpClient used for requesting map resources. + * + * @param client the OkHttpClient + */ + public static void setOkHttpClient(OkHttpClient client) { + HttpRequestImpl.setOkHttpClient(client); + } + + static String toHumanReadableAscii(String s) { + for (int i = 0, length = s.length(), c; i < length; i += Character.charCount(c)) { + c = s.codePointAt(i); + if (c > '\u001f' && c < '\u007f') { + continue; + } + + Buffer buffer = new Buffer(); + buffer.writeUtf8(s, 0, i); + for (int j = i; j < length; j += Character.charCount(c)) { + c = s.codePointAt(j); + buffer.writeUtf8CodePoint(c > '\u001f' && c < '\u007f' ? c : '?'); + } + return buffer.readUtf8(); + } + return s; + } +} \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/build.gradle b/platform/android/MapboxGLAndroidSDK/build.gradle index 35b4de003b..7ad3314821 100644 --- a/platform/android/MapboxGLAndroidSDK/build.gradle +++ b/platform/android/MapboxGLAndroidSDK/build.gradle @@ -2,6 +2,9 @@ apply plugin: 'com.android.library' apply plugin: "com.jaredsburrows.license" dependencies { + api(project(':MapboxGLAndroidModuleBase')) + api(project(':MapboxGLAndroidModuleHttp')) + api (dependenciesList.mapboxAndroidTelemetry) { exclude group: 'com.android.support', module: 'appcompat-v7' } @@ -11,8 +14,8 @@ dependencies { } implementation dependenciesList.supportAnnotations implementation dependenciesList.supportFragmentV4 + implementation dependenciesList.supportUtilV4 implementation dependenciesList.timber - implementation dependenciesList.okhttp3 testImplementation dependenciesList.junit testImplementation dependenciesList.mockito testImplementation dependenciesList.robolectric @@ -25,15 +28,12 @@ android { defaultConfig { minSdkVersion androidVersions.minSdkVersion targetSdkVersion androidVersions.targetSdkVersion - buildConfigField "String", "GIT_REVISION_SHORT", String.format("\"%s\"", getGitRevision()) - buildConfigField "String", "MAPBOX_SDK_IDENTIFIER", String.format("\"%s\"", "mapbox-maps-android") - buildConfigField "String", "MAPBOX_SDK_VERSION", String.format("\"%s\"", project.VERSION_NAME) - buildConfigField "String", "MAPBOX_VERSION_STRING", String.format("\"Mapbox/%s\"", project.VERSION_NAME) buildConfigField "String", "MAPBOX_EVENTS_USER_AGENT", String.format("\"MapboxEventsAndroid/%s\"", project.VERSION_NAME) } defaultPublishConfig project.hasProperty("mapbox.buildtype") ? project.getProperty("mapbox.buildtype") : "debug" + // We sometimes want to invoke Gradle without building a native dependency, e.g. when we just want // to invoke the Java tests. When we explicitly specify an ABI of 'none', no native dependencies are // added. When another ABI is specified explicitly, we're just going to build that ABI. In all other @@ -142,13 +142,6 @@ licenseReport { copyJsonReportToAssets = false } -def static getGitRevision() { - def cmd = "git rev-parse --short HEAD" - def proc = cmd.execute() - def ref = proc.text.trim() - return ref -} - configurations { all*.exclude group: 'commons-logging', module: 'commons-logging' all*.exclude group: 'commons-collections', module: 'commons-collections' diff --git a/platform/android/MapboxGLAndroidSDK/gradle.properties b/platform/android/MapboxGLAndroidSDK/gradle.properties deleted file mode 100644 index 77a93829f9..0000000000 --- a/platform/android/MapboxGLAndroidSDK/gradle.properties +++ /dev/null @@ -1,20 +0,0 @@ -GROUP=com.mapbox.mapboxsdk -VERSION_NAME=6.4.0-SNAPSHOT - -POM_DESCRIPTION=Mapbox GL Android SDK -POM_URL=https://github.com/mapbox/mapbox-gl-native -POM_SCM_URL=https://github.com/mapbox/mapbox-gl-native -POM_SCM_CONNECTION=scm:git@github.com:mapbox/mapbox-gl-native.git -POM_SCM_DEV_CONNECTION=scm:git@github.com:mapbox/mapbox-gl-native.git -POM_LICENCE_NAME=The Apache Software License, Version 2.0 -POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt -POM_LICENCE_DIST=repo -POM_DEVELOPER_ID=mapbox -POM_DEVELOPER_NAME=Mapbox -POM_NAME=Mapbox Maps SDK for Android -POM_ARTIFACT_ID=mapbox-android-sdk -POM_PACKAGING=aar - -# Only build native dependencies for the current ABI -# See https://code.google.com/p/android/issues/detail?id=221098#c20 -android.buildOnlyTargetAbi=true diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java index a809460375..8d208fc232 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java @@ -12,6 +12,8 @@ import com.mapbox.mapboxsdk.constants.MapboxConstants; import com.mapbox.mapboxsdk.exceptions.MapboxConfigurationException; import com.mapbox.mapboxsdk.maps.Telemetry; import com.mapbox.mapboxsdk.net.ConnectivityReceiver; + +import com.mapbox.mapboxsdk.utils.ApplicationContextWrapper; import timber.log.Timber; /** @@ -45,9 +47,10 @@ public final class Mapbox { public static synchronized Mapbox getInstance(@NonNull Context context, @Nullable String accessToken) { if (INSTANCE == null) { Context appContext = context.getApplicationContext(); + ApplicationContextWrapper.getInstance(appContext); INSTANCE = new Mapbox(appContext, accessToken); if (isAccessTokenValid(accessToken)) { - initializeTelemetry(); + //initializeTelemetry(); } ConnectivityReceiver.instance(appContext); } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java deleted file mode 100644 index 640c70282c..0000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java +++ /dev/null @@ -1,159 +0,0 @@ -package com.mapbox.mapboxsdk.constants; - -import java.util.Locale; - -/** - * MapboxConstants exposes Mapbox related constants - */ -public class MapboxConstants { - - /** - * Default Locale for data processing (ex: String.toLowerCase(MAPBOX_LOCALE, "foo")) - */ - public static final Locale MAPBOX_LOCALE = Locale.US; - - /** - * Key used to switch storage to external in AndroidManifest.xml - */ - public static final String KEY_META_DATA_SET_STORAGE_EXTERNAL = "com.mapbox.SetStorageExternal"; - - /** - * Default value for KEY_META_DATA_SET_STORAGE_EXTERNAL (default is internal storage) - */ - public static final boolean DEFAULT_SET_STORAGE_EXTERNAL = false; - - /** - * Unmeasured state - */ - public static final float UNMEASURED = -1f; - - /** - * Default animation time - */ - public static final int ANIMATION_DURATION = 300; - - /** - * Default short animation time - */ - public static final int ANIMATION_DURATION_SHORT = 150; - - /** - * Animation time of a fling gesture - */ - public static final long ANIMATION_DURATION_FLING_BASE = ANIMATION_DURATION_SHORT; - - /** - * Velocity threshold for a fling gesture - */ - public static final long VELOCITY_THRESHOLD_IGNORE_FLING = 1000; - - /** - * Value by which the default rotation threshold will be increased when scaling - */ - public static final float ROTATION_THRESHOLD_INCREASE_WHEN_SCALING = 25f; - - /** - * Time within which user needs to lift fingers for velocity animation to start. - */ - public static final long SCHEDULED_ANIMATION_TIMEOUT = 150L; - - /** - * Minimum angular velocity for rotation animation - */ - public static final float MINIMUM_ANGULAR_VELOCITY = 1.5f; - - /** - * Maximum angular velocity for rotation animation - */ - public static final float MAXIMUM_ANGULAR_VELOCITY = 20f; - - /** - * Factor to calculate tilt change based on pixel change during shove gesture. - */ - public static final float SHOVE_PIXEL_CHANGE_FACTOR = 0.1f; - - /** - * The currently supported minimum zoom level. - */ - public static final float MINIMUM_ZOOM = 0.0f; - - /** - * The currently supported maximum zoom level. - */ - public static final float MAXIMUM_ZOOM = 25.5f; - - /** - * The currently supported maximum tilt value. - */ - public static final double MAXIMUM_TILT = 60; - - /** - * The currently supported minimum tilt value. - */ - public static final double MINIMUM_TILT = 0; - - /** - * The currently supported maximum direction - */ - public static final double MAXIMUM_DIRECTION = 360; - - /** - * The currently supported minimum direction - */ - public static final double MINIMUM_DIRECTION = 0; - - /** - * The currently used minimum scale factor to clamp to when a quick zoom gesture occurs - */ - public static final float MINIMUM_SCALE_FACTOR_CLAMP = 0.00f; - - /** - * The currently used maximum scale factor to clamp to when a quick zoom gesture occurs - */ - public static final float MAXIMUM_SCALE_FACTOR_CLAMP = 0.15f; - - /** - * Fragment Argument Key for MapboxMapOptions - */ - public static final String FRAG_ARG_MAPBOXMAPOPTIONS = "MapboxMapOptions"; - - // Save instance state keys - public static final String STATE_HAS_SAVED_STATE = "mapbox_savedState"; - public static final String STATE_CAMERA_POSITION = "mapbox_cameraPosition"; - public static final String STATE_ZOOM_ENABLED = "mapbox_zoomEnabled"; - public static final String STATE_SCROLL_ENABLED = "mapbox_scrollEnabled"; - public static final String STATE_ROTATE_ENABLED = "mapbox_rotateEnabled"; - public static final String STATE_TILT_ENABLED = "mapbox_tiltEnabled"; - public static final String STATE_ZOOM_CONTROLS_ENABLED = "mapbox_zoomControlsEnabled"; - public static final String STATE_DOUBLE_TAP_ENABLED = "mapbox_doubleTapEnabled"; - public static final String STATE_DEBUG_ACTIVE = "mapbox_debugActive"; - public static final String STATE_STYLE_URL = "mapbox_styleUrl"; - public static final String STATE_COMPASS_ENABLED = "mapbox_compassEnabled"; - public static final String STATE_COMPASS_GRAVITY = "mapbox_compassGravity"; - public static final String STATE_COMPASS_MARGIN_LEFT = "mapbox_compassMarginLeft"; - public static final String STATE_COMPASS_MARGIN_TOP = "mapbox_compassMarginTop"; - public static final String STATE_COMPASS_MARGIN_RIGHT = "mapbox_compassMarginRight"; - public static final String STATE_COMPASS_MARGIN_BOTTOM = "mapbox_compassMarginBottom"; - public static final String STATE_COMPASS_FADE_WHEN_FACING_NORTH = "mapbox_compassFade"; - public static final String STATE_COMPASS_IMAGE_BITMAP = "mapbox_compassImage"; - public static final String STATE_LOGO_GRAVITY = "mapbox_logoGravity"; - public static final String STATE_LOGO_MARGIN_LEFT = "mapbox_logoMarginLeft"; - public static final String STATE_LOGO_MARGIN_TOP = "mapbox_logoMarginTop"; - public static final String STATE_LOGO_MARGIN_RIGHT = "mapbox_logoMarginRight"; - public static final String STATE_LOGO_MARGIN_BOTTOM = "mapbox_logoMarginBottom"; - public static final String STATE_LOGO_ENABLED = "mapbox_logoEnabled"; - public static final String STATE_ATTRIBUTION_GRAVITY = "mapbox_attrGravity"; - public static final String STATE_ATTRIBUTION_MARGIN_LEFT = "mapbox_attrMarginLeft"; - public static final String STATE_ATTRIBUTION_MARGIN_TOP = "mapbox_attrMarginTop"; - public static final String STATE_ATTRIBUTION_MARGIN_RIGHT = "mapbox_attrMarginRight"; - public static final String STATE_ATTRIBUTION_MARGIN_BOTTOM = "mapbox_atrrMarginBottom"; - public static final String STATE_ATTRIBUTION_ENABLED = "mapbox_atrrEnabled"; - public static final String STATE_DESELECT_MARKER_ON_TAP = "mapbox_deselectMarkerOnTap"; - public static final String STATE_USER_FOCAL_POINT = "mapbox_userFocalPoint"; - public static final String STATE_SCALE_ANIMATION_ENABLED = "mapbox_scaleAnimationEnabled"; - public static final String STATE_ROTATE_ANIMATION_ENABLED = "mapbox_rotateAnimationEnabled"; - public static final String STATE_FLING_ANIMATION_ENABLED = "mapbox_flingAnimationEnabled"; - public static final String STATE_INCREASE_ROTATE_THRESHOLD = "mapbox_increaseRotateThreshold"; - public static final String STATE_INCREASE_SCALE_THRESHOLD = "mapbox_increaseScaleThreshold"; - -} 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 e0c63944b9..0000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java +++ /dev/null @@ -1,273 +0,0 @@ -package com.mapbox.mapboxsdk.http; - -import android.content.Context; -import android.content.pm.PackageInfo; -import android.os.Build; -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; - private long nativePtr = 0; - private Call call; - - 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); - } - - 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 ""; - } - } - - private native void nativeOnFailure(int type, String message); - - 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/HttpRequestUtil.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestUtil.java deleted file mode 100644 index 872032867a..0000000000 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestUtil.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.mapbox.mapboxsdk.http; - -import okhttp3.OkHttpClient; - -/** - * Utility class for setting HttpRequest configurations - */ -public class HttpRequestUtil { - - /** - * Set the log state of HttpRequest. Default value is true. - *

- * This configuration will outlast the lifecycle of the Map. - *

- * - * @param enabled True will enable logging, false will disable - */ - public static void setLogEnabled(boolean enabled) { - HTTPRequest.enableLog(enabled); - } - - /** - * Enable printing of the request url when an error occurred. Default value is false. - *

- * Requires {@link #setLogEnabled(boolean)} to be activated. - *

- *

- * This configuration will outlast the lifecycle of the Map. - *

- * - * @param enabled True will print urls, false will disable - */ - public static void setPrintRequestUrlOnFailure(boolean enabled) { - HTTPRequest.enablePrintRequestUrlOnFailure(enabled); - } - - /** - * Set the OkHttpClient used for requesting map resources. - * - * @param client the OkHttpClient - */ - public static void setOkHttpClient(OkHttpClient client) { - HTTPRequest.setOKHttpClient(client); - } - -} \ No newline at end of file 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..eb4a726163 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/NativeHttpRequest.java @@ -0,0 +1,77 @@ +package com.mapbox.mapboxsdk.http; + +import java.util.concurrent.locks.ReentrantLock; + +public class NativeHttpRequest implements HttpRequestResponder { + + private final HttpRequestImpl httpRequestImpl = new HttpRequestImpl(); + + // Reentrancy is not needed, but "Lock" is an abstract class. + private ReentrantLock lock = new ReentrantLock(); + private long nativePtr = 0; + + 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; + } + httpRequestImpl.executeRequest(this, nativePtr, resourceUrl, etag, modified); + } + + public void cancel() { + httpRequestImpl.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(); + } + + private native void nativeOnFailure(int type, String message); + + 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/maps/MapGestureDetector.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java index fc4b13a293..ff9909ef8a 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java @@ -19,14 +19,10 @@ import com.mapbox.android.gestures.RotateGestureDetector; import com.mapbox.android.gestures.ShoveGestureDetector; import com.mapbox.android.gestures.StandardGestureDetector; import com.mapbox.android.gestures.StandardScaleGestureDetector; -import com.mapbox.android.telemetry.Event; -import com.mapbox.android.telemetry.MapEventFactory; -import com.mapbox.android.telemetry.MapState; -import com.mapbox.android.telemetry.MapboxTelemetry; + import com.mapbox.mapboxsdk.R; import com.mapbox.mapboxsdk.camera.CameraPosition; import com.mapbox.mapboxsdk.constants.MapboxConstants; -import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.utils.MathUtils; import java.util.ArrayList; @@ -887,12 +883,12 @@ final class MapGestureDetector { if (cameraPosition != null) { double zoom = cameraPosition.zoom; if (isZoomValid(zoom)) { - MapboxTelemetry telemetry = Telemetry.obtainTelemetry(); - MapEventFactory mapEventFactory = new MapEventFactory(); - LatLng latLng = projection.fromScreenLocation(focalPoint); - MapState state = new MapState(latLng.getLatitude(), latLng.getLongitude(), zoom); - state.setGesture(eventType); - telemetry.push(mapEventFactory.createMapGestureEvent(Event.Type.MAP_CLICK, state)); + //MapboxTelemetry telemetry = Telemetry.obtainTelemetry(); + //MapEventFactory mapEventFactory = new MapEventFactory(); + //LatLng latLng = projection.fromScreenLocation(focalPoint); + //MapState state = new MapState(latLng.getLatitude(), latLng.getLongitude(), zoom); + //state.setGesture(eventType); + //telemetry.push(mapEventFactory.createMapGestureEvent(Event.Type.MAP_CLICK, state)); } } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java index 0fa1072cd2..f70f0e5039 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java @@ -24,11 +24,7 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ZoomButtonsController; import com.mapbox.android.gestures.AndroidGesturesManager; -import com.mapbox.android.telemetry.AppUserTurnstile; -import com.mapbox.android.telemetry.Event; -import com.mapbox.android.telemetry.MapEventFactory; -import com.mapbox.android.telemetry.MapboxTelemetry; -import com.mapbox.mapboxsdk.BuildConfig; + import com.mapbox.mapboxsdk.R; import com.mapbox.mapboxsdk.annotations.Annotation; import com.mapbox.mapboxsdk.annotations.MarkerViewManager; @@ -271,12 +267,12 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback { @UiThread public void onCreate(@Nullable Bundle savedInstanceState) { if (savedInstanceState == null) { - MapboxTelemetry telemetry = Telemetry.obtainTelemetry(); - AppUserTurnstile turnstileEvent = new AppUserTurnstile(BuildConfig.MAPBOX_SDK_IDENTIFIER, - BuildConfig.MAPBOX_SDK_VERSION); - telemetry.push(turnstileEvent); - MapEventFactory mapEventFactory = new MapEventFactory(); - telemetry.push(mapEventFactory.createMapLoadEvent(Event.Type.MAP_LOAD)); + // MapboxTelemetry telemetry = Telemetry.obtainTelemetry(); + // AppUserTurnstile turnstileEvent = new AppUserTurnstile(BuildConfig.MAPBOX_SDK_IDENTIFIER, + // BuildConfig.MAPBOX_SDK_VERSION); + // telemetry.push(turnstileEvent); + // MapEventFactory mapEventFactory = new MapEventFactory(); + // telemetry.push(mapEventFactory.createMapLoadEvent(Event.Type.MAP_LOAD)); } else if (savedInstanceState.getBoolean(MapboxConstants.STATE_HAS_SAVED_STATE)) { this.savedInstanceState = savedInstanceState; } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle index d21eb73382..50660a8c52 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle +++ b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle @@ -54,10 +54,17 @@ android { dependencies { implementation dependenciesList.kotlinLib - api(project(':MapboxGLAndroidSDK')) - implementation dependenciesList.mapboxJavaServices - implementation dependenciesList.mapboxJavaTurf + implementation(project(':MapboxGLAndroidSDK')) { + exclude module: 'MapboxGLAndroidModuleHttp' + } + + implementation(dependenciesList.mapboxJavaTurf) { + exclude group: 'com.squareup.okhttp3', module: 'okhttp' + exclude group: 'com.squareup.okhttp3', module: 'logging-interceptor' + } + + implementation 'com.koushikdutta.ion:ion:2.2.1' implementation dependenciesList.supportAppcompatV7 implementation dependenciesList.supportRecyclerView diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestImpl.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestImpl.java new file mode 100644 index 0000000000..1653e1394e --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/http/HttpRequestImpl.java @@ -0,0 +1,39 @@ +package com.mapbox.mapboxsdk.http; + +import com.koushikdutta.async.future.Future; +import com.koushikdutta.ion.Ion; +import com.koushikdutta.ion.Response; +import com.koushikdutta.ion.builder.Builders; +import com.mapbox.mapboxsdk.Mapbox; + +import java.util.concurrent.ExecutionException; + +public class HttpRequestImpl extends HttpRequest { + + @Override + public void executeRequest(HttpRequestResponder httpRequest, long nativePtr, String resourceUrl, + String etag, String modified) { + Builders.Any.B loadBuilder = Ion.with(Mapbox.getApplicationContext()).load(resourceUrl); + if (etag.length() > 0) { + loadBuilder.addHeader("If-None-Match", etag); + } else if (modified.length() > 0) { + loadBuilder.addHeader("If-Modified-Since", modified); + } + Future> future = loadBuilder.asByteArray().withResponse(); + try { + Response result = future.get(); + int statusCode = result.getHeaders().code(); + httpRequest.onResponse(statusCode, null, null, null, null, null, null, result.getResult()); + } catch (InterruptedException interruptedException) { + interruptedException.printStackTrace(); + } catch (ExecutionException executionException) { + executionException.printStackTrace(); + } + } + + @Override + public void cancelRequest() { + // do nothing + // TODO manage Future objects and execute Future#cancel + } +} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxApplication.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxApplication.java index a06a489388..37b2c9b013 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxApplication.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxApplication.java @@ -3,10 +3,11 @@ package com.mapbox.mapboxsdk.testapp; import android.app.Application; import android.os.StrictMode; import android.text.TextUtils; + import com.mapbox.mapboxsdk.Mapbox; -import com.mapbox.mapboxsdk.maps.Telemetry; import com.mapbox.mapboxsdk.testapp.utils.TokenUtils; import com.squareup.leakcanary.LeakCanary; + import timber.log.Timber; import static timber.log.Timber.DebugTree; @@ -70,7 +71,7 @@ public class MapboxApplication extends Application { String accessToken = TokenUtils.getMapboxAccessToken(getApplicationContext()); validateAccessToken(accessToken); Mapbox.getInstance(getApplicationContext(), accessToken); - Telemetry.updateDebugLoggingEnabled(true); + //Telemetry.updateDebugLoggingEnabled(true); } private static void validateAccessToken(String accessToken) { diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java index ac4c6ff9df..686f564c5c 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java @@ -10,7 +10,6 @@ import com.mapbox.mapboxsdk.annotations.MarkerOptions; import com.mapbox.mapboxsdk.camera.CameraUpdateFactory; import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.geometry.LatLngBounds; -import com.mapbox.mapboxsdk.http.HttpRequestUtil; import com.mapbox.mapboxsdk.maps.MapView; import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.testapp.R; @@ -52,7 +51,6 @@ public class LatLngBoundsActivity extends AppCompatActivity implements View.OnCl @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - HttpRequestUtil.setLogEnabled(false); setContentView(R.layout.activity_latlngbounds); mapView = (MapView) findViewById(R.id.mapView); mapView.onCreate(savedInstanceState); @@ -151,7 +149,6 @@ public class LatLngBoundsActivity extends AppCompatActivity implements View.OnCl protected void onDestroy() { super.onDestroy(); mapView.onDestroy(); - HttpRequestUtil.setLogEnabled(true); } @Override diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DebugModeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DebugModeActivity.java index 44d27a41ab..22da952560 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DebugModeActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DebugModeActivity.java @@ -16,7 +16,6 @@ import android.widget.ListView; import android.widget.TextView; import com.mapbox.mapboxsdk.constants.Style; -import com.mapbox.mapboxsdk.http.HttpRequestUtil; import com.mapbox.mapboxsdk.maps.MapView; import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; @@ -55,7 +54,6 @@ public class DebugModeActivity extends AppCompatActivity implements OnMapReadyCa @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - HttpRequestUtil.setPrintRequestUrlOnFailure(true); setContentView(R.layout.activity_debug_mode); setupToolbar(); setupMapView(savedInstanceState); @@ -206,7 +204,6 @@ public class DebugModeActivity extends AppCompatActivity implements OnMapReadyCa protected void onDestroy() { super.onDestroy(); mapView.onDestroy(); - HttpRequestUtil.setPrintRequestUrlOnFailure(false); } @Override diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/render/RenderTestActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/render/RenderTestActivity.java index e3c5254805..6c37f3d5ea 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/render/RenderTestActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/render/RenderTestActivity.java @@ -12,11 +12,8 @@ import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageView; import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; import com.mapbox.mapboxsdk.snapshotter.MapSnapshotter; -import okio.BufferedSource; -import okio.Okio; + import timber.log.Timber; import java.io.File; @@ -24,7 +21,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.ref.WeakReference; -import java.nio.charset.Charset; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -167,13 +163,13 @@ public class RenderTestActivity extends AppCompatActivity { private static List loadIgnoreList(AssetManager assets) { List ignores = new ArrayList<>(); try (InputStream input = assets.open(String.format("%s/ignores.json", TEST_BASE_PATH))) { - BufferedSource source = Okio.buffer(Okio.source(input)); - String styleJson = source.readByteString().string(Charset.forName("utf-8")); - JsonObject object = new Gson().fromJson(styleJson, JsonObject.class); - for (Map.Entry stringJsonElementEntry : object.entrySet()) { - String[] parts = stringJsonElementEntry.getKey().split("/"); - ignores.add(String.format("%s,%s", parts[2], parts[1])); - } + // BufferedSource source = Okio.buffer(Okio.source(input)); + // String styleJson = source.readByteString().string(Charset.forName("utf-8")); + // JsonObject object = new Gson().fromJson(styleJson, JsonObject.class); + // for (Map.Entry stringJsonElementEntry : object.entrySet()) { + // String[] parts = stringJsonElementEntry.getKey().split("/"); + // ignores.add(String.format("%s,%s", parts[2], parts[1])); + // } } catch (IOException exception) { Timber.e(exception); } @@ -183,8 +179,8 @@ public class RenderTestActivity extends AppCompatActivity { private static String loadStyleJson(AssetManager assets, String category, String test) { String styleJson = null; try (InputStream input = assets.open(String.format("%s/%s/%s/style.json", RENDER_TEST_BASE_PATH, category, test))) { - BufferedSource source = Okio.buffer(Okio.source(input)); - styleJson = source.readByteString().string(Charset.forName("utf-8")); + // BufferedSource source = Okio.buffer(Okio.source(input)); + // styleJson = source.readByteString().string(Charset.forName("utf-8")); } catch (IOException exception) { Timber.e(exception); } diff --git a/platform/android/gradle.properties b/platform/android/gradle.properties new file mode 100644 index 0000000000..77a93829f9 --- /dev/null +++ b/platform/android/gradle.properties @@ -0,0 +1,20 @@ +GROUP=com.mapbox.mapboxsdk +VERSION_NAME=6.4.0-SNAPSHOT + +POM_DESCRIPTION=Mapbox GL Android SDK +POM_URL=https://github.com/mapbox/mapbox-gl-native +POM_SCM_URL=https://github.com/mapbox/mapbox-gl-native +POM_SCM_CONNECTION=scm:git@github.com:mapbox/mapbox-gl-native.git +POM_SCM_DEV_CONNECTION=scm:git@github.com:mapbox/mapbox-gl-native.git +POM_LICENCE_NAME=The Apache Software License, Version 2.0 +POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt +POM_LICENCE_DIST=repo +POM_DEVELOPER_ID=mapbox +POM_DEVELOPER_NAME=Mapbox +POM_NAME=Mapbox Maps SDK for Android +POM_ARTIFACT_ID=mapbox-android-sdk +POM_PACKAGING=aar + +# Only build native dependencies for the current ABI +# See https://code.google.com/p/android/issues/detail?id=221098#c20 +android.buildOnlyTargetAbi=true diff --git a/platform/android/gradle/dependencies.gradle b/platform/android/gradle/dependencies.gradle index fccaea9f71..01b92fe1c6 100644 --- a/platform/android/gradle/dependencies.gradle +++ b/platform/android/gradle/dependencies.gradle @@ -46,6 +46,7 @@ ext { supportAnnotations : "com.android.support:support-annotations:${versions.supportLib}", supportAppcompatV7 : "com.android.support:appcompat-v7:${versions.supportLib}", supportFragmentV4 : "com.android.support:support-fragment:${versions.supportLib}", + supportUtilV4 : "com.android.support:support-core-utils:${versions.supportLib}", supportDesign : "com.android.support:design:${versions.supportLib}", supportRecyclerView : "com.android.support:recyclerview-v7:${versions.supportLib}", diff --git a/platform/android/settings.gradle b/platform/android/settings.gradle index b5ab80b5ec..8aaa9424d4 100644 --- a/platform/android/settings.gradle +++ b/platform/android/settings.gradle @@ -1 +1 @@ -include ':MapboxGLAndroidSDK', ':MapboxGLAndroidSDKTestApp' \ No newline at end of file +include ':MapboxGLAndroidSDK', ':MapboxGLAndroidSDKTestApp', ':MapboxGLAndroidModuleBase', ':MapboxGLAndroidModuleHttp' \ No newline at end of file diff --git a/platform/android/src/http_file_source.cpp b/platform/android/src/http_file_source.cpp index cda84209ea..fc7ffbec8c 100644 --- a/platform/android/src/http_file_source.cpp +++ b/platform/android/src/http_file_source.cpp @@ -20,7 +20,7 @@ public: class HTTPRequest : public AsyncRequest { public: - static constexpr auto Name() { return "com/mapbox/mapboxsdk/http/HTTPRequest"; }; + static constexpr auto Name() { return "com/mapbox/mapboxsdk/http/NativeHttpRequest"; }; HTTPRequest(jni::JNIEnv&, const Resource&, FileSource::Callback); ~HTTPRequest(); -- cgit v1.2.1